--- /dev/null
+diff -Naur --exclude-from=OMIT kernel/bus_driver.c FilterDriver/bus_driver.c\r
+--- kernel/bus_driver.c 2008-07-08 11:28:35.970718400 -0700\r
++++ FilterDriver/bus_driver.c 2008-08-01 12:33:32.531009800 -0700\r
+@@ -27,7 +27,7 @@\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+- * $Id: bus_driver.c 1336 2008-07-07 17:29:40Z shefty $\r
++ * $Id: bus_driver.c 1294 2008-06-21 00:27:03Z stansmith $\r
+ */\r
+ \r
+ \r
+@@ -191,7 +191,8 @@\r
+ * output: pkey_array\r
+ * return: uint16_t number of pkey(s) found\r
+ *************************************************************************************/\r
+-static uint16_t __prepare_pKey_array(IN const UNICODE_STRING *str, OUT uint16_t *pkey_array)\r
++static uint16_t\r
++__prepare_pKey_array(IN const UNICODE_STRING *str, OUT uint16_t *pkey_array)\r
+ {\r
+ uint16_t i, num_pKeys, cur_pkey_length;\r
+ NTSTATUS status;\r
+@@ -320,6 +321,7 @@\r
+ BUS_EXIT( BUS_DBG_DRV );\r
+ return num_pKeys;\r
+ }\r
++\r
+ static NTSTATUS\r
+ __read_registry(\r
+ IN UNICODE_STRING* const p_registry_path )\r
+@@ -440,6 +442,8 @@\r
+ #if DBG\r
+ if( g_al_dbg_flags & AL_DBG_ERR )\r
+ g_al_dbg_flags |= CL_DBG_ERROR;\r
++\r
++ bus_globals.dbg_lvl |= BUS_DBG_DRV | BUS_DBG_PNP;\r
+ #endif\r
+ \r
+ BUS_TRACE(BUS_DBG_DRV ,\r
+@@ -667,7 +671,7 @@\r
+ IN DRIVER_OBJECT *p_driver_obj,\r
+ IN UNICODE_STRING *p_registry_path )\r
+ {\r
+- NTSTATUS status;\r
++ NTSTATUS status;\r
+ \r
+ BUS_ENTER( BUS_DBG_DRV );\r
+ \r
+@@ -707,6 +711,15 @@\r
+ p_driver_obj->DriverUnload = bus_drv_unload;\r
+ p_driver_obj->DriverExtension->AddDevice = bus_add_device;\r
+ \r
++ // Mutex to synchronize multiple threads creating & deleting \r
++ // control deviceobjects. \r
++\r
++ ExInitializeFastMutex(&ControlMutex);\r
++ bfi_InstanceCount = 0;\r
++ memset( __out_bcount(sizeof(bus_filters)) (void*)bus_filters, 0,\r
++ sizeof(bus_filters) );\r
++\r
+ BUS_EXIT( BUS_DBG_DRV );\r
+ return STATUS_SUCCESS;\r
+ }\r
++\r
+diff -Naur --exclude-from=OMIT kernel/bus_driver.h FilterDriver/bus_driver.h\r
+--- kernel/bus_driver.h 2008-08-01 14:47:13.196356800 -0700\r
++++ FilterDriver/bus_driver.h 2008-08-01 14:43:07.886051500 -0700\r
+@@ -27,7 +27,7 @@\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+- * $Id: bus_driver.h 1336 2008-07-07 17:29:40Z shefty $\r
++ * $Id: bus_driver.h 1307 2008-06-29 16:45:16Z leonidk $\r
+ */\r
+ \r
+ \r
+@@ -74,7 +74,12 @@\r
+ CL_TRACE_EXIT( lvl, bus_globals.dbg_lvl, msg )\r
+ \r
+ #define BUS_PRINT( lvl, msg ) \\r
+- CL_PRINT( lvl, bus_globals.dbl_lvl, msg )\r
++ CL_PRINT( lvl, bus_globals.dbg_lvl, msg )\r
++\r
++/* single character Macro elemination */\r
++#define XBUS_PRINT( lvl, msg )\r
++#define XBUS_ENTER( lvl )\r
++#define XBUS_EXIT( lvl )\r
+ \r
+ #define BUS_DBG_ERROR CL_DBG_ERROR\r
+ #define BUS_DBG_DRV (1 << 0)\r
+@@ -93,7 +98,6 @@\r
+ * in the paging, crash dump, or hibernation path.\r
+ */\r
+ \r
+-\r
+ /*\r
+ * Device extension for the device object that serves as entry point for \r
+ * the interface and IOCTL requests.\r
+@@ -112,15 +116,13 @@\r
+ port_mgr_t *p_port_mgr;\r
+ iou_mgr_t *p_iou_mgr;\r
+ \r
+- /* Interface names are generated by IoRegisterDeviceInterface. */\r
+- UNICODE_STRING al_ifc_name;\r
+- UNICODE_STRING ci_ifc_name;\r
+-\r
+ /* Number of references on the upper interface. */\r
+ atomic32_t n_al_ifc_ref;\r
+ /* Number of references on the CI interface. */\r
+ atomic32_t n_ci_ifc_ref;\r
+ \r
++ struct _bus_filter_instance *bus_filter;\r
++\r
+ } bus_fdo_ext_t;\r
+ \r
+ \r
+@@ -174,7 +176,7 @@\r
+ boolean_t b_reported_missing;\r
+ \r
+ /* Flag to control the behaviour of the driver during hibernation */\r
+- uint32_t b_hibernating;\r
++ uint32_t b_hibernating;\r
+ \r
+ /* work item for handling Power Management request */\r
+ PIO_WORKITEM p_po_work_item;\r
+@@ -196,13 +198,62 @@\r
+ /* Driver object. Used for registering of Plug and Play notifications. */\r
+ DRIVER_OBJECT *p_driver_obj;\r
+ \r
+- /* Pointer to the one and only bus root. */\r
+- bus_fdo_ext_t *p_bus_ext;\r
++ /* IBAL PNP event register handles */\r
++ ib_pnp_handle_t h_pnp_port;\r
++ ib_pnp_handle_t h_pnp_iou;\r
+ \r
+ } bus_globals_t;\r
+ \r
+ \r
+ extern bus_globals_t bus_globals;\r
+ \r
++/*\r
++ * Each instance of a bus filter on an HCA device stack (InfiniBandController)\r
++ * populates a bus_filter_t slot in bus_filters[MAX_BUS_FILTERS]; see\r
++ * bus_add_device(). Therefore MAX_BUS_FILTERS represents the MAX number of\r
++ * HCA's supported in a single system.\r
++ */\r
++#define MAX_BUS_FILTERS 16\r
++#define BFI_MAGIC 0xcafebabe\r
++\r
++#define BFI_PORT_MGR_OBJ 1\r
++#define BFI_IOU_MGR_OBJ 2\r
++\r
++\r
++typedef struct _bus_filter_instance\r
++{\r
++ /* Pointer to the bus filter instance FDO extention.\r
++ * if p_bus_ext is NULL, then it's an empty slot available for allocation\r
++ */\r
++ bus_fdo_ext_t *p_bus_ext;\r
++\r
++ /* HCA guid for which this bus filter is servicing */\r
++ ib_net64_t ca_guid;\r
++\r
++ /* PORT management - on a per HCA basis */\r
++ port_mgr_t *p_port_mgr;\r
++ cl_obj_t *p_port_mgr_obj;\r
++\r
++ /* IOU management - on a per HCA basis */\r
++ iou_mgr_t *p_iou_mgr;\r
++ cl_obj_t *p_iou_mgr_obj;\r
++#if DBG\r
++ ULONG magic; // initial/temp debug\r
++ char whoami[8];\r
++#endif\r
++\r
++} bus_filter_t;\r
++\r
++extern bus_filter_t bus_filters[MAX_BUS_FILTERS];\r
++extern ULONG bfi_InstanceCount;\r
++extern FAST_MUTEX ControlMutex; // serializes InstanceCount & bus_filters\r
++\r
++extern bus_filter_t *alloc_bfi( IN DRIVER_OBJECT *, OUT int * );\r
++extern int free_bfi( IN bus_filter_t *p_bfi );\r
++extern int get_bfi_count( void );\r
++extern bus_filter_t *get_bfi_by_obj( IN int obj_type, IN cl_obj_t *p_obj );\r
++extern bus_filter_t *get_bfi_by_ca_guid( IN net64_t ca_guid );\r
++extern bus_filter_t *get_set_bfi_by_ca_guid( IN net64_t ca_guid );\r
++extern char *get_obj_state_str(cl_state_t state);\r
+ \r
+ #endif /* !defined _BUS_DRIVER_H_ */\r
+diff -Naur --exclude-from=OMIT kernel/bus_iou_mgr.c FilterDriver/bus_iou_mgr.c\r
+--- kernel/bus_iou_mgr.c 2008-04-04 15:31:40.247102400 -0700\r
++++ FilterDriver/bus_iou_mgr.c 2008-08-01 14:40:07.673696300 -0700\r
+@@ -83,7 +83,12 @@\r
+ } bus_iou_ext_t;\r
+ \r
+ \r
+-iou_mgr_t* gp_iou_mgr = NULL;\r
++typedef struct _iou_pnp_context\r
++{\r
++ bus_filter_t *p_bus_filter;\r
++ void *p_pdo_ext;\r
++\r
++} iou_pnp_ctx_t;\r
+ \r
+ \r
+ /*\r
+@@ -98,7 +103,8 @@\r
+ IN cl_obj_t* p_obj );\r
+ \r
+ ib_api_status_t\r
+-bus_reg_iou_pnp( void );\r
++bus_reg_iou_pnp(\r
++ IN bus_filter_t* p_bfi );\r
+ \r
+ ib_api_status_t\r
+ iou_mgr_pnp_cb(\r
+@@ -278,25 +284,29 @@\r
+ */\r
+ ib_api_status_t\r
+ create_iou_mgr(\r
++ IN bus_filter_t* p_bfi,\r
+ OUT iou_mgr_t** const pp_iou_mgr )\r
+ {\r
+ ib_api_status_t status;\r
+ cl_status_t cl_status;\r
++ iou_mgr_t *gp_iou_mgr;\r
+ \r
+ BUS_ENTER( BUS_DBG_PNP );\r
+ \r
+- CL_ASSERT( !gp_iou_mgr );\r
++ CL_ASSERT( p_bfi->p_iou_mgr == NULL );\r
+ \r
+ gp_iou_mgr = cl_zalloc( sizeof(iou_mgr_t) );\r
+ if( !gp_iou_mgr )\r
+ {\r
+ BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
+- ("Failed to allocate port manager.\n") );\r
++ ("Failed to allocate IOU manager.\n") );\r
+ return IB_INSUFFICIENT_MEMORY;\r
+ }\r
++ p_bfi->p_iou_mgr = gp_iou_mgr;\r
+ \r
+ /* Construct the load service. */\r
+ cl_obj_construct( &gp_iou_mgr->obj, AL_OBJ_TYPE_LOADER );\r
++ p_bfi->p_iou_mgr_obj = &p_bfi->p_iou_mgr->obj; // save for destroy & free\r
+ cl_mutex_construct( &gp_iou_mgr->pdo_mutex );\r
+ cl_qlist_init( &gp_iou_mgr->iou_list );\r
+ \r
+@@ -311,7 +321,7 @@\r
+ \r
+ /* Initialize the load service object. */\r
+ cl_status = cl_obj_init( &gp_iou_mgr->obj, CL_DESTROY_SYNC,\r
+- destroying_iou_mgr, NULL, free_iou_mgr );\r
++ destroying_iou_mgr, NULL, free_iou_mgr );\r
+ if( cl_status != CL_SUCCESS )\r
+ {\r
+ free_iou_mgr( &gp_iou_mgr->obj );\r
+@@ -320,11 +330,12 @@\r
+ return ib_convert_cl_status( cl_status );\r
+ }\r
+ \r
+- /* Register for port PnP events. */\r
+- status = bus_reg_iou_pnp();\r
++ /* Register for IOU PnP events. */\r
++ status = bus_reg_iou_pnp( p_bfi );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+- cl_obj_destroy( &gp_iou_mgr->obj );\r
++// cl_obj_destroy( &gp_iou_mgr->obj );\r
++ free_iou_mgr( &gp_iou_mgr->obj );\r
+ BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
+ ("bus_reg_iou_pnp returned %s.\n", ib_get_err_str(status)) );\r
+ return status;\r
+@@ -337,6 +348,26 @@\r
+ }\r
+ \r
+ \r
++void\r
++destroy_iou_mgr_cb( IN void *context )\r
++{\r
++ iou_pnp_ctx_t *p_ctx = context;\r
++ bus_filter_t *p_bfi;\r
++\r
++ CL_ASSERT( p_ctx );\r
++ CL_ASSERT( p_ctx->p_bus_filter->magic == BFI_MAGIC );\r
++\r
++ p_bfi = p_ctx->p_bus_filter;\r
++ BUS_PRINT(BUS_DBG_PNP, ("%s() Enter: obj %p?\n", __FUNCTION__,\r
++ p_bfi->p_iou_mgr_obj));\r
++\r
++ cl_obj_deref( p_bfi->p_iou_mgr_obj );\r
++ \r
++ BUS_PRINT(BUS_DBG_PNP, ("%s() Exit: obj %p?\n", __FUNCTION__,\r
++ p_bfi->p_iou_mgr_obj));\r
++}\r
++\r
++\r
+ /*\r
+ * Pre-destroy the load service.\r
+ */\r
+@@ -345,20 +376,34 @@\r
+ IN cl_obj_t* p_obj )\r
+ {\r
+ ib_api_status_t status;\r
++ bus_filter_t *p_bfi;\r
++ iou_mgr_t *gp_iou_mgr;\r
+ \r
+ BUS_ENTER( BUS_DBG_PNP );\r
+ \r
+ CL_ASSERT( p_obj );\r
++ p_bfi = get_bfi_by_obj( BFI_IOU_MGR_OBJ, p_obj );\r
++ if (p_bfi == NULL) {\r
++ BUS_PRINT(BUS_DBG_PNP, ("%s() failed to find p_bfi by obj %p?\n",\r
++ __FUNCTION__,p_obj));\r
++ return;\r
++ }\r
++ gp_iou_mgr = p_bfi->p_iou_mgr;\r
++\r
++ BUS_PRINT(BUS_DBG_PNP, ("%s(%s) obj %p port_mgr %p\n",\r
++ __FUNCTION__, p_bfi->whoami, p_obj, gp_iou_mgr));\r
++\r
+ CL_ASSERT( gp_iou_mgr == PARENT_STRUCT( p_obj, iou_mgr_t, obj ) );\r
+- UNUSED_PARAM( p_obj );\r
+ \r
+- /* Deregister for port PnP events. */\r
+- if( gp_iou_mgr->h_pnp )\r
++ /* Deregister for iou PnP events. */\r
++ if( get_bfi_count() == 1 && bus_globals.h_pnp_iou )\r
+ {\r
+- status = ib_dereg_pnp( gp_iou_mgr->h_pnp,\r
+- (ib_pfn_destroy_cb_t)cl_obj_deref );\r
++ status = ib_dereg_pnp( bus_globals.h_pnp_iou, NULL );\r
++ bus_globals.h_pnp_iou = NULL;\r
+ CL_ASSERT( status == IB_SUCCESS );\r
+ }\r
++ cl_obj_deref( p_bfi->p_iou_mgr_obj );\r
++\r
+ BUS_EXIT( BUS_DBG_PNP );\r
+ }\r
+ \r
+@@ -372,14 +417,30 @@\r
+ {\r
+ bus_pdo_ext_t *p_ext;\r
+ cl_list_item_t *p_list_item;\r
++ bus_filter_t *p_bfi;\r
++ iou_mgr_t *gp_iou_mgr;\r
+ \r
+ BUS_ENTER( BUS_DBG_PNP );\r
+ \r
+ CL_ASSERT( p_obj );\r
++ p_bfi = get_bfi_by_obj( BFI_IOU_MGR_OBJ, p_obj );\r
++ if ( p_bfi == NULL ) {\r
++ BUS_PRINT( BUS_DBG_PNP, ("%s: unable to get p_bfi iou_obj %p?\n",\r
++ __FUNCTION__,p_obj) );\r
++ return;\r
++ }\r
++ gp_iou_mgr = p_bfi->p_iou_mgr;\r
++ if ( !gp_iou_mgr ) {\r
++ // if create fails & then free is called, p_bfi->p_iou_mgr == NULL\r
++ return;\r
++ }\r
++\r
+ CL_ASSERT( gp_iou_mgr == PARENT_STRUCT( p_obj, iou_mgr_t, obj ) );\r
+ \r
++ BUS_PRINT( BUS_DBG_PNP, ("%s(%s) Mark all IOU PDOs as no longer present\n",\r
++ __FUNCTION__, p_bfi->whoami));\r
+ /*\r
+- * Mark all IPoIB PDOs as no longer present. This will cause them\r
++ * Mark all IOU PDOs as no longer present. This will cause them\r
+ * to be removed when they process the IRP_MN_REMOVE_DEVICE.\r
+ */\r
+ p_list_item = cl_qlist_remove_head( &gp_iou_mgr->iou_list );\r
+@@ -391,8 +452,10 @@\r
+ {\r
+ CL_ASSERT( !p_ext->b_present );\r
+ p_ext->b_reported_missing = TRUE;\r
+- BUS_TRACE( BUS_DBG_PNP, ("%s: ext %p, present %d, missing %d .\n",\r
+- p_ext->cl_ext.vfptr_pnp_po->identity, p_ext, p_ext->b_present, p_ext->b_reported_missing ) );\r
++ BUS_TRACE( BUS_DBG_PNP, ("%s %s: ext %p, present %d, missing %d\n",\r
++ p_bfi->whoami,\r
++ p_ext->cl_ext.vfptr_pnp_po->identity, p_ext,\r
++ p_ext->b_present, p_ext->b_reported_missing ) );\r
+ continue;\r
+ }\r
+ if( p_ext->h_ca )\r
+@@ -404,13 +467,25 @@\r
+ /* Release the reference on the CA object. */\r
+ deref_al_obj( &p_ext->h_ca->obj );\r
+ }\r
++ BUS_TRACE( BUS_DBG_PNP, ("Deleted device %s %s: PDO %p, ext %p\n",\r
++ p_bfi->whoami, p_ext->cl_ext.vfptr_pnp_po->identity,\r
++ p_ext->cl_ext.p_self_do, p_ext ) );\r
++\r
++ BUS_TRACE( BUS_DBG_PNP,("%s(%s) p_ext->h_ca->obj.state %d ref_cnt %d\n",\r
++ __FUNCTION__, p_bfi->whoami,\r
++ p_ext->h_ca->obj.state,\r
++ p_ext->h_ca->obj.ref_cnt));//XXX\r
++\r
+ IoDeleteDevice( p_ext->cl_ext.p_self_do );\r
+ }\r
+ \r
+ cl_mutex_destroy( &gp_iou_mgr->pdo_mutex );\r
+ cl_obj_deinit( p_obj );\r
+ cl_free( gp_iou_mgr );\r
+- gp_iou_mgr = NULL;\r
++\r
++ p_bfi->p_iou_mgr = NULL;\r
++ p_bfi->p_iou_mgr_obj = NULL;\r
++\r
+ BUS_EXIT( BUS_DBG_PNP );\r
+ }\r
+ \r
+@@ -419,22 +494,24 @@\r
+ * Register the load service for the given PnP class events.\r
+ */\r
+ ib_api_status_t\r
+-bus_reg_iou_pnp( void )\r
++bus_reg_iou_pnp( IN bus_filter_t *p_bfi )\r
+ {\r
+ ib_pnp_req_t pnp_req;\r
+- ib_api_status_t status;\r
++ ib_api_status_t status = IB_SUCCESS;\r
+ \r
+- cl_memclr( &pnp_req, sizeof( ib_pnp_req_t ) );\r
+- pnp_req.pnp_class = IB_PNP_IOU | IB_PNP_FLAG_REG_SYNC;\r
+- pnp_req.pnp_context = gp_iou_mgr;\r
+- pnp_req.pfn_pnp_cb = iou_mgr_pnp_cb;\r
++ /* only need to register for PNP once */\r
++ if ( get_bfi_count() == 1 ) {\r
++ cl_memclr( &pnp_req, sizeof( ib_pnp_req_t ) );\r
++ pnp_req.pnp_class = IB_PNP_IOU | IB_PNP_FLAG_REG_SYNC;\r
++ pnp_req.pnp_context = NULL;\r
++ pnp_req.pfn_pnp_cb = iou_mgr_pnp_cb;\r
+ \r
+- status = ib_reg_pnp( gh_al, &pnp_req, &gp_iou_mgr->h_pnp );\r
++ status = ib_reg_pnp( gh_al, &pnp_req, &bus_globals.h_pnp_iou );\r
++ }\r
+ \r
+- if( status == IB_SUCCESS )\r
+- {\r
++ if( status == IB_SUCCESS ) {\r
+ /* Reference the load service on behalf of the ib_reg_pnp call. */\r
+- cl_obj_ref( &gp_iou_mgr->obj );\r
++ cl_obj_ref( &p_bfi->p_iou_mgr->obj );\r
+ }\r
+ \r
+ return status;\r
+@@ -448,12 +525,11 @@\r
+ iou_mgr_pnp_cb(\r
+ IN ib_pnp_rec_t* p_pnp_rec )\r
+ {\r
+- ib_api_status_t status;\r
++ ib_api_status_t status=IB_SUCCESS;\r
+ \r
+ BUS_ENTER( BUS_DBG_PNP );\r
+ \r
+ CL_ASSERT( p_pnp_rec );\r
+- CL_ASSERT( gp_iou_mgr == p_pnp_rec->pnp_context );\r
+ \r
+ switch( p_pnp_rec->pnp_event )\r
+ {\r
+@@ -463,9 +539,11 @@\r
+ \r
+ case IB_PNP_IOU_REMOVE:\r
+ iou_mgr_iou_remove( (ib_pnp_iou_rec_t*)p_pnp_rec );\r
++ break;\r
+ \r
+ default:\r
+- status = IB_SUCCESS;\r
++ BUS_PRINT( BUS_DBG_PNP, ("%s() Unhandled PNP Event %s\n",\r
++ __FUNCTION__, ib_get_pnp_event_str(p_pnp_rec->pnp_event) ));\r
+ break;\r
+ }\r
+ BUS_EXIT( BUS_DBG_PNP );\r
+@@ -482,9 +560,47 @@\r
+ IN IRP* const p_irp )\r
+ {\r
+ NTSTATUS status;\r
++ bus_filter_t *p_bfi;\r
++ iou_mgr_t *gp_iou_mgr;\r
++ DEVICE_RELATIONS *p_rel;\r
+ \r
+ BUS_ENTER( BUS_DBG_PNP );\r
+ \r
++ BUS_PRINT(BUS_DBG_PNP, ("%s() ca_guid %I64x\n",__FUNCTION__,ca_guid));\r
++\r
++ /* special case guid == 0 - walk all bus filter instances */\r
++ if ( ca_guid == 0ULL ) {\r
++ for(p_bfi=bus_filters; p_bfi < &bus_filters[MAX_BUS_FILTERS]; p_bfi++) {\r
++ gp_iou_mgr = p_bfi->p_iou_mgr;\r
++ if ( !gp_iou_mgr )\r
++ continue;\r
++ cl_mutex_acquire( &gp_iou_mgr->pdo_mutex );\r
++ status = bus_get_relations( &gp_iou_mgr->iou_list, ca_guid, p_irp );\r
++ cl_mutex_release( &gp_iou_mgr->pdo_mutex );\r
++ }\r
++ p_rel = (DEVICE_RELATIONS*)p_irp->IoStatus.Information;\r
++ if ( p_rel ) {\r
++ BUS_PRINT(BUS_DBG_PNP, ("%s() ca_guid 0 Reports %d\n",\r
++ __FUNCTION__,p_rel->Count));\r
++ }\r
++ BUS_EXIT( BUS_DBG_PNP );\r
++ return STATUS_SUCCESS;\r
++ }\r
++\r
++ p_bfi = get_bfi_by_ca_guid(ca_guid);\r
++ if (p_bfi == NULL) {\r
++ BUS_PRINT(BUS_DBG_PNP,\r
++ ("%s() Null p_bfi from ca_guid %I64x ?\n",__FUNCTION__,ca_guid));\r
++ BUS_EXIT( BUS_DBG_PNP );\r
++ return STATUS_UNSUCCESSFUL;\r
++ }\r
++ gp_iou_mgr = p_bfi->p_iou_mgr;\r
++\r
++ BUS_PRINT(BUS_DBG_PNP, ("%s(%s) for ca_guid %I64x iou_mgr %p\n",\r
++ __FUNCTION__, p_bfi->whoami, ca_guid, gp_iou_mgr) );\r
++ if (!gp_iou_mgr)\r
++ return STATUS_NO_SUCH_DEVICE;\r
++\r
+ cl_mutex_acquire( &gp_iou_mgr->pdo_mutex );\r
+ status = bus_get_relations( &gp_iou_mgr->iou_list, ca_guid, p_irp );\r
+ cl_mutex_release( &gp_iou_mgr->pdo_mutex );\r
+@@ -496,14 +612,17 @@\r
+ \r
+ static ib_api_status_t\r
+ __iou_was_hibernated(\r
+- IN ib_pnp_iou_rec_t* p_pnp_rec )\r
++ IN ib_pnp_iou_rec_t* p_pnp_rec,\r
++ IN bus_filter_t* p_bfi )\r
+ {\r
+ NTSTATUS status;\r
+- cl_list_item_t *p_list_item;\r
+- bus_iou_ext_t *p_iou_ext;\r
++ cl_list_item_t *p_list_item;\r
++ bus_iou_ext_t *p_iou_ext;\r
+ bus_pdo_ext_t *p_pdo_ext = NULL;\r
+ size_t n_devs = 0;\r
++ iou_mgr_t *gp_iou_mgr = p_bfi->p_iou_mgr;\r
+ cl_qlist_t* p_pdo_list = &gp_iou_mgr->iou_list;\r
++ iou_pnp_ctx_t *p_ctx = p_pnp_rec->pnp_rec.context;\r
+ \r
+ BUS_ENTER( BUS_DBG_PNP );\r
+ \r
+@@ -525,9 +644,11 @@\r
+ break;\r
+ }\r
+ \r
+- BUS_TRACE( BUS_DBG_PNP, \r
+- ("Skipped PDO for %s: PDO %p, ext %p, present %d, missing %d, hibernating %d, port_guid %I64x.\n",\r
+- p_pdo_ext->cl_ext.vfptr_pnp_po->identity, p_pdo_ext->cl_ext.p_self_do, \r
++ BUS_TRACE( BUS_DBG_PNP, ("%s Skipped PDO for %s: PDO %p, ext %p, "\r
++ "present %d, missing %d, hibernating %d, port_guid %I64x.\n",\r
++ p_bfi->whoami,\r
++ p_pdo_ext->cl_ext.vfptr_pnp_po->identity,\r
++ p_pdo_ext->cl_ext.p_self_do, \r
+ p_pdo_ext, p_pdo_ext->b_present, p_pdo_ext->b_reported_missing, \r
+ p_pdo_ext->b_hibernating, p_iou_ext->guid ) );\r
+ }\r
+@@ -545,20 +666,23 @@\r
+ else \r
+ {\r
+ p_pdo_ext->b_hibernating = FALSE;\r
+- p_pnp_rec->pnp_rec.context = p_pdo_ext;\r
++ p_ctx->p_pdo_ext = p_pdo_ext; // for iou_mgr_iou_remove()\r
++\r
+ status = IB_SUCCESS;\r
+ p_iou_ext = (bus_iou_ext_t*)p_pdo_ext;\r
+- BUS_TRACE( BUS_DBG_PNP, \r
+- ("Found PDO for %s: PDO %p, ext %p, present %d, missing %d, hibernating %d, port_guid %I64x.\n",\r
+- p_pdo_ext->cl_ext.vfptr_pnp_po->identity, p_pdo_ext->cl_ext.p_self_do, \r
++ BUS_TRACE( BUS_DBG_PNP, ("%s Found PDO for %s: PDO %p, ext %p, "\r
++ "present %d, missing %d, hibernating %d, port_guid %I64x.\n",\r
++ p_bfi->whoami,\r
++ p_pdo_ext->cl_ext.vfptr_pnp_po->identity,\r
++ p_pdo_ext->cl_ext.p_self_do, \r
+ p_pdo_ext, p_pdo_ext->b_present, p_pdo_ext->b_reported_missing, \r
+ p_pdo_ext->b_hibernating, p_iou_ext->guid ) );\r
+ }\r
+ }\r
+ else \r
+ {\r
+- BUS_TRACE( BUS_DBG_PNP, ("Failed to find PDO for guid %I64x .\n",\r
+- p_pnp_rec->pnp_rec.guid ) );\r
++ BUS_TRACE( BUS_DBG_PNP, ("%s Failed to find PDO for guid %I64x .\n",\r
++ p_bfi->whoami, p_pnp_rec->pnp_rec.guid ) );\r
+ status = IB_NOT_FOUND;\r
+ }\r
+ \r
+@@ -575,13 +699,48 @@\r
+ NTSTATUS status;\r
+ DEVICE_OBJECT *p_pdo;\r
+ bus_iou_ext_t *p_iou_ext;\r
++ bus_filter_t *p_bfi;\r
++ iou_mgr_t *gp_iou_mgr;\r
++ iou_pnp_ctx_t *p_ctx = p_pnp_rec->pnp_rec.context;\r
+ \r
+ BUS_ENTER( BUS_DBG_PNP );\r
+ \r
+- /* Upon hibernating of the computer IB_BUS driver doesn't remove PDO, but\r
++ p_bfi = get_set_bfi_by_ca_guid( p_pnp_rec->ca_guid );\r
++ if ( !p_bfi ) {\r
++ BUS_PRINT( BUS_DBG_PNP,("%s() NULL p_bfi? ca_guid 0x%I64x\n",\r
++ __FUNCTION__, p_pnp_rec->ca_guid ) );\r
++ return IB_ERROR;\r
++ }\r
++\r
++ if ( !p_ctx ) {\r
++ /*\r
++ * Allocate a PNP context for this object. pnp_rec.context is object\r
++ * unique.\r
++ */\r
++ p_ctx = cl_zalloc( sizeof(*p_ctx) );\r
++ if( !p_ctx )\r
++ {\r
++ BUS_PRINT(BUS_DBG_PNP, ("%s(%s) ca_guid 0x%I64x iou_guid(%I64x) "\r
++ "BAD alloc for PNP context\n", __FUNCTION__,\r
++ p_bfi->whoami, p_bfi->ca_guid, p_pnp_rec->guid ));\r
++\r
++ return IB_ERROR;\r
++ }\r
++ p_ctx->p_bus_filter = p_bfi;\r
++ p_pnp_rec->pnp_rec.context = p_ctx;\r
++\r
++ BUS_PRINT(BUS_DBG_PNP,\r
++ ("%s(%s) ca_guid %I64x iou_guid(%I64x) ALLOC p_ctx @ %p\n",\r
++ __FUNCTION__, p_bfi->whoami, p_bfi->ca_guid, \r
++ p_pnp_rec->guid,p_ctx));\r
++ }\r
++ gp_iou_mgr = p_bfi->p_iou_mgr;\r
++\r
++ /* Upon hibernating the computer IB_BUS driver doesn't remove PDO, but\r
+ marks with a flag. So we first try to find an existing PDO for this port,\r
+- marked with this flag. If it was found, we turn off the flag and use this PDO */\r
+- status = __iou_was_hibernated(p_pnp_rec);\r
++ marked with this flag. If it was found, we turn off the flag and use\r
++ this PDO */\r
++ status = __iou_was_hibernated( p_pnp_rec, p_bfi );\r
+ if( status != IB_NOT_FOUND )\r
+ {\r
+ BUS_EXIT( BUS_DBG_PNP );\r
+@@ -590,9 +749,11 @@\r
+ \r
+ /* Create the PDO for the new port device. */\r
+ status = IoCreateDevice( bus_globals.p_driver_obj, sizeof(bus_iou_ext_t),\r
+- NULL, FILE_DEVICE_CONTROLLER, \r
+- FILE_DEVICE_SECURE_OPEN | FILE_AUTOGENERATED_DEVICE_NAME,\r
+- FALSE, &p_pdo );\r
++ NULL, FILE_DEVICE_CONTROLLER, \r
++ FILE_DEVICE_SECURE_OPEN |\r
++ FILE_AUTOGENERATED_DEVICE_NAME,\r
++ FALSE, &p_pdo );\r
++\r
+ if( !NT_SUCCESS( status ) )\r
+ {\r
+ BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
+@@ -602,18 +763,19 @@\r
+ \r
+ /* Initialize the device extension. */\r
+ cl_init_pnp_po_ext( p_pdo, NULL, p_pdo, bus_globals.dbg_lvl,\r
+- &vfptr_iou_pnp, &vfptr_iou_query_txt );\r
++ &vfptr_iou_pnp, &vfptr_iou_query_txt );\r
+ \r
+ /* Set the DO_BUS_ENUMERATED_DEVICE flag to mark it as a PDO. */\r
+ p_pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;\r
+ \r
+ p_iou_ext = p_pdo->DeviceExtension;\r
+ p_iou_ext->pdo.dev_po_state.DeviceState = PowerDeviceD0;\r
+- p_iou_ext->pdo.p_parent_ext = bus_globals.p_bus_ext;\r
++ p_iou_ext->pdo.p_parent_ext = p_bfi->p_bus_ext;\r
+ p_iou_ext->pdo.b_present = TRUE;\r
+ p_iou_ext->pdo.b_reported_missing = FALSE;\r
+ BUS_TRACE( BUS_DBG_PNP, ("%s: ext %p, present %d, missing %d .\n",\r
+- p_iou_ext->pdo.cl_ext.vfptr_pnp_po->identity, p_iou_ext, p_iou_ext->pdo.b_present, p_iou_ext->pdo.b_reported_missing ) );\r
++ p_iou_ext->pdo.cl_ext.vfptr_pnp_po->identity, p_iou_ext,\r
++ p_iou_ext->pdo.b_present, p_iou_ext->pdo.b_reported_missing ) );\r
+ \r
+ p_iou_ext->guid = p_pnp_rec->guid;\r
+ p_iou_ext->chassis_guid = p_pnp_rec->chassis_guid;\r
+@@ -626,6 +788,7 @@\r
+ p_iou_ext->revision = cl_ntoh32( p_pnp_rec->revision );\r
+ cl_memcpy( p_iou_ext->desc, p_pnp_rec->desc,\r
+ IB_NODE_DESCRIPTION_SIZE + 1 );\r
++ p_iou_ext->n_ifc_ref = 0;\r
+ \r
+ /* Cache the CA GUID. */\r
+ p_iou_ext->pdo.ca_guid = p_pnp_rec->ca_guid;\r
+@@ -641,23 +804,26 @@\r
+ \r
+ /* Store the device extension in the PDO list for future queries. */\r
+ cl_mutex_acquire( &gp_iou_mgr->pdo_mutex );\r
+- cl_qlist_insert_tail( &gp_iou_mgr->iou_list,\r
+- &p_iou_ext->pdo.list_item );\r
++ cl_qlist_insert_tail( &gp_iou_mgr->iou_list, &p_iou_ext->pdo.list_item );\r
+ cl_mutex_release( &gp_iou_mgr->pdo_mutex );\r
+ \r
+ /*\r
+ * Set the context of the PNP event. The context is passed in for future\r
+ * events on the same port.\r
+ */\r
+- p_pnp_rec->pnp_rec.context = p_iou_ext;\r
++ /* if not set in iou_was_hibernated(), set now */\r
++ if ( !p_ctx->p_pdo_ext )\r
++ p_ctx->p_pdo_ext = p_iou_ext;\r
+ \r
+ /* Tell the PnP Manager to rescan for the HCA's bus relations. */\r
+ IoInvalidateDeviceRelations(\r
+- p_iou_ext->pdo.h_ca->obj.p_ci_ca->verbs.p_hca_dev, BusRelations );\r
++ p_iou_ext->pdo.h_ca->obj.p_ci_ca->verbs.p_hca_dev, BusRelations );\r
+ \r
++#if 0 // XXX\r
+ /* Invalidate removal relations for the bus driver. */\r
+ IoInvalidateDeviceRelations(\r
+- bus_globals.p_bus_ext->cl_ext.p_pdo, RemovalRelations );\r
++ p_bfi->p_bus_ext->cl_ext.p_pdo, RemovalRelations );\r
++#endif\r
+ \r
+ BUS_EXIT( BUS_DBG_PNP );\r
+ \r
+@@ -670,13 +836,50 @@\r
+ IN ib_pnp_iou_rec_t* p_pnp_rec )\r
+ {\r
+ bus_pdo_ext_t *p_ext;\r
++ iou_mgr_t *gp_iou_mgr;\r
++ bus_filter_t *p_bfi;\r
++ iou_pnp_ctx_t *p_ctx = p_pnp_rec->pnp_rec.context;\r
+ \r
+ BUS_ENTER( BUS_DBG_PNP );\r
+ \r
+- /* The PNP record's context is the port extension. */\r
+- p_ext = p_pnp_rec->pnp_rec.context;\r
++ if ( !p_ctx ) {\r
++ BUS_EXIT( BUS_DBG_PNP );\r
++ return;\r
++ }\r
++\r
++ CL_ASSERT( p_ctx->p_bus_filter->magic == BFI_MAGIC );\r
++ p_bfi = p_ctx->p_bus_filter;\r
++ CL_ASSERT( p_bfi );\r
++\r
++ BUS_PRINT(BUS_DBG_PNP,("%s(%s) ca_guid 0x%I64x iou_mgr %p\n",\r
++ __FUNCTION__, p_bfi->whoami, p_bfi->ca_guid, p_bfi->p_iou_mgr));\r
++\r
++ /* fdo_release_resources() has destroyed the IOU mgr, all that needs to be\r
++ * done is cleanup the PNP IOU context; one per port.\r
++ */\r
++ if ( p_bfi->ca_guid == 0ULL || !p_bfi->p_iou_mgr ) {\r
++ cl_free( p_ctx );\r
++ p_pnp_rec->pnp_rec.context = NULL;\r
++ BUS_EXIT( BUS_DBG_PNP );\r
++ return;\r
++ }\r
++\r
++ gp_iou_mgr = p_bfi->p_iou_mgr;\r
++\r
++ /* Within the Bus fabric instance is the port extension; see\r
++ * was_hibernated().\r
++ */\r
++ p_ext = p_ctx->p_pdo_ext;\r
+ CL_ASSERT( p_ext );\r
+ \r
++ if (p_bfi != p_ext->p_parent_ext->bus_filter) {\r
++ BUS_PRINT(BUS_DBG_PNP,\r
++ ("%s() p_bfi(%p) != p_ext->bus_filter(%p) line %d file %s\n",\r
++ __FUNCTION__,p_bfi,p_ext->p_parent_ext->bus_filter,\r
++ __LINE__,__FILE__));\r
++ CL_ASSERT (p_bfi == p_ext->p_parent_ext->bus_filter);\r
++ }\r
++\r
+ /*\r
+ * Flag the port PDO as no longer being present. We have to wait until\r
+ * the PnP manager removes it to clean up. However, we do release the\r
+@@ -684,31 +887,48 @@\r
+ * to proceed should it occur before the port's PDO is cleaned up.\r
+ */\r
+ cl_mutex_acquire( &gp_iou_mgr->pdo_mutex );\r
+- CL_ASSERT( p_ext->h_ca );\r
++ if ( !p_ext->h_ca )\r
++ {\r
++ BUS_TRACE( BUS_DBG_PNP, ("%s() NULL h_ca? p_ext %p\n",\r
++ __FUNCTION__, p_ext ) );\r
++ return;\r
++ }\r
+ \r
+ if( p_ext->b_hibernating )\r
+ {\r
+- BUS_TRACE( BUS_DBG_PNP, ("Skip port removing for %s: PDO %p, ext %p, present %d, missing %d, hibernating %d .\n",\r
+- p_ext->cl_ext.vfptr_pnp_po->identity, p_ext->cl_ext.p_self_do, p_ext, p_ext->b_present, \r
++ BUS_TRACE( BUS_DBG_PNP, ("%s Skip port removing for %s: PDO %p ext %p "\r
++ "present %d missing %d hibernating %d\n",\r
++ p_bfi->whoami,\r
++ p_ext->cl_ext.vfptr_pnp_po->identity, p_ext->cl_ext.p_self_do,\r
++ p_ext, p_ext->b_present, \r
+ p_ext->b_reported_missing, p_ext->b_hibernating ) );\r
+ goto hca_deref;\r
+ }\r
+ \r
+ p_ext->b_present = FALSE;\r
+- BUS_TRACE( BUS_DBG_PNP, ("%s: ext %p, present %d, missing %d .\n",\r
+- p_ext->cl_ext.vfptr_pnp_po->identity, p_ext, p_ext->b_present, p_ext->b_reported_missing ) );\r
++ p_ext->b_reported_missing = TRUE;\r
++\r
++ BUS_TRACE( BUS_DBG_PNP, ("%s %s: ext %p, present %d, missing %d .\n",\r
++ p_bfi->whoami,\r
++ p_ext->cl_ext.vfptr_pnp_po->identity, p_ext, p_ext->b_present,\r
++ p_ext->b_reported_missing ) );\r
+ \r
++#if 0 // XXX\r
+ /* Invalidate removal relations for the bus driver. */\r
+- IoInvalidateDeviceRelations( bus_globals.p_bus_ext->cl_ext.p_pdo,\r
+- RemovalRelations );\r
++ IoInvalidateDeviceRelations( p_bfi->p_bus_ext->cl_ext.p_pdo,\r
++ RemovalRelations );\r
++#endif\r
+ \r
+ /* Invalidate bus relations for the HCA. */\r
+ IoInvalidateDeviceRelations(\r
+ p_ext->h_ca->obj.p_ci_ca->verbs.p_hca_dev, BusRelations );\r
+ \r
++ /* free PNP context */\r
++ cl_free( p_ctx );\r
++ p_pnp_rec->pnp_rec.context = NULL;\r
++\r
+ hca_deref:\r
+ deref_al_obj( &p_ext->h_ca->obj );\r
+- p_ext->h_ca = NULL;\r
+ cl_mutex_release( &gp_iou_mgr->pdo_mutex );\r
+ \r
+ BUS_EXIT( BUS_DBG_PNP );\r
+@@ -778,10 +998,12 @@\r
+ {\r
+ bus_iou_ext_t *p_ext;\r
+ POWER_STATE po_state;\r
++ iou_mgr_t *gp_iou_mgr;\r
+ \r
+ BUS_ENTER( BUS_DBG_PNP );\r
+ \r
+ p_ext = p_dev_obj->DeviceExtension;\r
++ gp_iou_mgr = p_ext->pdo.p_parent_ext->bus_filter->p_iou_mgr;\r
+ \r
+ /* Remove this PDO from its list. */\r
+ cl_mutex_acquire( &gp_iou_mgr->pdo_mutex );\r
+diff -Naur --exclude-from=OMIT kernel/bus_iou_mgr.h FilterDriver/bus_iou_mgr.h\r
+--- kernel/bus_iou_mgr.h 2008-07-08 11:28:35.940675200 -0700\r
++++ FilterDriver/bus_iou_mgr.h 2008-07-24 11:03:33.255011800 -0700\r
+@@ -27,7 +27,7 @@\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+- * $Id: bus_iou_mgr.h 1336 2008-07-07 17:29:40Z shefty $\r
++ * $Id: bus_iou_mgr.h 1307 2008-06-29 16:45:16Z leonidk $\r
+ */\r
+ \r
+ \r
+@@ -43,7 +43,6 @@\r
+ typedef struct _iou_mgr\r
+ {\r
+ cl_obj_t obj;\r
+- ib_pnp_handle_t h_pnp; /* Handle for iou PnP events */\r
+ \r
+ /* Mutex protects both pointer vectors. */\r
+ cl_mutex_t pdo_mutex;\r
+@@ -54,9 +53,12 @@\r
+ } iou_mgr_t;\r
+ \r
+ \r
++struct _bus_filter_instance;\r
++\r
+ ib_api_status_t\r
+ create_iou_mgr(\r
+- OUT iou_mgr_t** const pp_iou_mgr );\r
++ IN struct _bus_filter_instance* p_bfi,\r
++ OUT iou_mgr_t** const pp_iou_mgr );\r
+ \r
+ \r
+ NTSTATUS\r
+diff -Naur --exclude-from=OMIT kernel/bus_pnp.c FilterDriver/bus_pnp.c\r
+--- kernel/bus_pnp.c 2008-04-04 15:31:40.187016000 -0700\r
++++ FilterDriver/bus_pnp.c 2008-08-01 14:43:58.929578700 -0700\r
+@@ -36,7 +36,6 @@\r
+ * Implemenation of all PnP functionality for FDO (power policy owners).\r
+ */\r
+ \r
+-\r
+ #include "bus_pnp.h"\r
+ #include "al_ca.h"\r
+ #include "al_init.h"\r
+@@ -48,6 +47,17 @@\r
+ #include "iba/ib_ci_ifc.h"\r
+ \r
+ \r
++/* Interface names are generated by IoRegisterDeviceInterface. */\r
++static UNICODE_STRING al_ifc_name;\r
++static UNICODE_STRING ci_ifc_name;\r
++\r
++FAST_MUTEX ControlMutex;\r
++ULONG bfi_InstanceCount;\r
++bus_filter_t bus_filters[MAX_BUS_FILTERS];\r
++\r
++extern ib_al_handle_t gh_al; // NULL if AL needs init.\r
++\r
++\r
+ static NTSTATUS\r
+ fdo_start(\r
+ IN DEVICE_OBJECT* const p_dev_obj,\r
+@@ -71,7 +81,7 @@\r
+ OUT cl_irp_action_t* const p_action );\r
+ \r
+ static NTSTATUS\r
+-fdo_query_remove_relations(\r
++fdo_query_bus_relations(\r
+ IN DEVICE_OBJECT* const p_dev_obj,\r
+ IN IRP* const p_irp, \r
+ OUT cl_irp_action_t* const p_action );\r
+@@ -117,7 +127,7 @@\r
+ #pragma alloc_text (PAGE, fdo_query_remove)\r
+ #pragma alloc_text (PAGE, fdo_release_resources)\r
+ #pragma alloc_text (PAGE, fdo_query_capabilities)\r
+-#pragma alloc_text (PAGE, fdo_query_remove_relations)\r
++#pragma alloc_text (PAGE, fdo_query_bus_relations)\r
+ #pragma alloc_text (PAGE, __query_al_ifc)\r
+ #pragma alloc_text (PAGE, __query_ci_ifc)\r
+ #pragma alloc_text (PAGE, __get_relations)\r
+@@ -143,9 +153,9 @@\r
+ cl_irp_skip,\r
+ cl_irp_skip,\r
+ cl_do_sync_pnp,\r
++ fdo_query_bus_relations /*cl_irp_ignore*/ ,\r
+ cl_irp_ignore,\r
+- cl_irp_ignore,\r
+- fdo_query_remove_relations,\r
++ cl_irp_skip /*fdo_query_remove_relations now _bus_relations */ ,\r
+ cl_irp_ignore,\r
+ cl_irp_ignore,\r
+ cl_irp_ignore,\r
+@@ -170,58 +180,90 @@\r
+ {\r
+ NTSTATUS status;\r
+ DEVICE_OBJECT *p_dev_obj, *p_next_do;\r
+- bus_fdo_ext_t *p_ext;\r
++ bus_fdo_ext_t *p_ext=NULL;\r
+ UNICODE_STRING dev_name, dos_name;\r
++ bus_filter_t *p_bfi;\r
++ int ic;\r
+ \r
+ BUS_ENTER( BUS_DBG_PNP );\r
+ \r
+- if( bus_globals.p_bus_ext )\r
++ /* allocate a Bus Filter Instance */\r
++ p_bfi = alloc_bfi( p_driver_obj, &ic );\r
++ if ( !p_bfi )\r
+ {\r
+- BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
+- ("Bus root already exists. Only one bus root allowed.\n") );\r
+- return STATUS_NO_SUCH_DEVICE;\r
++ BUS_PRINT( BUS_DBG_PNP,\r
++ ("%s() Err - Exceeded MAX_BUS_FILTERS(%d)\n",MAX_BUS_FILTERS));\r
++ return STATUS_UNSUCCESSFUL;\r
+ }\r
+ \r
+- RtlInitUnicodeString( &dev_name, AL_DEVICE_NAME );\r
+- RtlInitUnicodeString( &dos_name, L"\\DosDevices\\Global\\ibal" );\r
+-\r
+ /* Create the FDO device object to attach to the stack. */\r
+- status = IoCreateDevice( p_driver_obj, sizeof(bus_fdo_ext_t),\r
+- &dev_name, FILE_DEVICE_BUS_EXTENDER,\r
+- FILE_DEVICE_SECURE_OPEN, FALSE, &p_dev_obj );\r
+- if( !NT_SUCCESS(status) )\r
++\r
++ /* if 1st Bus Filter Instance, then create device names for user ioctl */\r
++ if ( ic == 1 )\r
+ {\r
+- BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
+- ("Failed to create bus root FDO device.\n") );\r
+- return status;\r
++ RtlInitUnicodeString( &dev_name, AL_DEVICE_NAME );\r
++ RtlInitUnicodeString( &dos_name, L"\\DosDevices\\Global\\ibal" );\r
++\r
++ status = IoCreateDevice( p_driver_obj, sizeof(bus_fdo_ext_t),\r
++ &dev_name, FILE_DEVICE_BUS_EXTENDER,\r
++ FILE_DEVICE_SECURE_OPEN, FALSE, &p_dev_obj );\r
++ if( !NT_SUCCESS(status) )\r
++ {\r
++ BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
++ ("Failed to create ControlDeviceObject, status %x.\n",status) );\r
++ goto bail;\r
++ }\r
++ IoDeleteSymbolicLink( &dos_name );\r
++ status = IoCreateSymbolicLink( &dos_name, &dev_name );\r
++ if( !NT_SUCCESS(status) )\r
++ {\r
++ IoDeleteDevice( p_dev_obj );\r
++ BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
++ ("Failed to create symlink for dos name.\n") );\r
++ goto bail;\r
++ }\r
++ }\r
++ else {\r
++ status = IoCreateDevice( p_driver_obj, sizeof(bus_fdo_ext_t),\r
++ NULL, FILE_DEVICE_BUS_EXTENDER,\r
++ FILE_DEVICE_SECURE_OPEN, FALSE, &p_dev_obj );\r
+ }\r
+ \r
+- IoDeleteSymbolicLink( &dos_name );\r
+- status = IoCreateSymbolicLink( &dos_name, &dev_name );\r
+ if( !NT_SUCCESS(status) )\r
+ {\r
+- IoDeleteDevice( p_dev_obj );\r
+- BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
+- ("Failed to create symlink for dos name.\n") );\r
+- return status;\r
++ BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
++ ("Failed to create bus root FDO device.\n") );\r
++ goto bail;\r
+ }\r
+ \r
+ p_ext = p_dev_obj->DeviceExtension;\r
++ p_ext->n_al_ifc_ref = 0;\r
++ p_ext->n_ci_ifc_ref = 0;\r
+ \r
+ p_next_do = IoAttachDeviceToDeviceStack( p_dev_obj, p_pdo );\r
+ if( !p_next_do )\r
+ {\r
+ IoDeleteDevice( p_dev_obj );\r
+ BUS_TRACE_EXIT( BUS_DBG_ERROR, ("IoAttachToDeviceStack failed.\n") );\r
+- return STATUS_NO_SUCH_DEVICE;\r
++ status = STATUS_NO_SUCH_DEVICE;\r
++ goto bail;\r
+ }\r
+ \r
+ cl_init_pnp_po_ext( p_dev_obj, p_next_do, p_pdo, bus_globals.dbg_lvl,\r
+- &vfptr_fdo_pnp, NULL );\r
++ &vfptr_fdo_pnp, NULL );\r
++\r
++ p_bfi->p_bus_ext = p_ext;\r
++ p_ext->bus_filter = p_bfi;\r
++\r
++ /*\r
++ * if not 1st Bus Filter Instance, then finished...\r
++ */\r
++ if ( ic > 1 )\r
++ goto adxit;\r
+ \r
+ /* Register the upper interface (the one used by clients). */\r
+- status = IoRegisterDeviceInterface( p_pdo, \r
+- &GUID_IB_AL_INTERFACE, NULL, &p_ext->al_ifc_name );\r
++ status = IoRegisterDeviceInterface( p_pdo, &GUID_IB_AL_INTERFACE, NULL,\r
++ &al_ifc_name );\r
+ if( !NT_SUCCESS( status ) )\r
+ {\r
+ IoDetachDevice( p_ext->cl_ext.p_next_do );\r
+@@ -229,27 +271,43 @@\r
+ BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
+ ("IoRegisterDeviceInterface for upper interface returned %08x\n",\r
+ status) );\r
+- return STATUS_NO_SUCH_DEVICE;\r
++ status = STATUS_NO_SUCH_DEVICE;\r
++ goto bail;\r
+ }\r
+ \r
+- /* Register the lower interface (the one used by HCA VPDs). */\r
+- status = IoRegisterDeviceInterface( p_pdo, \r
+- &GUID_IB_CI_INTERFACE, NULL, &p_ext->ci_ifc_name );\r
++ /* Register the lower (CI) interface (the one used by HCA VPDs). */\r
++ status = IoRegisterDeviceInterface( p_pdo, &GUID_IB_CI_INTERFACE, NULL,\r
++ &ci_ifc_name );\r
+ if( !NT_SUCCESS( status ) )\r
+ {\r
+- RtlFreeUnicodeString( &p_ext->al_ifc_name );\r
+ IoDetachDevice( p_ext->cl_ext.p_next_do );\r
+ IoDeleteDevice( p_dev_obj );\r
+ BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
+ ("IoRegisterDeviceInterface for lower interface returned %08x\n",\r
+ status) );\r
+- return STATUS_NO_SUCH_DEVICE;\r
++ status = STATUS_NO_SUCH_DEVICE;\r
++ goto bail;\r
+ }\r
+ \r
+- bus_globals.p_bus_ext = p_ext;\r
++adxit:\r
++ BUS_PRINT( BUS_DBG_PNP, ("%s(%s) exit status 0\n",\r
++ __FUNCTION__, p_bfi->whoami) );\r
+ \r
+ BUS_EXIT( BUS_DBG_PNP );\r
+ return STATUS_SUCCESS;\r
++\r
++bail:\r
++ BUS_PRINT( BUS_DBG_PNP, ("%s(%s) exit status %d\n",\r
++ __FUNCTION__,p_bfi->whoami,status) );\r
++ ic = free_bfi(p_bfi);\r
++ /* if last Bus filter, then cleanup */\r
++ if ( ic == 0 )\r
++ {\r
++ IoDeleteSymbolicLink( &dos_name );\r
++ RtlFreeUnicodeString( &al_ifc_name );\r
++ }\r
++ BUS_EXIT( BUS_DBG_PNP );\r
++ return status;\r
+ }\r
+ \r
+ \r
+@@ -262,10 +320,13 @@\r
+ NTSTATUS status;\r
+ bus_fdo_ext_t *p_ext;\r
+ ib_api_status_t ib_status;\r
++ bus_filter_t *p_bfi;\r
++ boolean_t AL_init_here = FALSE;\r
+ \r
+ BUS_ENTER( BUS_DBG_PNP );\r
+ \r
+ p_ext = p_dev_obj->DeviceExtension;\r
++ p_bfi = p_ext->bus_filter;\r
+ \r
+ /* Handled on the way up. */\r
+ status = cl_do_sync_pnp( p_dev_obj, p_irp, p_action );\r
+@@ -276,18 +337,24 @@\r
+ return status;\r
+ }\r
+ \r
+- /* Initialize AL */\r
+- ib_status = al_initialize();\r
+- if( ib_status != IB_SUCCESS )\r
+- {\r
+- al_cleanup();\r
+- BUS_TRACE_EXIT( BUS_DBG_ERROR, ("al_initialize returned %s.\n",\r
+- ib_get_err_str(ib_status)) );\r
+- return STATUS_UNSUCCESSFUL;\r
++ ExAcquireFastMutexUnsafe(&ControlMutex);\r
++ if ( !gh_al ) {\r
++ /* Initialize AL */\r
++ ib_status = al_initialize();\r
++ if( ib_status != IB_SUCCESS )\r
++ {\r
++ al_cleanup();\r
++ BUS_TRACE_EXIT( BUS_DBG_ERROR, ("al_initialize returned %s.\n",\r
++ ib_get_err_str(ib_status)) );\r
++ ExReleaseFastMutexUnsafe(&ControlMutex);\r
++ return STATUS_UNSUCCESSFUL;\r
++ }\r
++ AL_init_here = TRUE;\r
+ }\r
++ ExReleaseFastMutexUnsafe(&ControlMutex);\r
+ \r
+ /* Initialize the port manager. */\r
+- ib_status = create_port_mgr( &p_ext->p_port_mgr );\r
++ ib_status = create_port_mgr( p_ext->bus_filter, &p_ext->p_port_mgr );\r
+ if( ib_status != IB_SUCCESS )\r
+ {\r
+ BUS_TRACE_EXIT( BUS_DBG_ERROR, ("create_port_mgr returned %s.\n",\r
+@@ -296,7 +363,7 @@\r
+ }\r
+ \r
+ /* Initialize the IOU manager. */\r
+- ib_status = create_iou_mgr( &p_ext->p_iou_mgr );\r
++ ib_status = create_iou_mgr( p_ext->bus_filter, &p_ext->p_iou_mgr );\r
+ if( ib_status != IB_SUCCESS )\r
+ {\r
+ BUS_TRACE_EXIT( BUS_DBG_ERROR, ("create_iou_mgr returned %s.\n",\r
+@@ -304,13 +371,18 @@\r
+ return STATUS_UNSUCCESSFUL;\r
+ }\r
+ \r
+- status = IoSetDeviceInterfaceState( &p_ext->al_ifc_name, TRUE );\r
+- ASSERT( NT_SUCCESS( status ) );\r
++ if ( AL_init_here ) {\r
++ status = IoSetDeviceInterfaceState( &al_ifc_name, TRUE );\r
++ ASSERT( NT_SUCCESS( status ) );\r
+ \r
+- status = IoSetDeviceInterfaceState( &p_ext->ci_ifc_name, TRUE );\r
+- ASSERT( NT_SUCCESS( status ) );\r
++ status = IoSetDeviceInterfaceState( &ci_ifc_name, TRUE );\r
++ ASSERT( NT_SUCCESS( status ) );\r
++ }\r
+ \r
++ BUS_PRINT(BUS_DBG_PNP,\r
++ ("%s() %s exit %x\n",__FUNCTION__,p_bfi->whoami,status));\r
+ BUS_EXIT( BUS_DBG_PNP );\r
++\r
+ return status;\r
+ }\r
+ \r
+@@ -327,6 +399,11 @@\r
+ \r
+ p_ext = p_dev_obj->DeviceExtension;\r
+ \r
++ BUS_PRINT( BUS_DBG_PNP,\r
++ ("%s() IRP_MN_QUERY_REMOVE_DEVICE %s @ %p refs CI %d AL %d\n", \r
++ __FUNCTION__, p_ext->cl_ext.vfptr_pnp_po->identity, p_ext,\r
++ p_ext->n_ci_ifc_ref,p_ext->n_al_ifc_ref ) ); // XXX\r
++\r
+ if( p_ext->n_ci_ifc_ref )\r
+ {\r
+ /*\r
+@@ -363,30 +440,52 @@\r
+ {\r
+ bus_fdo_ext_t *p_ext;\r
+ NTSTATUS status;\r
++ bus_filter_t *p_bfi;\r
++ int ic;\r
+ \r
+ BUS_ENTER( BUS_DBG_PNP );\r
+ \r
+ p_ext = p_dev_obj->DeviceExtension;\r
++ ic = get_bfi_count();\r
+ \r
+ //TODO: Fail outstanding I/O operations.\r
+ \r
++ if (p_ext->p_port_mgr)\r
++ cl_obj_destroy( &p_ext->p_port_mgr->obj );\r
++\r
++ if (p_ext->p_iou_mgr)\r
++ cl_obj_destroy( &p_ext->p_iou_mgr->obj );\r
++\r
++ p_bfi = p_ext->bus_filter;\r
++ CL_ASSERT( p_bfi );\r
++ BUS_PRINT( BUS_DBG_PNP, ("%s() Releasing BusFilter %s\n",\r
++ __FUNCTION__, p_bfi->whoami ));\r
++ if (p_bfi) {\r
++ p_ext->bus_filter = NULL;\r
++ p_bfi->p_bus_ext = NULL;\r
++ }\r
++\r
++ ic = free_bfi( p_bfi );\r
++\r
++ /* if not last Buf Filter Instance, then exit, otherwise cleanup/shutdown */\r
++ if ( ic > 0 ) {\r
++ BUS_PRINT( BUS_DBG_PNP, ("%s() %d remaining BusFilters\n",\r
++ __FUNCTION__, ic ));\r
++ return;\r
++ }\r
++\r
+ /* Disable any exported interfaces. */\r
+- status = IoSetDeviceInterfaceState( &p_ext->al_ifc_name, FALSE );\r
++ status = IoSetDeviceInterfaceState( &al_ifc_name, FALSE );\r
+ ASSERT( NT_SUCCESS( status ) );\r
+- status = IoSetDeviceInterfaceState( &p_ext->ci_ifc_name, FALSE );\r
++ status = IoSetDeviceInterfaceState( &ci_ifc_name, FALSE );\r
+ ASSERT( NT_SUCCESS( status ) );\r
+ \r
+ /* Release the memory allocated for the interface symbolic names. */\r
+- RtlFreeUnicodeString( &p_ext->ci_ifc_name );\r
+- RtlFreeUnicodeString( &p_ext->al_ifc_name );\r
+-\r
+- cl_obj_destroy( &p_ext->p_port_mgr->obj );\r
+- cl_obj_destroy( &p_ext->p_iou_mgr->obj );\r
++ RtlFreeUnicodeString( &ci_ifc_name );\r
++ RtlFreeUnicodeString( &al_ifc_name );\r
+ \r
+ al_cleanup();\r
+ \r
+- bus_globals.p_bus_ext = NULL;\r
+-\r
+ BUS_EXIT( BUS_DBG_PNP );\r
+ }\r
+ \r
+@@ -431,18 +530,19 @@\r
+ }\r
+ \r
+ \r
++#if 0 // XXX\r
++\r
+ static NTSTATUS\r
+-fdo_query_remove_relations(\r
++fdo_query_removal_relations(\r
+ IN DEVICE_OBJECT* const p_dev_obj,\r
+ IN IRP* const p_irp, \r
+ OUT cl_irp_action_t* const p_action )\r
+ {\r
+ NTSTATUS status;\r
++ UNUSED_PARAM( p_dev_obj );\r
+ \r
+ BUS_ENTER( BUS_DBG_PNP );\r
+ \r
+- UNUSED_PARAM( p_dev_obj );\r
+-\r
+ status = port_mgr_get_bus_relations( 0, p_irp );\r
+ if( status == STATUS_SUCCESS || \r
+ status == STATUS_NO_SUCH_DEVICE )\r
+@@ -471,6 +571,67 @@\r
+ BUS_EXIT( BUS_DBG_PNP );\r
+ return status;\r
+ }\r
++#endif\r
++\r
++\r
++static NTSTATUS\r
++fdo_query_bus_relations(\r
++ IN DEVICE_OBJECT* const p_dev_obj,\r
++ IN IRP* const p_irp, \r
++ OUT cl_irp_action_t* const p_action )\r
++{\r
++ NTSTATUS status;\r
++ bus_fdo_ext_t *p_ext;\r
++ bus_filter_t *p_bfi;\r
++\r
++ BUS_ENTER( BUS_DBG_PNP );\r
++\r
++ p_ext = p_dev_obj->DeviceExtension;\r
++ CL_ASSERT( p_ext->bus_filter );\r
++ p_bfi = p_ext->bus_filter;\r
++ CL_ASSERT( p_bfi->magic == BFI_MAGIC );\r
++\r
++ BUS_PRINT( BUS_DBG_PNP, ("%s(%s) ca_guid %I64x\n",\r
++ __FUNCTION__,p_bfi->whoami, p_bfi->ca_guid) );\r
++\r
++ if ( p_bfi->ca_guid == 0ULL )\r
++ {\r
++ /* HCA not yet bound to a BFI slot (no PNP ADD event seen), no bus\r
++ * relations yet.\r
++ */\r
++ status = STATUS_SUCCESS;\r
++ }\r
++ else\r
++ {\r
++ status = port_mgr_get_bus_relations( p_bfi->ca_guid, p_irp );\r
++ if( status == STATUS_SUCCESS || \r
++ status == STATUS_NO_SUCH_DEVICE )\r
++ {\r
++ status = iou_mgr_get_bus_relations( p_bfi->ca_guid, p_irp );\r
++ }\r
++ if( status == STATUS_NO_SUCH_DEVICE )\r
++ status = STATUS_SUCCESS;\r
++ }\r
++\r
++ switch( status )\r
++ {\r
++ case STATUS_NO_SUCH_DEVICE:\r
++ *p_action = IrpSkip;\r
++ status = STATUS_SUCCESS;\r
++ break;\r
++\r
++ case STATUS_SUCCESS:\r
++ *p_action = IrpPassDown;\r
++ break;\r
++\r
++ default:\r
++ *p_action = IrpComplete;\r
++ break;\r
++ }\r
++\r
++ BUS_EXIT( BUS_DBG_PNP );\r
++ return status;\r
++}\r
+ \r
+ \r
+ void\r
+@@ -486,6 +647,8 @@\r
+ cl_atomic_inc( &p_ext->n_al_ifc_ref );\r
+ ObReferenceObject( p_dev_obj );\r
+ \r
++ BUS_PRINT( BUS_DBG_PNP, (" %p->n_al_ifc_ref %d\n",\r
++ p_ext,p_ext->n_al_ifc_ref )); // XXX\r
+ BUS_EXIT( BUS_DBG_PNP );\r
+ }\r
+ \r
+@@ -503,6 +666,8 @@\r
+ cl_atomic_dec( &p_ext->n_al_ifc_ref );\r
+ ObDereferenceObject( p_dev_obj );\r
+ \r
++ BUS_PRINT( BUS_DBG_PNP, (" %p->n_al_ifc_ref %d\n",\r
++ p_ext,p_ext->n_al_ifc_ref )); // XXX\r
+ BUS_EXIT( BUS_DBG_PNP );\r
+ }\r
+ \r
+@@ -520,6 +685,8 @@\r
+ cl_atomic_inc( &p_ext->n_ci_ifc_ref );\r
+ ObReferenceObject( p_dev_obj );\r
+ \r
++ BUS_PRINT( BUS_DBG_PNP, (" %p->n_ci_ifc_ref %d\n",\r
++ p_ext,p_ext->n_ci_ifc_ref )); // XXX\r
+ BUS_EXIT( BUS_DBG_PNP );\r
+ }\r
+ \r
+@@ -537,6 +704,8 @@\r
+ cl_atomic_dec( &p_ext->n_ci_ifc_ref );\r
+ ObDereferenceObject( p_dev_obj );\r
+ \r
++ BUS_PRINT( BUS_DBG_PNP, (" %p->n_ci_ifc_ref %d\n",\r
++ p_ext,p_ext->n_ci_ifc_ref )); // XXX\r
+ BUS_EXIT( BUS_DBG_PNP );\r
+ }\r
+ \r
+@@ -777,9 +946,7 @@\r
+ \r
+ BUS_ENTER( BUS_DBG_PNP );\r
+ \r
+-#pragma warning( push, 3 )\r
+ PAGED_CODE();\r
+-#pragma warning( pop )\r
+ \r
+ p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
+ \r
+@@ -971,7 +1138,8 @@\r
+ BUS_TRACE( BUS_DBG_POWER, \r
+ ("SET_POWER for FDO %p (ext %p): type %s, state %d, action %d \n",\r
+ p_dev_obj, p_ext,\r
+- (p_io_stack->Parameters.Power.Type) ? "DevicePowerState" : "SystemPowerState",\r
++ (p_io_stack->Parameters.Power.Type)\r
++ ? "DevicePowerState" : "SystemPowerState",\r
+ p_io_stack->Parameters.Power.State.DeviceState, \r
+ p_io_stack->Parameters.Power.ShutdownType ));\r
+ \r
+@@ -1073,16 +1241,18 @@\r
+ * the PDO will get cleaned up.\r
+ */\r
+ p_pdo_ext->b_reported_missing = TRUE;\r
+- BUS_TRACE( BUS_DBG_PNP, ("Don't report PDO! %s: PDO %p, ext %p, present %d, missing %d .\n",\r
+- p_pdo_ext->cl_ext.vfptr_pnp_po->identity, p_pdo_ext->cl_ext.p_self_do, \r
+- p_pdo_ext, p_pdo_ext->b_present, p_pdo_ext->b_reported_missing ) );\r
++ BUS_TRACE( BUS_DBG_PNP, ("Don't report PDO! %s: PDO %p, ext %p, "\r
++ "present %d, missing %d .\n",\r
++ p_pdo_ext->cl_ext.vfptr_pnp_po->identity,\r
++ p_pdo_ext->cl_ext.p_self_do, p_pdo_ext, p_pdo_ext->b_present,\r
++ p_pdo_ext->b_reported_missing ) );\r
+ continue;\r
+ }\r
+ \r
+ if( ca_guid && p_pdo_ext->ca_guid != ca_guid )\r
+ continue;\r
+ \r
+- BUS_TRACE( BUS_DBG_PNP, ("Reported PDO %p(=%p), ext %p.\n", \r
++ BUS_TRACE( BUS_DBG_PNP, ("Reported PDO %p(=%p), ext %p\n", \r
+ p_pdo_ext->cl_ext.p_self_do, p_pdo_ext->cl_ext.p_pdo, p_pdo_ext ));\r
+ \r
+ p_rel->Objects[p_rel->Count] = p_pdo_ext->cl_ext.p_pdo;\r
+@@ -1092,3 +1262,256 @@\r
+ BUS_EXIT( BUS_DBG_PNP );\r
+ return STATUS_SUCCESS;\r
+ }\r
++\r
++\r
++/*\r
++ * find a bus filter instance (p_bfi) given an *cl_obj: port_mgr or iou_mgr. \r
++ */\r
++\r
++bus_filter_t *\r
++get_bfi_by_obj(IN int obj_type, IN cl_obj_t *p_obj )\r
++{\r
++ bus_filter_t *p_bfi;\r
++ bus_filter_t *matched=NULL;\r
++\r
++ CL_ASSERT((obj_type == BFI_PORT_MGR_OBJ) || (obj_type == BFI_IOU_MGR_OBJ));\r
++\r
++ ExAcquireFastMutexUnsafe(&ControlMutex);\r
++\r
++ for(p_bfi=bus_filters; p_bfi < &bus_filters[MAX_BUS_FILTERS]; p_bfi++) {\r
++\r
++ if ( !p_bfi->p_bus_ext )\r
++ continue;\r
++\r
++ if ( obj_type == BFI_PORT_MGR_OBJ ) {\r
++ if ( p_obj == p_bfi->p_port_mgr_obj ) {\r
++ matched = p_bfi;\r
++ break;\r
++ }\r
++ }\r
++ else {\r
++ if ( p_obj == p_bfi->p_iou_mgr_obj ) {\r
++ matched = p_bfi;\r
++ break;\r
++ }\r
++ }\r
++ }\r
++ ExReleaseFastMutexUnsafe(&ControlMutex);\r
++\r
++ BUS_PRINT( BUS_DBG_PNP,\r
++ ("%s() cl_obj %p type %s_MGR_OBJ --> bfi[%d] %p\n",\r
++ __FUNCTION__,p_obj,\r
++ (obj_type == BFI_PORT_MGR_OBJ ? "PORT": "IOU"),\r
++ (matched ? (matched - bus_filters) : (-1)), matched ) );\r
++\r
++ return matched;\r
++}\r
++\r
++/*\r
++ * find a bus filter instance given an HCA guid.\r
++ */\r
++\r
++bus_filter_t *\r
++get_bfi_by_ca_guid( IN net64_t ca_guid )\r
++{\r
++ bus_filter_t *p_bfi;\r
++ bus_filter_t *matched=NULL;\r
++\r
++ if ( ca_guid == 0ULL )\r
++ {\r
++ matched = bus_filters;\r
++ BUS_PRINT( BUS_DBG_PNP, ("%s() ERR guid %I64x -> bfi[0] %p\n",\r
++ __FUNCTION__, ca_guid, matched) );\r
++ CL_ASSERT( ca_guid ); // XXX\r
++ return matched;\r
++ }\r
++\r
++ ExAcquireFastMutexUnsafe(&ControlMutex);\r
++\r
++ for(p_bfi=bus_filters; p_bfi < &bus_filters[MAX_BUS_FILTERS]; p_bfi++)\r
++ {\r
++ if ( !p_bfi->p_bus_ext )\r
++ continue;\r
++\r
++ if ( ca_guid == p_bfi->ca_guid )\r
++ {\r
++ matched = p_bfi;\r
++ break;\r
++ }\r
++ }\r
++ ExReleaseFastMutexUnsafe(&ControlMutex);\r
++\r
++ BUS_PRINT( BUS_DBG_PNP,\r
++ ("%s() guid 0x%I64x -> bfi[%d] %p\n",\r
++ __FUNCTION__, ca_guid,\r
++ (matched ? (matched - bus_filters) : (-1)), matched ) );\r
++\r
++ return matched;\r
++}\r
++\r
++\r
++/*\r
++ * find/bind the specified ca_guid to a bus filter instance.\r
++ * Called from PORT_ADD or IOU_ADD pnp callback routines with the ca_guid from\r
++ * the pnp event record.\r
++ * Assumption is a BFI slot has been allocated in add_device() although the\r
++ * ca_guid was not known at that time; hence !ca_bound. When PNP generates an\r
++ * 'ADD' event, the port_mgr/iou_mgr pnp callback routine calls here to match\r
++ * the input ca_guid which caused the PNP event to the BFI instance by ca_guid.\r
++ * In the 1st call after add_device() the BFI slot is allocated but not yet \r
++ * bound to a CA guid. If the input ca_guid is not matched, then the 1st\r
++ * allocated but not bound BFI slot is then 'bound' by setting\r
++ * bfi->ca_guid = input ca_guid.\r
++ */\r
++\r
++bus_filter_t *\r
++get_set_bfi_by_ca_guid( IN net64_t ca_guid )\r
++{\r
++ bus_filter_t *p_bfi;\r
++ bus_filter_t *matched=NULL;\r
++ boolean_t ca_bound = FALSE;\r
++\r
++ if ( ca_guid == 0ULL )\r
++ {\r
++ matched = bus_filters;\r
++ BUS_PRINT( BUS_DBG_PNP, ("%s() ERR guid 0x%I64x -> bfi[0] %p\n",\r
++ __FUNCTION__, ca_guid, matched) );\r
++ CL_ASSERT( ca_guid ); // XXX\r
++ return matched;\r
++ }\r
++\r
++ for(p_bfi=bus_filters; p_bfi < &bus_filters[MAX_BUS_FILTERS]; p_bfi++)\r
++ {\r
++ if ( !p_bfi->p_bus_ext )\r
++ continue;\r
++\r
++ if ( ca_guid == p_bfi->ca_guid )\r
++ {\r
++ matched = p_bfi;\r
++ break;\r
++ }\r
++ }\r
++\r
++ /*\r
++ * if no match, find an 'allocated' bfi slot which does not have a bound CA.\r
++ * Bound == ca_guid != 0ULL.\r
++ */\r
++ if ( !matched )\r
++ {\r
++ ExAcquireFastMutexUnsafe(&ControlMutex);\r
++\r
++ for(p_bfi=bus_filters; p_bfi < &bus_filters[MAX_BUS_FILTERS]; p_bfi++)\r
++ {\r
++ if ( !p_bfi->p_bus_ext )\r
++ continue; // not allocated.\r
++\r
++ if ( p_bfi->ca_guid == 0ULL )\r
++ {\r
++ ca_bound = TRUE;\r
++ p_bfi->ca_guid = ca_guid; // bind CA & this BFI slot; RTU.\r
++ matched = p_bfi;\r
++ break;\r
++ }\r
++ }\r
++ ExReleaseFastMutexUnsafe(&ControlMutex);\r
++ }\r
++\r
++ BUS_PRINT( BUS_DBG_PNP,\r
++ ("%s()%sguid 0x%I64x @ bfi[%d] %p \n",\r
++ __FUNCTION__, (ca_bound ? "SET ":" "), ca_guid,\r
++ (matched ? (matched - bus_filters) : (-1)), matched ) );\r
++\r
++ return matched;\r
++}\r
++\r
++\r
++bus_filter_t *\r
++alloc_bfi( IN DRIVER_OBJECT *p_driver_obj, OUT int *p_instance_count )\r
++{\r
++ bus_filter_t *p_bfi;\r
++ bus_filter_t *matched=NULL;\r
++\r
++ // Using unsafe function so that the IRQL remains at PASSIVE_LEVEL.\r
++ // IoCreateDeviceSecure & IoCreateSymbolicLink must be called at\r
++ // PASSIVE_LEVEL.\r
++\r
++ ExAcquireFastMutexUnsafe(&ControlMutex);\r
++\r
++ // find 1st unused bfi slot.\r
++ for(p_bfi=bus_filters; p_bfi < &bus_filters[MAX_BUS_FILTERS]; p_bfi++)\r
++ {\r
++ if ( !p_bfi->p_bus_ext )\r
++ {\r
++ /* temp setting until 'real' p_bus_ext is alloc; see bus_add_device.\r
++ * If p_bus_ext is ! 0, then bfi slot is allocated, although it\r
++ * may not yet have a bound CA guid; set set_get_\r
++ */\r
++ p_bfi->p_bus_ext = (bus_fdo_ext_t*)p_driver_obj;\r
++ matched = p_bfi;\r
++ *p_instance_count = ++bfi_InstanceCount; // record in-use\r
++ break;\r
++ }\r
++ }\r
++ ExReleaseFastMutexUnsafe(&ControlMutex);\r
++\r
++#if DBG\r
++ RtlStringCbPrintfA ( p_bfi->whoami,\r
++ sizeof(p_bfi->whoami),\r
++ "bfi-%d",\r
++ (bfi_InstanceCount - 1) );\r
++\r
++ p_bfi->magic = BFI_MAGIC; // XXX debug\r
++#endif\r
++\r
++ BUS_PRINT( BUS_DBG_PNP, ("%s() %s %p\n",\r
++ __FUNCTION__, (matched ? matched->whoami:"Nobody"), matched) );\r
++\r
++ return matched;\r
++}\r
++\r
++\r
++int\r
++free_bfi( IN bus_filter_t *p_bfi )\r
++{\r
++ int remaining;\r
++\r
++ ExAcquireFastMutexUnsafe(&ControlMutex);\r
++ p_bfi->p_bus_ext = NULL;\r
++ p_bfi->ca_guid = 0ULL;\r
++ remaining = --bfi_InstanceCount; // one less bfi in-use\r
++ ExReleaseFastMutexUnsafe(&ControlMutex);\r
++\r
++ return remaining;\r
++}\r
++\r
++int\r
++get_bfi_count( void )\r
++{\r
++ int ic;\r
++\r
++ ExAcquireFastMutexUnsafe(&ControlMutex);\r
++ ic = bfi_InstanceCount;\r
++ ExReleaseFastMutexUnsafe(&ControlMutex);\r
++\r
++ return ic;\r
++}\r
++\r
++#if DBG\r
++char *get_obj_state_str(cl_state_t state)\r
++{\r
++ switch( state ) {\r
++ case CL_UNINITIALIZED:\r
++ return "UNINITIALIZED";\r
++ case CL_INITIALIZED:\r
++ return "INITIALIZED";\r
++ case CL_DESTROYING:\r
++ return "DESTROYING";\r
++ case CL_DESTROYED:\r
++ return "DESTROYED";\r
++ default:\r
++ break;\r
++ }\r
++ return "Err - Bad obj state";\r
++}\r
++#endif\r
++\r
+diff -Naur --exclude-from=OMIT kernel/bus_pnp.h.bak FilterDriver/bus_pnp.h.bak\r
+--- kernel/bus_pnp.h.bak 1969-12-31 16:00:00.000000000 -0800\r
++++ FilterDriver/bus_pnp.h.bak 2008-07-08 12:01:36.000000000 -0700\r
+@@ -0,0 +1,90 @@\r
++/*\r
++ * Copyright (c) 2005 SilverStorm Technologies. All rights reserved.\r
++ *\r
++ * This software is available to you under the OpenIB.org BSD license\r
++ * below:\r
++ *\r
++ * Redistribution and use in source and binary forms, with or\r
++ * without modification, are permitted provided that the following\r
++ * conditions are met:\r
++ *\r
++ * - Redistributions of source code must retain the above\r
++ * copyright notice, this list of conditions and the following\r
++ * disclaimer.\r
++ *\r
++ * - Redistributions in binary form must reproduce the above\r
++ * copyright notice, this list of conditions and the following\r
++ * disclaimer in the documentation and/or other materials\r
++ * provided with the distribution.\r
++ *\r
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
++ * SOFTWARE.\r
++ *\r
++ * $Id: bus_pnp.h 1160 2008-05-12 13:01:47Z tzachid $\r
++ */\r
++\r
++\r
++\r
++#if !defined _BUS_DRV_PNP_H_\r
++#define _BUS_DRV_PNP_H_\r
++\r
++\r
++#include "bus_driver.h"\r
++#include "iba/ib_al_ifc.h"\r
++\r
++\r
++/****f* InfiniBand Bus Driver: Plug and Play/bus_add_device\r
++* NAME\r
++* bus_add_device\r
++*\r
++* DESCRIPTION\r
++* Main AddDevice entrypoint for the IB Bus driver.\r
++* Adds the bus root functional device object to the device node. The\r
++* bus root FDO performs all PnP operations for fabric attached devices.\r
++*\r
++* SYNOPSIS\r
++*/\r
++NTSTATUS\r
++bus_add_device(\r
++ IN PDRIVER_OBJECT p_driver_obj,\r
++ IN PDEVICE_OBJECT p_pdo );\r
++/*\r
++* PARAMETERS\r
++* p_driver_obj\r
++* Driver object for the BUS driver.\r
++*\r
++* p_pdo\r
++* Pointer to the device object representing the PDO for the device on\r
++* which we are loading.\r
++*\r
++* RETURN VBUSUES\r
++* STATUS_SUCCESS if the device was successfully added.\r
++*\r
++* Other NTSTATUS error values if errors are encountered.\r
++*\r
++* SEE ALSO\r
++*********/\r
++\r
++\r
++void\r
++al_set_ifc(\r
++ OUT ib_al_ifc_t* const p_ifc );\r
++\r
++void\r
++al_ref_ifc(\r
++ IN DEVICE_OBJECT* p_dev_obj );\r
++\r
++NTSTATUS\r
++bus_get_relations(\r
++ IN cl_qlist_t* const p_pdo_list,\r
++ IN const net64_t ca_guid,\r
++ IN IRP* const p_irp );\r
++\r
++NTSTATUS port_mgr_pkey_add();\r
++#endif // !defined _BUS_DRV_PNP_H_\r
+diff -Naur --exclude-from=OMIT kernel/bus_port_mgr.c FilterDriver/bus_port_mgr.c\r
+--- kernel/bus_port_mgr.c 2008-06-25 09:57:32.091601600 -0700\r
++++ FilterDriver/bus_port_mgr.c 2008-08-01 14:42:28.511399100 -0700\r
+@@ -27,7 +27,7 @@\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+- * $Id: bus_port_mgr.c 1236 2008-06-03 22:41:24Z shefty $\r
++ * $Id: bus_port_mgr.c 1160 2008-05-12 13:01:47Z tzachid $\r
+ */\r
+ \r
+ \r
+@@ -71,7 +71,14 @@\r
+ } bus_port_ext_t;\r
+ \r
+ \r
+-port_mgr_t* gp_port_mgr = NULL;\r
++typedef struct _port_pnp_context\r
++{\r
++ bus_filter_t *p_bus_filter;\r
++ void *p_pdo_ext;\r
++ int port_num;\r
++\r
++} port_pnp_ctx_t;\r
++\r
+ \r
+ extern pkey_array_t g_pkeys;\r
+ \r
+@@ -88,7 +95,8 @@\r
+ IN cl_obj_t* p_obj );\r
+ \r
+ ib_api_status_t\r
+-bus_reg_port_pnp( void );\r
++bus_reg_port_pnp(\r
++ IN bus_filter_t* p_bfi );\r
+ \r
+ ib_api_status_t\r
+ port_mgr_pnp_cb(\r
+@@ -274,14 +282,16 @@\r
+ */\r
+ ib_api_status_t\r
+ create_port_mgr(\r
++ IN bus_filter_t* p_bfi,\r
+ OUT port_mgr_t** const pp_port_mgr )\r
+ {\r
+ ib_api_status_t status;\r
+ cl_status_t cl_status;\r
++ port_mgr_t *gp_port_mgr;\r
+ \r
+ BUS_ENTER( BUS_DBG_PNP );\r
+ \r
+- CL_ASSERT( !gp_port_mgr );\r
++ CL_ASSERT( p_bfi->p_port_mgr == NULL );\r
+ \r
+ gp_port_mgr = cl_zalloc( sizeof( port_mgr_t ) );\r
+ if( !gp_port_mgr )\r
+@@ -290,9 +300,11 @@\r
+ ("Failed to allocate port manager.\n") );\r
+ return IB_INSUFFICIENT_MEMORY;\r
+ }\r
++ p_bfi->p_port_mgr = gp_port_mgr;\r
+ \r
+ /* Construct the load service. */\r
+ cl_obj_construct( &gp_port_mgr->obj, AL_OBJ_TYPE_LOADER );\r
++ p_bfi->p_port_mgr_obj = &gp_port_mgr->obj;\r
+ cl_mutex_construct( &gp_port_mgr->pdo_mutex );\r
+ cl_qlist_init( &gp_port_mgr->port_list );\r
+ \r
+@@ -307,7 +319,8 @@\r
+ \r
+ /* Initialize the load service object. */\r
+ cl_status = cl_obj_init( &gp_port_mgr->obj, CL_DESTROY_SYNC,\r
+- destroying_port_mgr, NULL, free_port_mgr );\r
++ destroying_port_mgr, NULL, free_port_mgr );\r
++\r
+ if( cl_status != CL_SUCCESS )\r
+ {\r
+ free_port_mgr( &gp_port_mgr->obj );\r
+@@ -316,13 +329,13 @@\r
+ return ib_convert_cl_status( cl_status );\r
+ }\r
+ \r
+- /* Register for port PnP events. */\r
+- status = bus_reg_port_pnp();\r
++ /* Register for port PnP events */\r
++ status = bus_reg_port_pnp(p_bfi);\r
+ if( status != IB_SUCCESS )\r
+ {\r
+- cl_obj_destroy( &gp_port_mgr->obj );\r
+ BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
+ ("bus_reg_port_pnp returned %s.\n", ib_get_err_str(status)) );\r
++ free_port_mgr( &gp_port_mgr->obj );\r
+ return status;\r
+ }\r
+ \r
+@@ -341,20 +354,35 @@\r
+ IN cl_obj_t* p_obj )\r
+ {\r
+ ib_api_status_t status;\r
++ bus_filter_t *p_bfi;\r
++ port_mgr_t *gp_port_mgr;\r
+ \r
+ BUS_ENTER( BUS_DBG_PNP );\r
+ \r
+ CL_ASSERT( p_obj );\r
++ p_bfi = get_bfi_by_obj(BFI_PORT_MGR_OBJ, p_obj);\r
++ if (p_bfi == NULL) {\r
++ BUS_PRINT(BUS_DBG_PNP, ("%s() failed to find p_bfi by obj %p?\n",\r
++ __FUNCTION__,p_obj));\r
++ return;\r
++ }\r
++ gp_port_mgr = p_bfi->p_port_mgr;\r
++\r
++ BUS_PRINT(BUS_DBG_PNP, ("%s(%s) obj %p port_mgr %p port_mgr_obj %p\n",\r
++ __FUNCTION__,p_bfi->whoami,p_obj,gp_port_mgr,\r
++ p_bfi->p_port_mgr_obj) );\r
++\r
++ CL_ASSERT( (void*)p_bfi->p_port_mgr == (void*)p_bfi->p_port_mgr_obj );\r
+ CL_ASSERT( gp_port_mgr == PARENT_STRUCT( p_obj, port_mgr_t, obj ) );\r
+- UNUSED_PARAM( p_obj );\r
+ \r
+- /* Deregister for port PnP events. */\r
+- if( gp_port_mgr->h_pnp )\r
+- {\r
+- status = ib_dereg_pnp( gp_port_mgr->h_pnp,\r
+- (ib_pfn_destroy_cb_t)cl_obj_deref );\r
++ /* Deregister for port PnP events if this is the last Port manager. */\r
++ if ( get_bfi_count() == 1 && bus_globals.h_pnp_port ) {\r
++ status = ib_dereg_pnp( bus_globals.h_pnp_port, NULL );\r
++ bus_globals.h_pnp_port = NULL;\r
+ CL_ASSERT( status == IB_SUCCESS );\r
+ }\r
++ cl_obj_deref( p_bfi->p_port_mgr_obj );\r
++\r
+ BUS_EXIT( BUS_DBG_PNP );\r
+ }\r
+ \r
+@@ -368,12 +396,32 @@\r
+ {\r
+ bus_pdo_ext_t *p_ext;\r
+ cl_list_item_t *p_list_item;\r
++ bus_filter_t *p_bfi;\r
++ port_mgr_t *gp_port_mgr;\r
+ \r
+ BUS_ENTER( BUS_DBG_PNP );\r
+ \r
+ CL_ASSERT( p_obj );\r
++ p_bfi = get_bfi_by_obj(BFI_PORT_MGR_OBJ, p_obj);\r
++ if (p_bfi == NULL) {\r
++ BUS_PRINT(BUS_DBG_PNP, ("%s: unable to get p_bfi for port obj %p?\n",\r
++ __FUNCTION__,p_obj));\r
++ return;\r
++ }\r
++ gp_port_mgr = p_bfi->p_port_mgr;\r
++ if ( !gp_port_mgr ) {\r
++ // if create fails & then free is called, p_bfi->p_port_mgr == NULL\r
++ return;\r
++ }\r
+ CL_ASSERT( gp_port_mgr == PARENT_STRUCT( p_obj, port_mgr_t, obj ) );\r
+ \r
++ BUS_PRINT(BUS_DBG_PNP, ("%s(%s) obj %p port_mgr %p port_mgr_obj %p\n",\r
++ __FUNCTION__, p_bfi->whoami, p_obj,gp_port_mgr,\r
++ p_bfi->p_port_mgr_obj) );\r
++\r
++ BUS_PRINT( BUS_DBG_PNP,\r
++ ("%s(%s) Mark all IPoIB PDOs as no longer present\n",\r
++ __FUNCTION__, p_bfi->whoami));\r
+ /*\r
+ * Mark all IPoIB PDOs as no longer present. This will cause them\r
+ * to be removed when they process the IRP_MN_REMOVE_DEVICE.\r
+@@ -387,8 +435,11 @@\r
+ {\r
+ CL_ASSERT( !p_ext->b_present );\r
+ p_ext->b_reported_missing = TRUE;\r
+- BUS_TRACE( BUS_DBG_PNP, ("%s: PDO %p, ext %p, present %d, missing %d .\n",\r
+- p_ext->cl_ext.vfptr_pnp_po->identity, p_ext->cl_ext.p_self_do, p_ext, p_ext->b_present, p_ext->b_reported_missing ) );\r
++ BUS_TRACE( BUS_DBG_PNP,\r
++ ("%s %s: PDO %p, ext %p, present %d, missing %d .\n",\r
++ p_bfi->whoami,\r
++ p_ext->cl_ext.vfptr_pnp_po->identity, p_ext->cl_ext.p_self_do,\r
++ p_ext, p_ext->b_present, p_ext->b_reported_missing ) );\r
+ continue;\r
+ }\r
+ if( p_ext->h_ca )\r
+@@ -400,15 +451,26 @@\r
+ /* Release the reference on the CA object. */\r
+ deref_al_obj( &p_ext->h_ca->obj );\r
+ }\r
+- BUS_TRACE( BUS_DBG_PNP, ("Deleted device %s: PDO %p, ext %p\n",\r
+- p_ext->cl_ext.vfptr_pnp_po->identity, p_ext->cl_ext.p_self_do, p_ext ) );\r
++\r
++ BUS_TRACE( BUS_DBG_PNP, ("%s Deleted device %s: PDO %p, ext %p\n",\r
++ p_bfi->whoami, p_ext->cl_ext.vfptr_pnp_po->identity,\r
++ p_ext->cl_ext.p_self_do, p_ext ) );\r
++\r
++ BUS_TRACE( BUS_DBG_PNP,("%s(%s) h_ca->obj.state %s refs %d\n",\r
++ __FUNCTION__, p_bfi->whoami,\r
++ get_obj_state_str(p_ext->h_ca->obj.state),\r
++ p_ext->h_ca->obj.ref_cnt)); // XXX\r
++\r
+ IoDeleteDevice( p_ext->cl_ext.p_self_do );\r
+ }\r
+ \r
+ cl_mutex_destroy( &gp_port_mgr->pdo_mutex );\r
+ cl_obj_deinit( p_obj );\r
+ cl_free( gp_port_mgr );\r
+- gp_port_mgr = NULL;\r
++\r
++ p_bfi->p_port_mgr = NULL;\r
++ p_bfi->p_port_mgr_obj = NULL;\r
++\r
+ BUS_EXIT( BUS_DBG_PNP );\r
+ }\r
+ \r
+@@ -417,22 +479,26 @@\r
+ * Register the load service for the given PnP class events.\r
+ */\r
+ ib_api_status_t\r
+-bus_reg_port_pnp( void )\r
++bus_reg_port_pnp( IN bus_filter_t *p_bfi )\r
+ {\r
+ ib_pnp_req_t pnp_req;\r
+- ib_api_status_t status;\r
++ ib_api_status_t status = IB_SUCCESS;\r
+ \r
+- cl_memclr( &pnp_req, sizeof( ib_pnp_req_t ) );\r
+- pnp_req.pnp_class = IB_PNP_PORT | IB_PNP_FLAG_REG_SYNC;\r
+- pnp_req.pnp_context = gp_port_mgr;\r
+- pnp_req.pfn_pnp_cb = port_mgr_pnp_cb;\r
+-\r
+- status = ib_reg_pnp( gh_al, &pnp_req, &gp_port_mgr->h_pnp );\r
+-\r
+- if( status == IB_SUCCESS )\r
+- {\r
+- /* Reference the load service on behalf of the ib_reg_pnp call. */\r
+- cl_obj_ref( &gp_port_mgr->obj );\r
++ /* only need to register for PNP once */\r
++ ExAcquireFastMutexUnsafe(&ControlMutex);\r
++ if ( !bus_globals.h_pnp_port ) {\r
++ cl_memclr( &pnp_req, sizeof( ib_pnp_req_t ) );\r
++ pnp_req.pnp_class = IB_PNP_PORT | IB_PNP_FLAG_REG_SYNC;\r
++ pnp_req.pnp_context = NULL;\r
++ pnp_req.pfn_pnp_cb = port_mgr_pnp_cb;\r
++\r
++ status = ib_reg_pnp( gh_al, &pnp_req, &bus_globals.h_pnp_port );\r
++ }\r
++ ExReleaseFastMutexUnsafe(&ControlMutex);\r
++\r
++ if( status == IB_SUCCESS ) {\r
++ /* Reference this bus filter's port load service */\r
++ cl_obj_ref( &p_bfi->p_port_mgr->obj );\r
+ }\r
+ \r
+ return status;\r
+@@ -446,12 +512,11 @@\r
+ port_mgr_pnp_cb(\r
+ IN ib_pnp_rec_t* p_pnp_rec )\r
+ {\r
+- ib_api_status_t status;\r
++ ib_api_status_t status=IB_SUCCESS;\r
+ \r
+ BUS_ENTER( BUS_DBG_PNP );\r
+ \r
+ CL_ASSERT( p_pnp_rec );\r
+- CL_ASSERT( gp_port_mgr == p_pnp_rec->pnp_context );\r
+ \r
+ switch( p_pnp_rec->pnp_event )\r
+ {\r
+@@ -461,12 +526,15 @@\r
+ \r
+ case IB_PNP_PORT_REMOVE:\r
+ port_mgr_port_remove( (ib_pnp_port_rec_t*)p_pnp_rec );\r
++ break;\r
+ \r
+ default:\r
+- status = IB_SUCCESS;\r
++ XBUS_PRINT( BUS_DBG_PNP, ("%s() Unhandled PNP Event %s\n",\r
++ __FUNCTION__, ib_get_pnp_event_str(p_pnp_rec->pnp_event) ));\r
+ break;\r
+ }\r
+ BUS_EXIT( BUS_DBG_PNP );\r
++\r
+ return status;\r
+ }\r
+ \r
+@@ -480,9 +548,50 @@\r
+ IN IRP* const p_irp )\r
+ {\r
+ NTSTATUS status;\r
++ bus_filter_t *p_bfi;\r
++ port_mgr_t *gp_port_mgr;\r
++ DEVICE_RELATIONS *p_rel;\r
+ \r
+ BUS_ENTER( BUS_DBG_PNP );\r
+ \r
++ BUS_PRINT(BUS_DBG_PNP, ("%s() ca_guid %I64x\n",__FUNCTION__,ca_guid));\r
++\r
++ /* special case guid == 0 - walk all bus filter instances */\r
++ if ( ca_guid == 0ULL ) {\r
++ for(p_bfi=bus_filters; p_bfi < &bus_filters[MAX_BUS_FILTERS]; p_bfi++) {\r
++ gp_port_mgr = p_bfi->p_port_mgr;\r
++ if ( !gp_port_mgr )\r
++ continue;\r
++ cl_mutex_acquire( &gp_port_mgr->pdo_mutex );\r
++ status = bus_get_relations( &gp_port_mgr->port_list,\r
++ ca_guid,\r
++ p_irp );\r
++ cl_mutex_release( &gp_port_mgr->pdo_mutex );\r
++ }\r
++\r
++ p_rel = (DEVICE_RELATIONS*)p_irp->IoStatus.Information;\r
++ if ( p_rel ) {\r
++ BUS_PRINT(BUS_DBG_PNP, ("%s() ca_guid 0 Reports %d\n",\r
++ __FUNCTION__,p_rel->Count));\r
++ }\r
++ BUS_EXIT( BUS_DBG_PNP );\r
++ return STATUS_SUCCESS;\r
++ }\r
++\r
++ p_bfi = get_bfi_by_ca_guid(ca_guid);\r
++ if (p_bfi == NULL) {\r
++ BUS_PRINT(BUS_DBG_PNP,\r
++ ("%s() Null *p_bfi from ca_guid %I64x\n",__FUNCTION__,ca_guid));\r
++ BUS_EXIT( BUS_DBG_PNP );\r
++ return STATUS_NO_SUCH_DEVICE;\r
++ }\r
++ gp_port_mgr = p_bfi->p_port_mgr;\r
++\r
++ BUS_PRINT(BUS_DBG_PNP, ("%s(%s) for ca_guid %I64x port_mgr %p\n",\r
++ __FUNCTION__, p_bfi->whoami, ca_guid, gp_port_mgr) );\r
++ if (!gp_port_mgr)\r
++ return STATUS_NO_SUCH_DEVICE;\r
++\r
+ cl_mutex_acquire( &gp_port_mgr->pdo_mutex );\r
+ status = bus_get_relations( &gp_port_mgr->port_list, ca_guid, p_irp );\r
+ cl_mutex_release( &gp_port_mgr->pdo_mutex );\r
+@@ -493,15 +602,19 @@\r
+ \r
+ static ib_api_status_t\r
+ __port_was_hibernated(\r
+- IN ib_pnp_port_rec_t* p_pnp_rec )\r
++ IN ib_pnp_port_rec_t* p_pnp_rec,\r
++ IN bus_filter_t* p_bfi )\r
+ {\r
+ NTSTATUS status;\r
+- cl_list_item_t *p_list_item;\r
++ cl_list_item_t *p_list_item;\r
+ bus_port_ext_t *p_port_ext;\r
+ bus_pdo_ext_t *p_pdo_ext = NULL;\r
+ size_t n_devs = 0;\r
++ port_mgr_t *gp_port_mgr = p_bfi->p_port_mgr;\r
+ cl_qlist_t* p_pdo_list = &gp_port_mgr->port_list;\r
+ \r
++ port_pnp_ctx_t *p_ctx = p_pnp_rec->pnp_rec.context;\r
++\r
+ BUS_ENTER( BUS_DBG_PNP );\r
+ \r
+ cl_mutex_acquire( &gp_port_mgr->pdo_mutex );\r
+@@ -521,9 +634,11 @@\r
+ break;\r
+ }\r
+ \r
+- BUS_TRACE( BUS_DBG_PNP, \r
+- ("Skipped PDO for %s: PDO %p, ext %p, present %d, missing %d, hibernating %d, port_guid %I64x.\n",\r
+- p_pdo_ext->cl_ext.vfptr_pnp_po->identity, p_pdo_ext->cl_ext.p_self_do, \r
++ BUS_TRACE( BUS_DBG_PNP, ("%s Skipped PDO for %s: PDO %p, ext %p, "\r
++ "present %d, missing %d, hibernating %d, port_guid %I64x.\n",\r
++ p_bfi->whoami,\r
++ p_pdo_ext->cl_ext.vfptr_pnp_po->identity,\r
++ p_pdo_ext->cl_ext.p_self_do, \r
+ p_pdo_ext, p_pdo_ext->b_present, p_pdo_ext->b_reported_missing, \r
+ p_pdo_ext->b_hibernating, p_port_ext->port_guid.guid ) );\r
+ }\r
+@@ -534,27 +649,33 @@\r
+ p_pdo_ext->h_ca = acquire_ca( p_pnp_rec->p_ca_attr->ca_guid );\r
+ if( !p_pdo_ext->h_ca )\r
+ {\r
+- BUS_TRACE( BUS_DBG_ERROR, ("acquire_ca failed to find CA by guid %I64x\n",\r
+- p_pnp_rec->p_ca_attr->ca_guid ) );\r
++ BUS_TRACE( BUS_DBG_ERROR,\r
++ ("%s acquire_ca failed to find CA by guid %I64x\n",\r
++ p_bfi->whoami, p_pnp_rec->p_ca_attr->ca_guid ) );\r
+ status = IB_INVALID_GUID;\r
+ }\r
+ else \r
+ {\r
+ p_pdo_ext->b_hibernating = FALSE;\r
+- p_pnp_rec->pnp_rec.context = p_pdo_ext;\r
++\r
++ CL_ASSERT( p_ctx );\r
++ p_ctx->p_pdo_ext = p_pdo_ext; // save for port_mgr_port_remove\r
++\r
+ status = IB_SUCCESS;\r
+ p_port_ext = (bus_port_ext_t*)p_pdo_ext;\r
+- BUS_TRACE( BUS_DBG_PNP, \r
+- ("Found PDO for %s: PDO %p, ext %p, present %d, missing %d, hibernating %d, port_guid %I64x.\n",\r
+- p_pdo_ext->cl_ext.vfptr_pnp_po->identity, p_pdo_ext->cl_ext.p_self_do, \r
++ BUS_TRACE( BUS_DBG_PNP, ("%s Found PDO for %s: PDO %p, ext %p, "\r
++ "present %d, missing %d, hibernating %d, port_guid %I64x.\n",\r
++ p_bfi->whoami,\r
++ p_pdo_ext->cl_ext.vfptr_pnp_po->identity,\r
++ p_pdo_ext->cl_ext.p_self_do, \r
+ p_pdo_ext, p_pdo_ext->b_present, p_pdo_ext->b_reported_missing, \r
+ p_pdo_ext->b_hibernating, p_port_ext->port_guid.guid ) );\r
+ }\r
+ }\r
+ else \r
+ {\r
+- BUS_TRACE( BUS_DBG_PNP, ("Failed to find PDO for guid %I64x .\n",\r
+- p_pnp_rec->p_ca_attr->ca_guid ) );\r
++ BUS_TRACE( BUS_DBG_PNP, ("%s Failed to find PDO for guid %I64x .\n",\r
++ p_bfi->whoami, p_pnp_rec->p_ca_attr->ca_guid ) );\r
+ status = IB_NOT_FOUND;\r
+ }\r
+ \r
+@@ -564,6 +685,69 @@\r
+ return status;\r
+ }\r
+ \r
++\r
++void\r
++dump_pnp_port_rec( ib_pnp_port_rec_t* pr )\r
++{\r
++ BUS_PRINT( BUS_DBG_PNP, ("%s() ib_pnp_port_rec_t* @ %p\nib_pnp_rec_t*:\n",\r
++ __FUNCTION__,pr));\r
++\r
++\r
++ BUS_PRINT( BUS_DBG_PNP, (" Event %s\n",\r
++ ib_get_pnp_event_str(pr->pnp_rec.pnp_event) ));\r
++\r
++ BUS_PRINT( BUS_DBG_PNP, (" pnp_context %p\n",pr->pnp_rec.pnp_context));\r
++ BUS_PRINT( BUS_DBG_PNP, (" context %p\n",pr->pnp_rec.context));\r
++ BUS_PRINT( BUS_DBG_PNP, (" guid %I64x\n",pr->pnp_rec.guid));\r
++ BUS_PRINT( BUS_DBG_PNP, (" ca_guid %I64x\n",pr->pnp_rec.ca_guid));\r
++\r
++ if ( !pr->p_ca_attr ) {\r
++ BUS_PRINT( BUS_DBG_PNP, (" NULL *p_ca_attr ?\n"));\r
++ }\r
++ else {\r
++ BUS_PRINT( BUS_DBG_PNP, ("*p_ca_attr\n"));\r
++ BUS_PRINT( BUS_DBG_PNP, (" ca_guid 0x%I64x\n",\r
++ pr->p_ca_attr->ca_guid ) );\r
++ }\r
++ if ( !pr->p_port_attr ) {\r
++ BUS_PRINT( BUS_DBG_PNP, (" NULL *p_port_attr?\n"));\r
++ }\r
++ else {\r
++ BUS_PRINT( BUS_DBG_PNP, ("*p_port_attr:\n"));\r
++ BUS_PRINT( BUS_DBG_PNP, (" port_guid 0x%I64x port_num %d\n",\r
++ pr->p_port_attr->port_guid,\r
++ pr->p_port_attr->port_num ));\r
++ }\r
++}\r
++\r
++void\r
++dump_pnp_iou_rec( ib_pnp_iou_rec_t* pr )\r
++{\r
++ BUS_PRINT( BUS_DBG_PNP, ("%s() ib_pnp_iou_rec_t* @ %p\nib_pnp_rec_t*:\n",\r
++ __FUNCTION__,pr));\r
++\r
++\r
++ BUS_PRINT( BUS_DBG_PNP, (" Event %s\n",\r
++ ib_get_pnp_event_str(pr->pnp_rec.pnp_event) ));\r
++\r
++ BUS_PRINT( BUS_DBG_PNP, (" pnp_context %p\n",pr->pnp_rec.pnp_context));\r
++ BUS_PRINT( BUS_DBG_PNP, (" context %p\n",pr->pnp_rec.context));\r
++ BUS_PRINT( BUS_DBG_PNP, (" guid %I64x\n",pr->pnp_rec.guid));\r
++ BUS_PRINT( BUS_DBG_PNP, (" ca_guid %I64x\n",pr->pnp_rec.ca_guid));\r
++\r
++ BUS_PRINT( BUS_DBG_PNP, ("pnp_iou_rec_t:\n" ));\r
++ BUS_PRINT( BUS_DBG_PNP,\r
++ (" guid 0x%I64x\n ca_guid %I64x\n chassis_guid %I64x\n",\r
++ pr->guid, pr->ca_guid, pr->chassis_guid ));\r
++ BUS_PRINT( BUS_DBG_PNP,\r
++ (" slot 0x%x\n vend_id 0x%x\n dev_id 0x%x revision 0x%x\n",\r
++ pr->slot, pr->vend_id, pr->dev_id, pr->revision ));\r
++ if ( pr->desc[0] ) {\r
++ BUS_PRINT( BUS_DBG_PNP, (" Desc %s\n",pr->desc ));\r
++ }\r
++}\r
++\r
++\r
+ ib_api_status_t\r
+ port_mgr_port_add(\r
+ IN ib_pnp_port_rec_t* p_pnp_rec )\r
+@@ -573,18 +757,56 @@\r
+ uint8_t num_pdo;\r
+ bus_port_ext_t *p_port_ext;\r
+ ib_net16_t pdo_cnt;\r
++ bus_filter_t *p_bfi;\r
++ port_mgr_t *gp_port_mgr;\r
++ port_pnp_ctx_t *p_ctx = p_pnp_rec->pnp_rec.context;\r
++\r
+ BUS_ENTER( BUS_DBG_PNP );\r
+ \r
++ CL_ASSERT( p_pnp_rec->p_ca_attr->ca_guid );\r
++\r
++ p_bfi = get_set_bfi_by_ca_guid( p_pnp_rec->p_ca_attr->ca_guid );\r
++ if ( !p_bfi ) {\r
++ BUS_PRINT( BUS_DBG_PNP,("%s() NULL p_bfi? ca_guid 0x%I64x\n",\r
++ __FUNCTION__, p_pnp_rec->p_ca_attr->ca_guid ) );\r
++ return IB_ERROR;\r
++ }\r
++\r
++ /*\r
++ * Allocate a PNP context for this object. pnp_rec.context is obj unique.\r
++ */\r
++ if ( !p_ctx ) {\r
++ p_ctx = cl_zalloc( sizeof(*p_ctx) );\r
++ if( !p_ctx )\r
++ {\r
++ BUS_PRINT(BUS_DBG_PNP,\r
++ ("%s(%s) ca_guid %I64x port(%d) BAD alloc PNP context\n",\r
++ __FUNCTION__, p_bfi->whoami, p_bfi->ca_guid, \r
++ p_pnp_rec->p_port_attr->port_num));\r
++ return IB_ERROR;\r
++ }\r
++ p_ctx->p_bus_filter = p_bfi;\r
++ p_ctx->port_num = p_pnp_rec->p_port_attr->port_num;\r
++ p_pnp_rec->pnp_rec.context = p_ctx;\r
++\r
++ BUS_PRINT(BUS_DBG_PNP,\r
++ ("%s(%s) ca_guid %I64x port %d ALLOC p_ctx @ %p\n",\r
++ __FUNCTION__, p_bfi->whoami, p_bfi->ca_guid, \r
++ p_pnp_rec->p_port_attr->port_num,p_ctx));\r
++ }\r
++ gp_port_mgr = p_bfi->p_port_mgr;\r
++\r
+ if( !bus_globals.b_report_port_nic )\r
+ {\r
+ BUS_EXIT( BUS_DBG_PNP );\r
+ return IB_NOT_DONE;\r
+ }\r
+ \r
+- /* Upon hibernating of the computer IB_BUS driver doesn't remove PDO, but\r
++ /* Upon hibernating the computer IB_BUS driver doesn't remove PDO, but\r
+ marks with a flag. So we first try to find an existing PDO for this port,\r
+- marked with this flag. If it was found, we turn off the flag and use this PDO */\r
+- status = __port_was_hibernated(p_pnp_rec);\r
++ marked with this flag. If it was found, we turn off the flag and use\r
++ this PDO */\r
++ status = __port_was_hibernated( p_pnp_rec, p_bfi );\r
+ if( status != IB_NOT_FOUND )\r
+ {\r
+ BUS_EXIT( BUS_DBG_PNP );\r
+@@ -600,73 +822,82 @@\r
+ \r
+ for (num_pdo = 0; num_pdo < pdo_cnt; num_pdo++)\r
+ {\r
+- /* Create the PDO for the new port device. */\r
+- status = IoCreateDevice( bus_globals.p_driver_obj, sizeof(bus_port_ext_t),\r
+- NULL, FILE_DEVICE_CONTROLLER,\r
+- FILE_DEVICE_SECURE_OPEN | FILE_AUTOGENERATED_DEVICE_NAME,\r
+- FALSE, &p_pdo[num_pdo] );\r
+- if( !NT_SUCCESS( status ) )\r
+- {\r
+- BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
+- ("IoCreateDevice returned %08x.\n", status) );\r
+- return IB_ERROR;\r
+- }\r
++ /* Create the PDO for the new port device. */\r
++ status = IoCreateDevice( bus_globals.p_driver_obj,\r
++ sizeof(bus_port_ext_t),\r
++ NULL, FILE_DEVICE_CONTROLLER,\r
++ FILE_DEVICE_SECURE_OPEN |\r
++ FILE_AUTOGENERATED_DEVICE_NAME,\r
++ FALSE, &p_pdo[num_pdo] );\r
++ if( !NT_SUCCESS( status ) )\r
++ {\r
++ BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
++ ("IoCreateDevice returned %08x.\n", status) );\r
++ return IB_ERROR;\r
++ }\r
+ \r
+- /* Initialize the device extension. */\r
+- cl_init_pnp_po_ext( p_pdo[num_pdo], NULL, p_pdo[num_pdo], bus_globals.dbg_lvl,\r
+- &vfptr_port_pnp, &vfptr_port_query_txt );\r
++ /* Initialize the device extension. */\r
++ cl_init_pnp_po_ext( p_pdo[num_pdo], NULL, p_pdo[num_pdo],\r
++ bus_globals.dbg_lvl, &vfptr_port_pnp,\r
++ &vfptr_port_query_txt );\r
+ \r
+- /* Set the DO_BUS_ENUMERATED_DEVICE flag to mark it as a PDO. */\r
++ /* Set the DO_BUS_ENUMERATED_DEVICE flag to mark it as a PDO. */\r
+ p_pdo[num_pdo]->Flags |= DO_BUS_ENUMERATED_DEVICE;\r
+ \r
+ p_port_ext = p_pdo[num_pdo]->DeviceExtension;\r
+- p_port_ext->pdo.dev_po_state.DeviceState = PowerDeviceD0;\r
+- p_port_ext->pdo.p_parent_ext = bus_globals.p_bus_ext;\r
+- p_port_ext->pdo.b_present = TRUE;\r
+- p_port_ext->pdo.b_reported_missing = FALSE;\r
+- p_port_ext->pdo.b_hibernating = FALSE;\r
+- p_port_ext->pdo.p_po_work_item = NULL;\r
+- BUS_TRACE( BUS_DBG_PNP, ("Created device for %s: PDO %p,ext %p, present %d, missing %d .\n",\r
+- p_port_ext->pdo.cl_ext.vfptr_pnp_po->identity, p_pdo[num_pdo], p_port_ext, p_port_ext->pdo.b_present, \r
+- p_port_ext->pdo.b_reported_missing ) );\r
++ p_port_ext->pdo.dev_po_state.DeviceState = PowerDeviceD0;\r
++ p_port_ext->pdo.p_parent_ext = p_bfi->p_bus_ext;\r
++ p_port_ext->pdo.b_present = TRUE;\r
++ p_port_ext->pdo.b_reported_missing = FALSE;\r
++ p_port_ext->pdo.b_hibernating = FALSE;\r
++ p_port_ext->pdo.p_po_work_item = NULL;\r
++ BUS_TRACE( BUS_DBG_PNP,\r
++ ("Created %s %s: PDO %p,ext %p, present %d, missing %d .\n",\r
++ p_bfi->whoami,\r
++ p_port_ext->pdo.cl_ext.vfptr_pnp_po->identity, p_pdo[num_pdo],\r
++ p_port_ext, p_port_ext->pdo.b_present,\r
++ p_port_ext->pdo.b_reported_missing ) );\r
+ \r
+- /* Cache the CA GUID. */\r
+- p_port_ext->pdo.ca_guid = p_pnp_rec->p_ca_attr->ca_guid;\r
++ /* Cache the CA GUID. */\r
++ p_port_ext->pdo.ca_guid = p_pnp_rec->p_ca_attr->ca_guid;\r
+ \r
+- /* Take a reference on the parent HCA. */\r
++ /* Take a reference on the parent HCA. */\r
+ if(num_pdo > 0)\r
+ {\r
+ p_port_ext->pdo.h_ca = ((bus_port_ext_t*)p_pdo[0]->DeviceExtension)->pdo.h_ca;\r
+ }\r
+ else\r
+- p_port_ext->pdo.h_ca = acquire_ca( p_pnp_rec->p_ca_attr->ca_guid );\r
+- if( !p_port_ext->pdo.h_ca )\r
+- {\r
++ p_port_ext->pdo.h_ca = acquire_ca( p_pnp_rec->p_ca_attr->ca_guid );\r
++\r
++ if( !p_port_ext->pdo.h_ca )\r
++ {\r
+ BUS_TRACE( BUS_DBG_PNP, ("Deleted device: PDO %p\n", p_pdo[num_pdo]));\r
+ IoDeleteDevice( p_pdo[num_pdo]);\r
+- BUS_TRACE_EXIT( BUS_DBG_ERROR, ("acquire_ca failed to find CA.\n") );\r
+- return IB_INVALID_GUID;\r
+- }\r
++ BUS_TRACE_EXIT( BUS_DBG_ERROR, ("acquire_ca failed to find CA.\n") );\r
++ return IB_INVALID_GUID;\r
++ }\r
+ p_port_ext->port_guid.guid = p_pnp_rec->p_port_attr->port_guid;\r
+- p_port_ext->n_port = p_pnp_rec->p_port_attr->port_num;\r
++ p_port_ext->n_port = p_pnp_rec->p_port_attr->port_num;\r
+ p_port_ext->port_guid.pkey = IB_DEFAULT_PKEY;\r
++ p_port_ext->n_ifc_ref = 0;\r
+ \r
+ if(num_pdo > 0)\r
+ {\r
+ p_port_ext->port_guid.pkey = g_pkeys.pkey_array[num_pdo -1];\r
+ }\r
+- /* Store the device extension in the port vector for future queries. */\r
+- cl_mutex_acquire( &gp_port_mgr->pdo_mutex );\r
+- cl_qlist_insert_tail( &gp_port_mgr->port_list,\r
+- &p_port_ext->pdo.list_item );\r
+- cl_mutex_release( &gp_port_mgr->pdo_mutex );\r
+ \r
+- /*\r
+- * Set the context of the PNP event. The context is passed in for future\r
+- * events on the same port.\r
+- */\r
++ /* Store the device extension in the port vector for future queries. */\r
++ cl_mutex_acquire( &gp_port_mgr->pdo_mutex );\r
++ cl_qlist_insert_tail( &gp_port_mgr->port_list,\r
++ &p_port_ext->pdo.list_item );\r
++ cl_mutex_release( &gp_port_mgr->pdo_mutex );\r
++\r
++ /*\r
++ * save the port_ext, as the context is passed in for future events on\r
++ * the same port.\r
++ */\r
+ if(num_pdo == 0)\r
+- p_pnp_rec->pnp_rec.context = p_port_ext;\r
++ p_ctx->p_pdo_ext = p_port_ext;\r
+ }\r
+ pkeys_enumerated = TRUE;\r
+ \r
+@@ -674,9 +905,11 @@\r
+ IoInvalidateDeviceRelations(\r
+ p_port_ext->pdo.h_ca->obj.p_ci_ca->verbs.p_hca_dev, BusRelations );\r
+ \r
++#if 0 // XXX\r
+ /* Invalidate removal relations for the bus driver. */\r
+- IoInvalidateDeviceRelations(\r
+- bus_globals.p_bus_ext->cl_ext.p_pdo, RemovalRelations );\r
++ IoInvalidateDeviceRelations( p_bfi->p_bus_ext->cl_ext.p_pdo,\r
++ RemovalRelations );\r
++#endif\r
+ \r
+ BUS_EXIT( BUS_DBG_PNP );\r
+ return IB_SUCCESS;\r
+@@ -697,10 +930,14 @@\r
+ bus_port_ext_t *p_port_ext, *pkey_port_ext;\r
+ DEVICE_OBJECT *p_pdo[MAX_NUM_PKEY];\r
+ bus_pdo_ext_t *p_pdo_ext = NULL;\r
+- cl_qlist_t* p_pdo_list = &gp_port_mgr->port_list;\r
++ cl_qlist_t* p_pdo_list;\r
++ bus_filter_t *p_bfi = &bus_filters[0];// pass in ca_guid? | all CA's?\r
++ port_mgr_t *gp_port_mgr;\r
+ \r
+ BUS_ENTER( BUS_DBG_PNP );\r
+ \r
++ gp_port_mgr = p_bfi->p_port_mgr; \r
++ p_pdo_list = &gp_port_mgr->port_list;\r
+ p_port_ext = NULL;\r
+ cl_mutex_acquire( &gp_port_mgr->pdo_mutex );\r
+ \r
+@@ -720,18 +957,19 @@\r
+ if (!p_port_ext)\r
+ {\r
+ BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
+- ("No existed pdo found.\n") );\r
++ ("No existing pdo found.\n") );\r
+ return CL_ERROR;\r
+ }\r
+ \r
+ for (cnt = 0; cnt < pkeys->pkey_num; cnt++)\r
+ {\r
+-\r
+ /* Create the PDO for the new port device. */\r
+- status = IoCreateDevice( bus_globals.p_driver_obj, sizeof(bus_port_ext_t),\r
+- NULL, FILE_DEVICE_CONTROLLER,\r
+- FILE_DEVICE_SECURE_OPEN | FILE_AUTOGENERATED_DEVICE_NAME,\r
+- FALSE, &p_pdo[cnt] );\r
++ status = IoCreateDevice( bus_globals.p_driver_obj,\r
++ sizeof(bus_port_ext_t),\r
++ NULL, FILE_DEVICE_CONTROLLER,\r
++ FILE_DEVICE_SECURE_OPEN\r
++ | FILE_AUTOGENERATED_DEVICE_NAME,\r
++ FALSE, &p_pdo[cnt] );\r
+ if( !NT_SUCCESS( status ) )\r
+ {\r
+ BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
+@@ -741,20 +979,22 @@\r
+ \r
+ /* Initialize the device extension. */\r
+ cl_init_pnp_po_ext( p_pdo[cnt], NULL, p_pdo[cnt], bus_globals.dbg_lvl,\r
+- &vfptr_port_pnp, &vfptr_port_query_txt );\r
++ &vfptr_port_pnp, &vfptr_port_query_txt );\r
+ \r
+ /* Set the DO_BUS_ENUMERATED_DEVICE flag to mark it as a PDO. */\r
+ p_pdo[cnt]->Flags |= DO_BUS_ENUMERATED_DEVICE;\r
+ \r
+ pkey_port_ext = p_pdo[cnt]->DeviceExtension;\r
+ pkey_port_ext->pdo.dev_po_state.DeviceState = PowerDeviceD0;\r
+- pkey_port_ext->pdo.p_parent_ext = bus_globals.p_bus_ext;\r
++ pkey_port_ext->pdo.p_parent_ext = p_bfi->p_bus_ext;\r
+ pkey_port_ext->pdo.b_present = TRUE;\r
+ pkey_port_ext->pdo.b_reported_missing = FALSE;\r
+ pkey_port_ext->pdo.b_hibernating = FALSE;\r
+ pkey_port_ext->pdo.p_po_work_item = NULL;\r
+- BUS_TRACE( BUS_DBG_PNP, ("Created device for %s: PDO %p,ext %p, present %d, missing %d .\n",\r
+- pkey_port_ext->pdo.cl_ext.vfptr_pnp_po->identity, p_pdo[cnt], pkey_port_ext, pkey_port_ext->pdo.b_present, \r
++ BUS_TRACE( BUS_DBG_PNP,\r
++ ("Created device for %s: PDO %p,ext %p, present %d, missing %d\n",\r
++ pkey_port_ext->pdo.cl_ext.vfptr_pnp_po->identity, p_pdo[cnt],\r
++ pkey_port_ext, pkey_port_ext->pdo.b_present, \r
+ pkey_port_ext->pdo.b_reported_missing ) );\r
+ \r
+ /* Cache the CA GUID. */\r
+@@ -775,9 +1015,11 @@\r
+ IoInvalidateDeviceRelations(\r
+ p_port_ext->pdo.h_ca->obj.p_ci_ca->verbs.p_hca_dev, BusRelations );\r
+ \r
++#if 0 // XXX\r
+ /* Invalidate removal relations for the bus driver. */\r
+- IoInvalidateDeviceRelations(\r
+- bus_globals.p_bus_ext->cl_ext.p_pdo, RemovalRelations );\r
++ IoInvalidateDeviceRelations( p_bfi->p_bus_ext->cl_ext.p_pdo,\r
++ RemovalRelations );\r
++#endif\r
+ \r
+ BUS_EXIT( BUS_DBG_PNP );\r
+ return CL_SUCCESS;\r
+@@ -785,48 +1027,108 @@\r
+ \r
+ void\r
+ port_mgr_port_remove(\r
+- IN ib_pnp_port_rec_t* p_pnp_rec )\r
++ IN ib_pnp_port_rec_t* p_pnp_rec )\r
+ {\r
+ bus_pdo_ext_t *p_ext;\r
++ port_mgr_t *gp_port_mgr;\r
++ bus_filter_t *p_bfi;\r
++ port_pnp_ctx_t *p_ctx = p_pnp_rec->pnp_rec.context;\r
+ \r
+ BUS_ENTER( BUS_DBG_PNP );\r
+ \r
+- /* The PNP record's context is the port extension. */\r
+- p_ext = p_pnp_rec->pnp_rec.context;\r
++ if ( !p_ctx ) {\r
++ BUS_EXIT( BUS_DBG_PNP );\r
++ return;\r
++ }\r
++\r
++ CL_ASSERT( p_ctx->p_bus_filter->magic == BFI_MAGIC );\r
++ p_bfi = p_ctx->p_bus_filter;\r
++ CL_ASSERT( p_bfi );\r
++\r
++ BUS_PRINT(BUS_DBG_PNP,("%s(%s) ca_guid 0x%I64x port_num %d port_mgr %p\n",\r
++ __FUNCTION__, p_bfi->whoami, p_bfi->ca_guid,\r
++ p_ctx->port_num, p_bfi->p_port_mgr));\r
++\r
++ /* in the process of device remove, port_mgr has been destroyed.\r
++ * cleanup allocated PNP port context; one per port.\r
++ * The issue is the PNP PORT_REMOVE event occurs after\r
++ * fdo_release_resources() completes.\r
++ */\r
++ if ( p_bfi->ca_guid == 0ULL || !p_bfi->p_port_mgr ) {\r
++ cl_free( p_ctx );\r
++ p_pnp_rec->pnp_rec.context = NULL;\r
++ BUS_EXIT( BUS_DBG_PNP );\r
++ return;\r
++ }\r
++\r
++ gp_port_mgr = p_bfi->p_port_mgr;\r
++\r
++ /* Within the PNP record's context is the port extension ptr;\r
++ * see port_was_hibernated().\r
++ */\r
++ p_ext = p_ctx->p_pdo_ext;\r
+ CL_ASSERT( p_ext );\r
+ \r
++ CL_ASSERT(p_bfi == p_ext->p_parent_ext->bus_filter);\r
++#if DBG // XXX\r
++ if (p_bfi != p_ext->p_parent_ext->bus_filter) {\r
++ BUS_PRINT(BUS_DBG_PNP,\r
++ ("%s() p_bfi(%p) != p_ext->bus_filter(%p) line %d file %s\n",\r
++ __FUNCTION__,p_bfi,p_ext->p_parent_ext->bus_filter,\r
++ __LINE__,__FILE__));\r
++ }\r
++#endif\r
++\r
+ /*\r
+ * Flag the port PDO as no longer being present. We have to wait until\r
+ * the PnP manager removes it to clean up. However, we do release the\r
+ * reference on the CA object in order to allow the removal of the HCA\r
+ * to proceed should it occur before the port's PDO is cleaned up.\r
+ */\r
++ if ( !p_ext->h_ca )\r
++ {\r
++ BUS_TRACE( BUS_DBG_PNP, ("%s() %s NULL h_ca? p_ext %p\n",\r
++ __FUNCTION__, p_bfi->whoami, p_ext ) );\r
++ return;\r
++ }\r
++\r
+ cl_mutex_acquire( &gp_port_mgr->pdo_mutex );\r
+ CL_ASSERT( p_ext->h_ca );\r
+ \r
+ if( p_ext->b_hibernating )\r
+ {\r
+- BUS_TRACE( BUS_DBG_PNP, ("Skip port removing for %s: PDO %p, ext %p, present %d, missing %d, hibernating %d .\n",\r
+- p_ext->cl_ext.vfptr_pnp_po->identity, p_ext->cl_ext.p_self_do, p_ext, p_ext->b_present, \r
+- p_ext->b_reported_missing, p_ext->b_hibernating ) );\r
++ BUS_TRACE( BUS_DBG_PNP, ("Skip port removing for %s: PDO %p, ext %p, "\r
++ "present %d, missing %d, hibernating %d .\n",\r
++ p_ext->cl_ext.vfptr_pnp_po->identity, p_ext->cl_ext.p_self_do,\r
++ p_ext, p_ext->b_present, p_ext->b_reported_missing,\r
++ p_ext->b_hibernating ) );\r
+ goto hca_deref;\r
+ }\r
+ \r
+ p_ext->b_present = FALSE;\r
+- BUS_TRACE( BUS_DBG_PNP, ("Mark removing %s: PDO %p, ext %p, present %d, missing %d .\n",\r
+- p_ext->cl_ext.vfptr_pnp_po->identity, p_ext->cl_ext.p_self_do, p_ext, p_ext->b_present, p_ext->b_reported_missing ) );\r
++ p_ext->b_reported_missing = TRUE;\r
+ \r
++ BUS_TRACE( BUS_DBG_PNP,\r
++ ("Mark removing %s: PDO %p, ext %p, present %d, missing %d .\n",\r
++ p_ext->cl_ext.vfptr_pnp_po->identity, p_ext->cl_ext.p_self_do, p_ext,\r
++ p_ext->b_present, p_ext->b_reported_missing ) );\r
++\r
++#if 0 // XXX\r
+ /* Invalidate removal relations for the bus driver. */\r
+- IoInvalidateDeviceRelations( bus_globals.p_bus_ext->cl_ext.p_pdo,\r
+- RemovalRelations );\r
++ IoInvalidateDeviceRelations( p_bfi->p_bus_ext->cl_ext.p_pdo,\r
++ RemovalRelations );\r
++#endif\r
+ \r
+ /* Invalidate bus relations for the HCA. */\r
+ IoInvalidateDeviceRelations(\r
+ p_ext->h_ca->obj.p_ci_ca->verbs.p_hca_dev, BusRelations );\r
+ \r
++ /* Free PNP context memory */\r
++ cl_free( p_ctx );\r
++ p_pnp_rec->pnp_rec.context = NULL;\r
++\r
+ hca_deref:\r
+ deref_al_obj( &p_ext->h_ca->obj );\r
+- p_ext->h_ca = NULL;\r
+ cl_mutex_release( &gp_port_mgr->pdo_mutex );\r
+ \r
+ BUS_EXIT( BUS_DBG_PNP );\r
+@@ -850,7 +1152,9 @@\r
+ /* Notify the Power Manager that the device is started. */\r
+ PoSetPowerState( p_dev_obj, DevicePowerState, p_ext->dev_po_state );\r
+ *p_action = IrpComplete;\r
++\r
+ BUS_EXIT( BUS_DBG_PNP );\r
++\r
+ return STATUS_SUCCESS;\r
+ }\r
+ \r
+@@ -869,6 +1173,9 @@\r
+ \r
+ p_ext = p_dev_obj->DeviceExtension;\r
+ \r
++BUS_PRINT( BUS_DBG_PNP, ("%s() %p->n_ifc_ref %d\n",\r
++ __FUNCTION__,p_ext,p_ext->n_ifc_ref ));\r
++\r
+ *p_action = IrpComplete;\r
+ if( p_ext->n_ifc_ref )\r
+ {\r
+@@ -895,14 +1202,17 @@\r
+ {\r
+ bus_port_ext_t *p_ext;\r
+ POWER_STATE po_state;\r
++ port_mgr_t *gp_port_mgr;\r
+ \r
+ BUS_ENTER( BUS_DBG_PNP );\r
+ \r
+ p_ext = p_dev_obj->DeviceExtension;\r
++ gp_port_mgr = p_ext->pdo.p_parent_ext->bus_filter->p_port_mgr;\r
+ \r
+ /* Remove this PDO from its list. */\r
+ cl_mutex_acquire( &gp_port_mgr->pdo_mutex );\r
+- BUS_TRACE( BUS_DBG_PNP, ("Removing port from vector: PDO %p, ext %p\n", p_dev_obj, p_ext) );\r
++ BUS_TRACE( BUS_DBG_PNP, ("Removing port from vector: PDO %p, ext %p\n",\r
++ p_dev_obj, p_ext) );\r
+ cl_qlist_remove_item( &gp_port_mgr->port_list, &p_ext->pdo.list_item );\r
+ cl_mutex_release( &gp_port_mgr->pdo_mutex );\r
+ po_state.DeviceState = PowerDeviceD3;\r
+@@ -932,7 +1242,9 @@\r
+ cl_set_pnp_state( &p_ext->pdo.cl_ext, NotStarted );\r
+ /* Don't delete the device. It may simply be disabled. */\r
+ *p_action = IrpComplete;\r
+- BUS_TRACE_EXIT( BUS_DBG_PNP, ("Device still present: PDO %p, ext %p\n", p_dev_obj, p_ext) );\r
++ BUS_TRACE_EXIT( BUS_DBG_PNP,\r
++ ("Device %s still present: PDO %p, ext %p\n",\r
++ p_ext->pdo.cl_ext.vfptr_pnp_po->identity, p_dev_obj, p_ext) );\r
+ return STATUS_SUCCESS;\r
+ }\r
+ \r
+@@ -941,7 +1253,10 @@\r
+ /* Reset the state to RemovePending. Complib set it to Deleted. */\r
+ cl_rollback_pnp_state( &p_ext->pdo.cl_ext );\r
+ *p_action = IrpComplete;\r
+- BUS_TRACE_EXIT( BUS_DBG_PNP, ("Device not reported missing yet: PDO %p, ext %p\n", p_dev_obj, p_ext) );\r
++ BUS_TRACE_EXIT( BUS_DBG_PNP,\r
++ ("Device %s not reported missing yet: PDO %p, ext %p\n",\r
++ p_ext->pdo.cl_ext.vfptr_pnp_po->identity,\r
++ p_dev_obj, p_ext) );\r
+ return STATUS_SUCCESS;\r
+ }\r
+ \r
+@@ -955,8 +1270,9 @@\r
+ p_irp->IoStatus.Status = STATUS_SUCCESS;\r
+ IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
+ \r
+- BUS_TRACE( BUS_DBG_PNP, ("Deleted device %s: PDO %p(=%p), ext %p\n",\r
+- p_ext->pdo.cl_ext.vfptr_pnp_po->identity, p_ext->pdo.cl_ext.p_self_do, p_dev_obj, p_ext ) );\r
++ BUS_PRINT/*XXX TRACE*/( BUS_DBG_PNP, ("Deleted device %s: PDO %p(=%p), ext %p\n",\r
++ p_ext->pdo.cl_ext.vfptr_pnp_po->identity, p_ext->pdo.cl_ext.p_self_do,\r
++ p_dev_obj, p_ext ) );\r
+ IoDeleteDevice( p_dev_obj );\r
+ \r
+ *p_action = IrpDoNothing;\r
+@@ -1382,7 +1698,6 @@\r
+ ipoib_ifc_data_t *p_ipoib_data;\r
+ bus_port_ext_t *p_ext;\r
+ const GUID *p_guid;\r
+- \r
+ \r
+ BUS_ENTER( BUS_DBG_PNP );\r
+ \r
+@@ -1455,6 +1770,9 @@\r
+ p_ipoib_data->port_guid = p_ext->port_guid;\r
+ p_ipoib_data->port_num = (uint8_t)p_ext->n_port;\r
+ \r
++ BUS_TRACE_EXIT( BUS_DBG_PNP,\r
++ (" %p->n_ifc_ref %d\n",p_ext,p_ext->n_ifc_ref) ); //XXX\r
++\r
+ BUS_EXIT( BUS_DBG_PNP );\r
+ return STATUS_SUCCESS;\r
+ }\r
+@@ -1472,9 +1790,7 @@\r
+ \r
+ BUS_ENTER( BUS_DBG_PNP );\r
+ \r
+-#pragma warning( push, 3 )\r
+ PAGED_CODE();\r
+-#pragma warning( pop )\r
+ \r
+ p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
+ \r
+diff -Naur --exclude-from=OMIT kernel/bus_port_mgr.h FilterDriver/bus_port_mgr.h\r
+--- kernel/bus_port_mgr.h 2008-07-08 11:28:36.000761600 -0700\r
++++ FilterDriver/bus_port_mgr.h 2008-07-24 11:03:45.579090800 -0700\r
+@@ -27,7 +27,7 @@\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+- * $Id: bus_port_mgr.h 1336 2008-07-07 17:29:40Z shefty $\r
++ * $Id: bus_port_mgr.h 1307 2008-06-29 16:45:16Z leonidk $\r
+ */\r
+ \r
+ \r
+@@ -43,7 +43,6 @@\r
+ typedef struct _port_mgr\r
+ {\r
+ cl_obj_t obj;\r
+- ib_pnp_handle_t h_pnp; /* Handle for port PnP events */\r
+ \r
+ /* Mutex protects both pointer vectors. */\r
+ cl_mutex_t pdo_mutex;\r
+@@ -54,8 +53,11 @@\r
+ } port_mgr_t;\r
+ \r
+ \r
++struct _bus_filter_instance;\r
++\r
+ ib_api_status_t\r
+ create_port_mgr(\r
++ IN struct _bus_filter_instance *p_bfi,\r
+ OUT port_mgr_t** const pp_port_mgr );\r
+ \r
+ \r
+diff -Naur --exclude-from=OMIT kernel/etc/ib_iou.inf FilterDriver/etc/ib_iou.inf\r
+--- kernel/etc/ib_iou.inf 1969-12-31 16:00:00.000000000 -0800\r
++++ FilterDriver/etc/ib_iou.inf 2008-06-10 14:53:48.602241900 -0700\r
+@@ -0,0 +1,127 @@\r
++; OpenIB InfiniBand Bus/IOU Driver.\r
++; Copyright 2005 SilverStorm Technologies all Rights Reserved.\r
++; Copyright 2006 Mellanox Technologies all Rights Reserved.\r
++\r
++[Version]\r
++Signature="$Windows NT$"\r
++Class=System\r
++ClassGuid={4D36E97D-E325-11CE-BFC1-08002BE10318}\r
++Provider=%OPENIB%\r
++DriverVer=04/29/2008,1.1.0000.1085\r
++\r
++; ================= Device Install section =====================\r
++\r
++; 64-bit platforms also copy 32-bit user-mode binaries.\r
++[DestinationDirs]\r
++DefaultDestDir=%DIRID_DRIVERS%\r
++\r
++[SourceDisksNames.x86]\r
++1=%DiskId%,,,""\r
++\r
++[SourceDisksNames.amd64]\r
++1=%DiskId%,,,""\r
++\r
++[SourceDisksNames.ia64]\r
++1=%DiskId%,,,""\r
++\r
++[SourceDisksFiles.x86]\r
++ibiou.sys=1\r
++\r
++[SourceDisksFiles.amd64]\r
++ibiou.sys=1\r
++\r
++[SourceDisksFiles.ia64]\r
++ibiou.sys=1\r
++\r
++[Manufacturer]\r
++%OPENIB% = GenIOU.DeviceSection,ntx86,ntamd64,ntia64\r
++%SST% = QLogicIOU.DeviceSection,ntx86,ntamd64,ntia64\r
++\r
++[GenIOU.DeviceSection]\r
++; empty since we don't support W9x/Me\r
++\r
++[GenIOU.DeviceSection.ntx86]\r
++%Iou.DeviceDesc% = Iou.DDInstall,IBA\IB_IOU\r
++\r
++[GenIOU.DeviceSection.ntamd64]\r
++%Iou.DeviceDesc% = Iou.DDInstall,IBA\IB_IOU\r
++\r
++[GenIOU.DeviceSection.ntia64]\r
++%Iou.DeviceDesc% = Iou.DDInstall,IBA\IB_IOU\r
++\r
++[QLogicIOU.DeviceSection]\r
++; empty since we don't support W9x/Me\r
++\r
++[QLogicIOU.DeviceSection.ntx86]\r
++%VFx.DeviceDesc% = Iou.DDInstall,IBA\V00066aP0060,IBA\V00066aP0010\r
++%VEx.DeviceDesc% = Iou.DDInstall,IBA\V00066aP0058\r
++%FVIC.DeviceDesc% = Iou.DDInstall,IBA\V00066aP00dd\r
++%EVIC.DeviceDesc% = Iou.DDInstall,IBA\V00066aP00de\r
++%BC2FC.DeviceDesc% = Iou.DDInstall,IBA\V00066aP00e0\r
++%BC2GE.DeviceDesc% = Iou.DDInstall,IBA\V00066aP00e1\r
++\r
++[QLogicIOU.DeviceSection.ntamd64]\r
++%VFx.DeviceDesc% = Iou.DDInstall,IBA\V00066aP0060,IBA\V00066aP0010\r
++%VEx.DeviceDesc% = Iou.DDInstall,IBA\V00066aP0058\r
++%FVIC.DeviceDesc% = Iou.DDInstall,IBA\V00066aP00dd\r
++%EVIC.DeviceDesc% = Iou.DDInstall,IBA\V00066aP00de\r
++%BC2FC.DeviceDesc% = Iou.DDInstall,IBA\V00066aP00e0\r
++%BC2GE.DeviceDesc% = Iou.DDInstall,IBA\V00066aP00e1\r
++\r
++[QLogicIOU.DeviceSection.ntia64]\r
++%VFx.DeviceDesc% = Iou.DDInstall,IBA\V00066aP0060,IBA\V00066aP0010\r
++%VEx.DeviceDesc% = Iou.DDInstall,IBA\V00066aP0058\r
++%FVIC.DeviceDesc% = Iou.DDInstall,IBA\V00066aP00dd\r
++%EVIC.DeviceDesc% = Iou.DDInstall,IBA\V00066aP00de\r
++%BC2FC.DeviceDesc% = Iou.DDInstall,IBA\V00066aP00e0\r
++%BC2GE.DeviceDesc% = Iou.DDInstall,IBA\V00066aP00e1\r
++\r
++[Iou.DDInstall.nt]\r
++CopyFiles = Iou.CopyFiles\r
++\r
++[Iou.DDInstall.nt.Services]\r
++AddService = ibiou,%SPSVCINST_ASSOCSERVICE%,Iou.ServiceInstall\r
++;AddService = ibiou,,Iou.ServiceInstall\r
++\r
++[Iou.CopyFiles]\r
++ibiou.sys\r
++\r
++;\r
++; ============= Service Install section ==============\r
++;\r
++\r
++[Iou.ServiceInstall]\r
++DisplayName = %Iou.ServiceDesc%\r
++ServiceType = %SERVICE_KERNEL_DRIVER%\r
++StartType = %SERVICE_DEMAND_START%\r
++ErrorControl = %SERVICE_ERROR_NORMAL%\r
++ServiceBinary = %12%\ibiou.sys\r
++AddReg = Iou.ParamsReg\r
++\r
++[Iou.ParamsReg]\r
++HKR,"Parameters","DebugLevel",%REG_DWORD%,2\r
++HKR,"Parameters","DebugFlags",%REG_DWORD%,0x00ffffff\r
++\r
++[Strings]\r
++OPENIB = "OpenFabrics Alliance"\r
++SST = "SilverStorm Technologies"\r
++VFx.DeviceDesc = "SilverStorm VFx"\r
++VEx.DeviceDesc = "SilverStorm VEx"\r
++FVIC.DeviceDesc = "SilverStorm FVIC"\r
++EVIC.DeviceDesc = "SilverStorm EVIC"\r
++BC2FC.DeviceDesc = "QLogic InfiniBand Fibre Channel Bridge Module"\r
++BC2GE.DeviceDesc = "QLogic InfiniBand Ethernet Bridge Module"\r
++\r
++Iou.DeviceDesc = "InfiniBand I/O Unit"\r
++Iou.ServiceDesc = "OpenIB InfiniBand I/O Unit Driver"\r
++DiskId = "OpenIB InfiniBand Access Layer installation disk"\r
++SPSVCINST_NULL = 0x0\r
++SPSVCINST_ASSOCSERVICE = 0x00000002\r
++SERVICE_KERNEL_DRIVER = 1\r
++SERVICE_DEMAND_START = 3\r
++SERVICE_ERROR_NORMAL = 1\r
++REG_DWORD = 0x00010001\r
++REG_DWORD_NO_CLOBBER = 0x00010003\r
++DIRID_SYSTEM = 11\r
++DIRID_DRIVERS = 12\r
++DIRID_SYSTEM_X86 = 16425\r
+diff -Naur --exclude-from=OMIT kernel/etc/mthca.cdf FilterDriver/etc/mthca.cdf\r
+--- kernel/etc/mthca.cdf 1969-12-31 16:00:00.000000000 -0800\r
++++ FilterDriver/etc/mthca.cdf 2008-06-03 13:06:32.000000000 -0700\r
+@@ -0,0 +1,22 @@\r
++[CatalogHeader]\r
++Name=mthca.cat\r
++PublicVersion=0x0000001\r
++EncodingType=0x00010001\r
++CATATTR1=0x10010001:OSAttr:2:6.0\r
++[CatalogFiles]\r
++<hash>mthca.inf=mthca.inf\r
++<hash>mthca.sys=mthca.sys\r
++<hash>mthcau.dll=mthcau.dll\r
++<hash>mthcaud.dll=mthcaud.dll\r
++<hash>mthca32.dll=mthca32.dll\r
++<hash>mthca32d.dll=mthca32d.dll\r
++<hash>ibal.dll=ibal.dll\r
++<hash>ibald.dll=ibald.dll\r
++<hash>complib.dll=complib.dll\r
++<hash>complibd.dll=complibd.dll\r
++<hash>cl32.dll=cl32.dll\r
++<hash>cl32d.dll=cl32d.dll\r
++<hash>ibal32.dll=ibal32.dll\r
++<hash>ibal32d.dll=ibal32d.dll\r
++<hash>ibbus.sys=ibbus.sys\r
++\r
+diff -Naur --exclude-from=OMIT kernel/etc/mthca.inx FilterDriver/etc/mthca.inx\r
+--- kernel/etc/mthca.inx 1969-12-31 16:00:00.000000000 -0800\r
++++ FilterDriver/etc/mthca.inx 2008-06-26 11:05:20.962763400 -0700\r
+@@ -0,0 +1,318 @@\r
++; Mellanox Technologies InfiniBand HCAs.\r
++; Copyright 2005 Mellanox Technologies all Rights Reserved.\r
++\r
++[Version]\r
++Signature="$Windows NT$"\r
++Class=InfiniBandController\r
++ClassGUID={58517E00-D3CF-40c9-A679-CEE5752F4491}\r
++Provider=%OFA%\r
++; must be synchronized with MTHCA_DEV.H\r
++DriverVer=05/19/2008,2.0.0000.1177\r
++CatalogFile=mthca.cat\r
++\r
++; ================= Destination directory section =====================\r
++\r
++[DestinationDirs]\r
++DefaultDestDir=%DIRID_DRIVERS%\r
++MTHCA.UMCopyFiles=%DIRID_SYSTEM%\r
++MTHCA.WOW64CopyFiles=%DIRID_SYSTEM_X86%\r
++Ibal.UMCopyFiles=%DIRID_SYSTEM%\r
++Ibal.WOW64CopyFiles=%DIRID_SYSTEM_X86%\r
++\r
++; ================= Class Install section =====================\r
++\r
++[ClassInstall32]\r
++AddReg=ClassAddReg\r
++\r
++[ClassAddReg]\r
++HKR,,,0,"RDMA Channel Adapters"\r
++HKR,,Icon,,-5\r
++HKR,,SilentInstall,,0\r
++HKR,,"UpperFilters",0x00010000,"ibbus" ; enable IBBUS/AL Filter driver loading.\r
++\r
++\r
++; ================= Device Install section =====================\r
++\r
++[SourceDisksNames.x86]\r
++1=%DiskId%,,,""\r
++\r
++[SourceDisksNames.amd64]\r
++1=%DiskId%,,,""\r
++\r
++[SourceDisksNames.ia64]\r
++1=%DiskId%,,,""\r
++\r
++[SourceDisksFiles]\r
++mthca.sys=1,,\r
++mthcau.dll=1,,\r
++mthcaud.dll=1,,\r
++ibal.dll=1,,\r
++complib.dll=1,,\r
++ibald.dll=1,,\r
++complibd.dll=1,,\r
++ibbus.sys=1,,\r
++\r
++[SourceDisksFiles.amd64]\r
++mthca.sys=1,,\r
++mthcau.dll=1,,\r
++mthcaud.dll=1,,\r
++mthca32.dll=1,,\r
++mthca32d.dll=1,,\r
++ibal.dll=1,,\r
++ibald.dll=1,,\r
++complib.dll=1,,\r
++complibd.dll=1,,\r
++cl32.dll=1,,\r
++cl32d.dll=1,,\r
++ibal32.dll=1,,\r
++ibal32d.dll=1,,\r
++ibbus.sys=1,,\r
++\r
++[SourceDisksFiles.ia64]\r
++mthca.sys=1,,\r
++mthcau.dll=1,,\r
++mthcaud.dll=1,,\r
++mthca32.dll=1,,\r
++mthca32d.dll=1,,\r
++ibal.dll=1,,\r
++ibald.dll=1,,\r
++complib.dll=1,,\r
++complibd.dll=1,,\r
++cl32.dll=1,,\r
++cl32d.dll=1,,\r
++ibal32.dll=1,,\r
++ibal32d.dll=1,,\r
++ibbus.sys=1,,\r
++\r
++[Manufacturer]\r
++%MTL% = HCA.DeviceSection,ntx86,ntamd64,ntia64\r
++\r
++[HCA.DeviceSection]\r
++; empty since we don't support W9x/Me\r
++\r
++[HCA.DeviceSection.ntx86]\r
++%MT23108.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_5A44\r
++%MT23109.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_5A45\r
++%MT25208.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_6278\r
++%MT25209.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_6279\r
++%MT25218.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_6282\r
++%MT24204.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_5E8C\r
++%MT24205.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_5E8D\r
++%MT25204.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_6274\r
++%MT25205.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_6275\r
++\r
++[HCA.DeviceSection.ntamd64]\r
++%MT23108.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_5A44\r
++%MT23109.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_5A45\r
++%MT25208.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_6278\r
++%MT25209.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_6279\r
++%MT25218.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_6282\r
++%MT24204.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_5E8C\r
++%MT24205.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_5E8D\r
++%MT25204.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_6274\r
++%MT25205.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_6275\r
++\r
++[HCA.DeviceSection.ntia64]\r
++%MT23108.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_5A44\r
++%MT23109.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_5A45\r
++%MT25208.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_6278\r
++%MT25209.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_6279\r
++%MT25218.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_6282\r
++%MT24204.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_5E8C\r
++%MT24205.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_5E8D\r
++%MT25204.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_6274\r
++%MT25205.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_6275\r
++\r
++[MTHCA.DDInstall.ntx86]\r
++CopyFiles = MTHCA.CopyFiles\r
++CopyFiles = MTHCA.UMCopyFiles\r
++CopyFiles = Ibal.UMCopyFiles\r
++CopyFiles = Ibbus.CopyFiles\r
++\r
++[MTHCA.DDInstall.ntamd64]\r
++CopyFiles = MTHCA.CopyFiles\r
++CopyFiles = MTHCA.UMCopyFiles\r
++CopyFiles = MTHCA.WOW64CopyFiles\r
++CopyFiles = Ibal.UMCopyFiles\r
++CopyFiles = Ibal.WOW64CopyFiles\r
++CopyFiles = Ibbus.CopyFiles\r
++\r
++[MTHCA.DDInstall.ntia64]\r
++CopyFiles = MTHCA.CopyFiles\r
++CopyFiles = MTHCA.UMCopyFiles\r
++CopyFiles = MTHCA.WOW64CopyFiles\r
++CopyFiles = Ibal.UMCopyFiles\r
++CopyFiles = Ibal.WOW64CopyFiles\r
++CopyFiles = Ibbus.CopyFiles\r
++\r
++\r
++; ============== Services ==============\r
++\r
++[MTHCA.DDInstall.ntx86.Services]\r
++AddService = mthca,%SPSVCINST_ASSOCSERVICE%,MTHCA.ServiceInstall,MTHCA.EventLog\r
++AddService = ibbus,,Ibbus.ServiceInstall\r
++\r
++[MTHCA.DDInstall.ntamd64.Services]\r
++AddService = mthca,%SPSVCINST_ASSOCSERVICE%,MTHCA.ServiceInstall,MTHCA.EventLog\r
++AddService = ibbus,,Ibbus.ServiceInstall\r
++\r
++[MTHCA.DDInstall.ntia64.Services]\r
++AddService = mthca,%SPSVCINST_ASSOCSERVICE%,MTHCA.ServiceInstall,MTHCA.EventLog\r
++AddService = ibbus,,Ibbus.ServiceInstall\r
++\r
++\r
++; ============= File Copy ==============\r
++\r
++[MTHCA.CopyFiles]\r
++mthca.sys\r
++\r
++[MTHCA.UMCopyFiles]\r
++mthcau.dll,,,2\r
++mthcaud.dll,,,2\r
++\r
++[MTHCA.WOW64CopyFiles]\r
++mthcau.dll,mthca32.dll,,2\r
++mthcaud.dll,mthca32d.dll,,2\r
++\r
++[Ibal.UMCopyFiles]\r
++ibal.dll,,,2\r
++ibald.dll,,,2\r
++complib.dll,,,2\r
++complibd.dll,,,2\r
++\r
++[Ibal.WOW64CopyFiles]\r
++ibal.dll,ibal32.dll,,2\r
++ibald.dll,ibal32d.dll,,2\r
++complib.dll,cl32.dll,,2\r
++complibd.dll,cl32d.dll,,2\r
++\r
++[Ibbus.CopyFiles]\r
++ibbus.sys\r
++\r
++\r
++;\r
++; ============= MTHCA Service Install section ==============\r
++;\r
++\r
++[MTHCA.ServiceInstall]\r
++DisplayName = %MTHCA.ServiceDesc%\r
++ServiceType = %SERVICE_KERNEL_DRIVER%\r
++StartType = %SERVICE_DEMAND_START%\r
++ErrorControl = %SERVICE_ERROR_NORMAL%\r
++ServiceBinary = %12%\mthca.sys\r
++LoadOrderGroup = extended base\r
++AddReg = MTHCA.ParamsReg\r
++\r
++\r
++[MTHCA.EventLog]\r
++AddReg = MTHCA.AddEventLogReg\r
++\r
++[MTHCA.AddEventLogReg]\r
++HKR, , EventMessageFile, 0x00020000, "%%SystemRoot%%\System32\IoLogMsg.dll;%%SystemRoot%%\System32\drivers\mthca.sys"\r
++HKR, , TypesSupported, 0x00010001, 7\r
++\r
++[MTHCA.ParamsReg]\r
++HKR,"Parameters","DebugLevel",%REG_DWORD%,0x00000003\r
++HKR,"Parameters","DebugFlags",%REG_DWORD%,0x0000ffff\r
++HKR,"Parameters","SkipTavorReset",%REG_DWORD%,0\r
++HKR,"Parameters","DisableTavorResetOnFailure",%REG_DWORD%,1\r
++HKR,"Parameters","TunePci",%REG_DWORD%,0\r
++HKR,"Parameters","ProcessorAffinity",%REG_DWORD%,0\r
++HKR,"Parameters","MaxDpcTimeUs",%REG_DWORD%,10000\r
++HKR,"Parameters","ProfileQpNum",%REG_DWORD%,0\r
++HKR,"Parameters","ProfileRdOut",%REG_DWORD%,0xffffffff\r
++HKLM,"System\CurrentControlSet\Control\WMI\GlobalLogger\8bf1f640-63fe-4743-b9ef-fa38c695bfde","Flags",%REG_DWORD%,0xffff\r
++HKLM,"System\CurrentControlSet\Control\WMI\GlobalLogger\8bf1f640-63fe-4743-b9ef-fa38c695bfde","Level",%REG_DWORD%,0x3\r
++\r
++\r
++; ============= IBBUS/AL Service Install section ==============\r
++;\r
++\r
++[Ibbus.ServiceInstall]\r
++DisplayName = %Ibbus.ServiceDesc%\r
++ServiceType = %SERVICE_KERNEL_DRIVER%\r
++StartType = %SERVICE_DEMAND_START%\r
++ErrorControl = %SERVICE_ERROR_NORMAL%\r
++ServiceBinary = %12%\ibbus.sys\r
++LoadOrderGroup = PnP Filter\r
++AddReg = Ibbus.ParamsReg\r
++Dependencies = mthca\r
++\r
++[Ibbus.ParamsReg]\r
++HKR,"Parameters","IbalDebugLevel",%REG_DWORD%,2\r
++HKR,"Parameters","IbalDebugFlags",%REG_DWORD%,0x00ffffff\r
++HKR,"Parameters","SmiPollInterval",%REG_DWORD_NO_CLOBBER%,20000\r
++HKR,"Parameters","IocQueryTimeout",%REG_DWORD_NO_CLOBBER%,250\r
++HKR,"Parameters","IocQueryRetries",%REG_DWORD_NO_CLOBBER%,4\r
++HKR,"Parameters","IocPollInterval",%REG_DWORD_NO_CLOBBER%,30000\r
++HKR,"Parameters","DebugFlags",%REG_DWORD%,0x80000000\r
++HKR,"Parameters","ReportPortNIC",%REG_DWORD%,1\r
++\r
++\r
++; ============= Uninstall Section =============\r
++\r
++[DefaultUninstall.ntx86]\r
++DelFiles = MTHCA.CopyFiles\r
++DelFiles = MTHCA.UMCopyFiles\r
++DelReg = MTHCA.ParamsReg\r
++DelReg = MTHCA.AddEventLogReg\r
++DelReg = ClassAddReg\r
++DelFiles = Ibal.UMCopyFiles\r
++\r
++\r
++[DefaultUninstall.ntamd64]\r
++DelFiles = MTHCA.CopyFiles\r
++DelFiles = MTHCA.UMCopyFiles\r
++DelFiles = MTHCA.WOW64CopyFiles\r
++DelReg = MTHCA.ParamsReg\r
++DelReg = MTHCA.AddEventLogReg\r
++DelReg = ClassAddReg\r
++DelFiles = Ibal.UMCopyFiles\r
++DelFiles = Ibal.WOW64CopyFiles\r
++\r
++\r
++[DefaultUninstall.ntia64]\r
++DelFiles = MTHCA.CopyFiles\r
++DelFiles = MTHCA.UMCopyFiles\r
++DelFiles = MTHCA.WOW64CopyFiles\r
++DelReg = MTHCA.ParamsReg\r
++DelReg = MTHCA.AddEventLogReg\r
++DelReg = ClassAddReg\r
++DelFiles = Ibal.UMCopyFiles\r
++DelFiles = Ibal.WOW64CopyFiles\r
++\r
++\r
++[DefaultUninstall.Services]\r
++DelService = Ibbus,%SPSVCINST_STOPSERVICE%\r
++DelService = mthca,%SPSVCINST_STOPSERVICE%\r
++\r
++\r
++[Strings]\r
++IBClassGuid = "{58517E00-D3CF-40c9-A679-CEE5752F4491}"\r
++OFA = "OpenFabrics Alliance"\r
++MTL="Mellanox Technologies Ltd."\r
++MTHCA.ServiceDesc = "Driver for Mellanox InfiniHost Devices"\r
++MT23108.DeviceDesc="InfiniHost (MT23108) - Mellanox InfiniBand HCA"\r
++MT23109.DeviceDesc="InfiniHost (MT23109) - Mellanox InfiniBand HCA (burner device)"\r
++MT25208.DeviceDesc="InfiniHost (MT25208) - Mellanox InfiniBand HCA for PCI Express"\r
++MT25209.DeviceDesc="InfiniHost (MT25209) - Mellanox InfiniBand HCA for PCI Express (burner device)"\r
++MT25218.DeviceDesc="InfiniHost III Ex (MT25218) - Mellanox InfiniBand HCA for PCI Express"\r
++MT24204.DeviceDesc="InfiniHost III Lx (MT24204) - Mellanox InfiniBand HCA for PCI Express"\r
++MT24205.DeviceDesc="InfiniHost III Lx (MT24205) - Mellanox InfiniBand HCA for PCI Express (burner device)"\r
++MT25204.DeviceDesc="InfiniHost III Lx (MT25204) - Mellanox InfiniBand HCA for PCI Express"\r
++MT25205.DeviceDesc="InfiniHost III Lx (MT25205) - Mellanox InfiniBand HCA for PCI Express (burner device)"\r
++DiskId = "Mellanox InfiniBand HCA installation disk"\r
++Ibbus.ServiceDesc = "InfiniBand Bus/Fabric/AL (Filter Driver)"\r
++SPSVCINST_NULL = 0x0\r
++SPSVCINST_ASSOCSERVICE = 0x00000002\r
++SPSVCINST_STOPSERVICE = 0x00000200\r
++SERVICE_KERNEL_DRIVER = 1\r
++SERVICE_DEMAND_START = 3\r
++SERVICE_ERROR_NORMAL = 1\r
++REG_DWORD = 0x00010001\r
++REG_DWORD_NO_CLOBBER = 0x00010003\r
++REG_MULTI_SZ_APPEND = 0x00010008\r
++DIRID_SYSTEM = 11\r
++DIRID_DRIVERS = 12\r
++DIRID_SYSTEM_X86 = 16425\r
++\r