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