if "%1" == "allnoforce" goto OK\r
if "%1" == "allf" (\r
if "%2" == "" goto usage\r
- goto OK\r
+ if exist "%2" goto OK\r
+ echo %0 Err - path .\%2 does not exist?\r
+ exit /B 1\r
)\r
if "%1" == "compile" goto OK\r
if "%1" == "compilenoforce" goto OK\r
if "%1" == "compf" (\r
if "%2" == "" goto usage\r
- goto OK\r
+ if exist "%2" goto OK\r
+ echo %0 Err - path .\%2 does not exist?\r
+ exit /B 1\r
)\r
if "%1" == "makebin" goto OK\r
if "%1" == "msi" goto OK\r
\r
if "%WIN7%" == "yes" (\r
rem Windows 7 WDK\r
- set _DDK_VER=7053.0.winmain.090226-1910\r
+ set _DDK_VER=7068.0.0\r
set _COIN_VER=01009\r
) else (\r
rem Server 2008 WDK & WdfCoInstaller version\r
echo %0: Finished %TIME%\r
\r
endlocal\r
-@echo on\r
-[11-13-08]\r
+[04-10-09]\r
\r
How to generate a Windows OpenFabrics Release (WinOF) using the WIX 2.0 open\r
source installer tool set ( http://sourceforge.net/projects/wix/ ).\r
WIX Introduction http://wix.sourceforge.net/manual-wix2/wix_index.htm \r
\r
\r
-WinOF Revisions:\r
- 1.0 based on svn.614\r
+WinOF Revisions: (based on)\r
+ 1.0 svn.614\r
1.0.1 svn.864\r
1.1 svn.1177\r
2.0 svn.1763\r
+ 2.0.2 svn.1975\r
\r
\r
\r
As of WinOF 2.0 release [Aug'08] the build environment has been switched over to\r
Microsoft's WDK (Windows Driver Kit) version 6001.180001.\r
\r
-See gen1\trunk\BuildRelease.bat file to generate a Wix installer (.msi file) containing\r
-signed driver files.\r
+See gen1\trunk\WinOF\BuildRelease.bat file to generate a Wix installer (.msi\r
+file) containing signed driver files.\r
The OS flavor WLH\ - Vista/Server 2008[LongHorn], WNET\ - Server 2003+XP64\r
-and XP\ (x86 only) bin folders will be populated with the correct folder structure such that\r
-a WIX installer (.msi) files can be generated; either cd into OS\arch dir and\r
-run buildmsi.bat or use BuildRelease.bat from trunk\ folder.\r
+and XP\ (x86 only) bin\ folders will be populated with the correct folder\r
+structure such that a WIX installer (.msi) files can be generated; either\r
+cd into OS\arch dir and run buildmsi.bat or use WinOF\BuildRelease.bat.\r
\r
Warning - buildrelease.bat is not generic, some asembly required as the folder\r
-structure is assumed.\r
+structure is assumed; see SVN to set build SVN (aka OPENIB_REV).\r
\r
BuildRelease.bat will by default deposit 7 .msi files in\r
'%SystemRoot%\temp\WinOF_OS_arch.msi'.\r
cd to trunk; build /wg from a WDK OS and arch specific command window; all\r
are required by etc\makebin.bat.\r
\r
- 2) cd trunk\etc; execute 'makebin src-dir dest-dir OS-flavor' for each OS flavor:\r
- wnet, wlh and wxp.\r
+ 2) from trunk: execute 'etc\makebin %CD% dest-dir OS-flavor' for each OS\r
+ flavor: wnet, wlh and wxp.\r
Say your svn repository is at C:\open-ib\, then to populate the WIX bin\r
folder for Server 2008 binaries from a command window:\r
- makebin C:\open-ib\gen1\trunk C:\open-ib\gen1\branches\WinOF\Wix\WLH\bin WLH\r
-\r
-With the arrival of Windows Server 2008 & Vista (WLH - Windows LongHorn) driver signing\r
-is a requirement. The WIX\sign-all-drivers.bat script will create a .cat file for each\r
-driver .inf located. The generation of the .cat file is driven from the corresponding\r
-.cdf file (.inf + .cdf + all files listed in .cdf + inf2cat.exe & signtool.exe result\r
-in a .cat file).\r
-\r
-A SW publisher's digital-ID certificate is required in order for WinOF installers to\r
-be created. A test certificate can be generated for local use, requires overhead during\r
-installation ('bcdedit -set testsigning on', reboot & local certificate store updates).\r
-The MS prescribed procedure is to obtain a SW publisher's certificate from VeriSign or\r
-other agency; if your company is producing SW drivers for SVR2008/Vista, then you will\r
-likely have access to a cert file.\r
+ makebin C:\open-ib\gen1\trunk C:\open-ib\gen1\WinOF\Wix\WLH\bin WLH\r
+\r
+With the arrival of Windows Server 2008 & Vista (WLH - Windows LongHorn) driver\r
+signing is a requirement. The WIX\sign-all-drivers.bat script will create a .cat\r
+file for each driver .inf located. The generation of the .cat file is driven\r
+from the corresponding driver.inf file via inf2cat.exe creating the .cat file\r
+and signtool.exe signing the .cat and .sys files.\r
+\r
+A SW publisher's digital-ID certificate is required in order for WinOF\r
+installers to be created. A test certificate can be generated for local use,\r
+requires overhead during installation ('bcdedit -set testsigning on', reboot &\r
+local certificate store updates).\r
+The MS prescribed procedure is to obtain a SW publisher's certificate from\r
+VeriSign or other CA agency; if your company is producing SW drivers for\r
+SVR2008/Vista, then you will likely have access to a cert file.\r
The OFA will be purchasing a certificate for WinOF publication.\r
-Scripts for signing drivers assume the .cer file will be resident in '...WinOF\Wix\*.cer'.\r
-see trunk\buildrelease.bat for an example of how to invoke driver\r
-signing; 'WIX\sign-all-drivers.bat'.\r
-Also see the Microsoft 'Kernel Mode Code Signing' document 'KMCS_Walkthrough.doc'; goggle\r
-for current URL.\r
+Scripts for signing drivers assume the MS cross-certification .cer file will be\r
+resident in 'trunk\WinOF\Wix\*.cer'; your company Cert must be placed in the\r
+local cert store under the default personal 'My' store. \r
+see trunk\winof\buildrelease.bat for an example of how to invoke driver\r
+signing or 'WIX\sign-all-drivers.bat'.\r
+Also see the Microsoft 'Kernel Mode Code Signing' document\r
+'KMCS_Walkthrough.doc'; goggle for current URL.\r
\r
\r
Creating a WIX tool set\r
-------------------------\r
\r
Download the WIX v2 (stable) tool set (http://sourceforge.net/projects/wix/)\r
-to \91WInOF\WIX\WIX_tools\\92.\r
+to \91WinOF\WIX\WIX_tools\\92.\r
Unzip the archive to a folder within 'WIX_tools\' as this folder represents the\r
version of the tool set.\r
Something like unzip wix-2.0.5325.0-binaries.zip into wix-2.0.5325.0-binaries\.\r
You would now have the following structure:\r
WinOF\WIX\WIX_tools\wix-2.0.5325.0-binaries\{candle.exe, light.exe,...}\r
+Point being Trunk\WinOF\buildRelease.bat needs the path to the WIX tool set.\r
\r
\r
\r
The file 'Release_notes.htm' represents the next to be released\r
WinOF version, as reflected by is Release ID.\r
\r
- Release ID number (e.g., 1.0)\r
+ Release ID number (e.g., 1.0, point releases are 1.0.x)\r
\r
New features\r
\r
Know issues\r
\r
-Update the trunk\doc\Manual.htm file for new features.\r
+Update the trunk\docs\Manual.htm file for new features.\r
\r
\r
BUILDING a .msi installer image file\r
------------------------------------\r
\r
Easy way:\r
- place certificate file (.cer) in WIX\ folder; 'My Personal' cert store needs to be updated.\r
+ place MS cross certificate file (.cer) in WIX\ folder; 'My' cert store needs\r
+ to contain your company cert file; WinOF\BuildRelease.bat needs the name of\r
+ your company cert file; OFA case 'OpenFabrics Alliance'.\r
+ .\r
cd trunk\\r
From a standard DOS cmd window, not a WDK cmd window, say \r
- buildrelease clean\r
- buildrelease all # .msi file created in %windir%\temp\*.msi\r
\r
- buildrelease makebin - assumes trunk\bin\* built, populates WIX\{wlh,wnet,wxp}\bin folders.\r
+ buildrelease all # .msi files created in %windir%\temp\*.msi\r
+\r
+ buildrelease makebin - assumes trunk\bin\* built,\r
+ populates WIX\{wlh,wnet,wxp}\bin folders.\r
+ buildrelease sign - sign driver files & exit, assumes makebin has been run.\r
buildrelease msi - signs & creates installers assuming makebin has been run.\r
- buildrelease wix - just creates .msi installers - assumes all bin\ folders populated.\r
+ buildrelease wix - creates .msi installers - assumes all bin\ folders\r
+ populated and drivers signed.\r
\r
CPU specific builds\r
\r
-CD to the WIX OS-flavor and architecture specific directory. 'nmake.exe' needs to be\r
-in your command window search path. Build three arch specific installers\r
+CD to the WIX OS-flavor and architecture specific directory. 'nmake.exe' needs\r
+to be in your command window search path. Build three arch specific installers\r
(.msi files) for WLH and WNET; WXP is x86 only. \r
\r
WARNING:\r
- assupmtion: .\bin is populated correctly from makebin.bat or BuildRelease.bat makebin.\r
+ assupmtion: .\bin is populated correctly from makebin.bat or\r
+ 'BuildRelease makebin'.\r
\r
-cd gen1\branches\WinOF\WIX\wlh\x86 & nmake\r
+cd gen1\trunk\WinOF\WIX\wlh\x86 & nmake\r
Results in a .\WOF_wlh_x86.msi installer image.\r
\r
-cd gen1\branches\WinOF\WIX\wlh\x64 & nmake\r
+cd gen1\trunk\WinOF\WIX\wlh\x64 & nmake\r
Results in a WOF_wlh_x64.msi installer image.\r
\r
-cd gen1\branches\WinOF\WIX\wlh\ia64 & nmake\r
+cd gen1\trunk\WinOF\WIX\wlh\ia64 & nmake\r
Results in a WOF_wlh_ia64.msi installer image.\r
\r
\r
-DEBUG\r
------\r
+DEBUG Installation\r
+------------------\r
Create a log file for a given .msi installation:\r
\r
msiexec /I "WOF_x86.msi" /Lv \temp\msi.log\r
\r
- Also see %windir%\inf\setupapi.dev.log on Svr08 & Vista for driver load logging.\r
+ Also see %windir%\inf\setupapi.dev.log on Svr08 & Vista for driver load\r
+ logging.\r
\r
Command line way to set an interface's IP address, netmask, no gateway:\r
\r
- netsh interface ip set address "Local Area Connection 3" static 10.10.4.200 255.255.255.0\r
+ netsh interface ip set \\r
+ address "Local Area Connection 3" static 10.10.4.200 255.255.255.0\r
netsh interface ip show address "Local Area Connection 3"\r
\r
\r
1) The WinOF 2.1 release is based on openib-windows source svn revision\r
(branches\WOF2-1 svn.xxxx).\r
\r
- Last WinOF release (2.0.1) based on svn 1932.\r
+ Last WinOF release (2.0.1) based on svn.1932.\r
\r
2) Bug fixes in\r
\r
\r
3) New Functionality\r
\r
- A) Connected mode IPoIB ensures higher performance IPoIB transfers in\r
+ - OFED Compatibility layers allow for easy porting of OFED applications\r
+ into the WinOF environment.\r
+ libibverbs - OFED verbs API library.\r
+ libmad - InfiniBand MAD (Management Datagram) library.\r
+ libumad - IB MAD exported user-mode interface library.\r
+ librdmacm - OFED RDMA CM (Comunications Manager).\r
+\r
+ - OFED fabric diagnostic utilities are available.\r
+ ibstat - display HCA information.\r
+ ibnetdiscover - generate a fabric topology.\r
+ portinfo - display InfiniBand port specific information.\r
+ saquery - SA (Subnet Administrator) query test.\r
+\r
+ - Connected mode IPoIB ensures higher performance IPoIB transfers in\r
addition to OFED (Linux) IPoIB compatibility.\r
\r
- B) Windows Server 2008/Vista WinOF installs now utilize Windows Plug-n-Play\r
+ - Windows Server 2008/Vista WinOF installs now utilize Windows Plug-n-Play\r
(PNP) to install the correct HCA driver(s). Selection of a specific HCA\r
device type is no longer required for Server 2008/Vista/HPC.\r
\r
start/wait msiexec /X WinOF_wlh_x64.msi /passive\r
\r
\r
- C) Server 2008-HPC install support has been enhanced to provide a no-drivers\r
+ - Server 2008-HPC install support has been enhanced to provide a no-drivers\r
installed mode. Device driver '.inf' files are not processed during the\r
WinOF install.\r
The base assumption is that a WDM node provisioning template will install\r
unattended uninstall with auto-reboot:\r
start/wait msiexec /X WOF.msi /passive\r
\r
- D) SRP and VNIC drivers are command line selectable:\r
+ - SRP and VNIC drivers are command line selectable:\r
start/wait msiexec /I WOF.msi /passive SRP=1\r
start/wait msiexec /I WOF.msi /passive VNIC=1\r
\r
- E) Subnet Management started as a local Windows Service from a command line:\r
+ - Subnet Management started as a local Windows Service from a command line:\r
start/wait msiexec /I WOF.msi /passive OSMS=1\r
\r
- F) HCA drivers load WinVerbs and WinMad filter drivers by default.\r
+ - HCA drivers load WinVerbs and WinMad filter drivers by default.\r
\r
- G) OFED Compatibility layers allow for easy porting of OFED applications\r
- into the WinOF environment.\r
- libibverbs - OFED verbs API library.\r
- libmad - InfiniBand MAD (Management Datagram) library.\r
- libumad - IB MAD exported user-mode interface library.\r
-\r
- H) OFED fabric diagnostic utilities are available.\r
- ibstat - display HCA information.\r
- ibnetdiscover - generate a fabric topology.\r
- portinfo - display InfiniBand port specific information.\r
- saquery - SA (Subnet Administrator) query test.\r
\r
\r
Note on Vista installs Only:\r
<h1 align=center style='text-align:center'><a name="1.1_Release_Notes">2.1 Release Notes</a></h1>\r
\r
<h3 align=center style='text-align:center'>\r
-<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%m/%d/%Y" startspan -->03/09/2009<!--webbot bot="Timestamp" endspan i-checksum="12644" --></h3>\r
+<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%m/%d/%Y" startspan -->04/10/2009<!--webbot bot="Timestamp" endspan i-checksum="12510" --></h3>\r
\r
<div class=MsoNormal align=center style='text-align:center'>\r
\r
Server 2008</span></font></p>\r
</li>\r
<li>\r
+ <p style='margin-left:.5in;text-indent:-.25in'><font face="Arial">Windows \r
+ Server 2008 R2</font></p>\r
+ </li>\r
+ <li>\r
+ <p style='margin-left:.5in;text-indent:-.25in'><font face="Arial">Windows 7 \r
+ (Server/Ultimate/Professional)</font></p>\r
+ </li>\r
+ <li>\r
<p style='margin-left:.5in;text-indent:-.25in'><font face="Arial"><span dir="LTR">Vista</span></font></p>\r
</li>\r
<li>\r
<p><a href="#1.1_Release_Notes"><font color="#000000"><Return-to-Top></font></a></p>\r
<p> </p>\r
<h3><u><a name="Server_2008_HPC_Install_Notes">Server 2008 HPC Install Notes</a></u></h3>\r
-<p><font face="Arial">Device drivers in WinOF 2.0 and later releases, are Digitally \r
-signed although they are not WHQL'ed (Windows Quality Hardware Labs) certified. The lack \r
-of WHQL certification impacts unattended installs by requiring the user to \r
-'accept' \r
-installation of the non-WHQL'ed driver the first time a compute node is \r
-installing WinOF drivers via the WinOF .msi installer. Additionally the non-WHQL \r
+<p><font face="Arial">Device drivers in WinOF 2.0 and later releases are Digitally \r
+signed by the OpenFabrics Alliance, although they are not WHQL'ed (Windows Quality Hardware Labs) certified. \r
+The WinOF source code is used by hardware vendors to achieve WHQL \r
+certification. This lack \r
+of WinOF WHQL certification impacts unattended installs by requiring the user to \r
+'accept' installation of non-WHQL'ed drivers the 'first' time a compute node \r
+installs WinOF drivers via the WinOF .msi installer. <br>\r
+Additionally the non-WHQL \r
driver notifier box has a \r
-checkbox which allows establishing a trust for software from the publisher \r
-'OpenFabrics Alliance'. Checking this box allows future WinOF driver installs to proceed \r
-without user intervention as you have indicated to Windows that you trust non-WHQL \r
-drivers from the Openfabrics Alliance software publisher.</font></p>\r
+checkbox which allows establishing a <b><i>trust</i></b> for software from the publisher \r
+'OpenFabrics Alliance'. Checking the 'Trust Software from the OpenFabrics \r
+Alliance publisher' box allows future WinOF driver installs to proceed \r
+without user intervention as you have indicated to Windows that you trust non-WHQL'ed \r
+drivers from the OpenFabrics Alliance software publisher.</font></p>\r
<p><font face="Arial">***** Warning *****<br>\r
WinOF .msi installs on compute nodes the first time require human input to 'accept' \r
installation of non-WHQL'ed drivers along with establishing a trust for the SW \r
WinOF.....msi /quiet', the install will \r
silently hang waiting for user input.<br>\r
First time unattended WinOF .msi installs need mouse input to complete. \r
-Once the SW publisher trust has been established, future unattended WinOF .msi \r
+Once the Openfabrics Alliance SW publisher trust has been established, future unattended WinOF .msi \r
installs procees without human input.</font></p>\r
<p><font face="Arial">Be aware: if a node is reimaged (same or different template applied) the \r
established trust of OpenFabric Alliance is destroyed, thus the non-WHQL driver \r
-notifier box and ensuing human input is again required on the first WinOF .msi \r
+notifier box and muse-click input is again required on the first WinOF .msi \r
install</font></p>\r
<h4><u>Windows Deployment Manager usage for HPC compute node provisioning</u></h4>\r
-<p><font face="Arial">Microsoft has chosen the WDM to provision HPC \r
-cluster compute nodes. WinOF now supports an administrative install mode which \r
-is a method to extract the WinOF installed files without actually installing them, \r
-thus making WinOF driver files accessible for WDM provisioning.</font></p>\r
+<p><font face="Arial">Microsoft has chosen WDM to provision HPC \r
+cluster compute nodes; see \r
+<a href="http://technet.microsoft.com/en-us/library/dd391826.aspx">Microsoft HPC \r
+installs</a> for details.</font></p>\r
+<p><font face="Arial">In support of the new Microsoft WDM HPC cluster \r
+provisioning process, WinOF now supports an administrative install mode which is \r
+a method to extract WinOF files to the local filesystem without actually installing them; \r
+thus making WinOF driver files accessible to WDM provisioning. </font></p>\r
<p><font face="Arial">msiexec /A WinOF_2-0_wlh_x64.msi TARGETDIR=dev:\path-to-extracted-files</font></p>\r
<p><font face="Arial">example: msiexec /A WinOF_2-1_wlh_x64.msi TARGETDIR=%TEMP% \r
(note: TARGETDIR is case sensitive)</font></p>\r
<h4><u>WinOF device driver-less installs:</u></h4>\r
<p><font face="Arial">Normally WinOF device driver files are installed by processing the driver '.inf' \r
files. To install the WinOF package by selecting install features without \r
-installing any device drivers [HCA, IPoIB, ND, WSD, SRP or VNIC] (assumded \r
+installing any device drivers [HCA, IPoIB, ND, WSD, SRP or VNIC] (assumed \r
reliance on WDM to install drivers) can be accomplished with the following \r
command:</font></p>\r
<p><font face="Arial">start/wait msiexec /i WinOF_2-0-1_wlh_x64.msi NODRV=1</font></p>\r
@echo off\r
setlocal\r
-rem\r
-rem create a ZIP file of a WinOF distribution, such that the zip file is pushed to the\r
-rem OFA WinOF download site, unzipped for distribution.\r
+\r
+rem TabStop=4\r
+\r
+rem Mfg. a ZIP file of a WinOF distribution, such that the zip file can be\r
+rem pushed to the OFA WinOF download site and unzipped for distribution.\r
\r
rem populate arch specific distribution folders, zip'em, populate symbols \r
rem folder and zip the entire package for transmission to OFA download website.\r
rem # if target_path is null then default %SystemRoot%\temp\v%1\r
rem # otherwise %2\v%1\r
\r
+rem cmd.exe /V:on (delayed environment variable expansion) is required!\r
+set F=on\r
+set F=off\r
+if not "!F!" == "off" (\r
+ echo Err: cmd.exe /V:on [delayed environment variable expansion] Required!\r
+ exit /B 1\r
+)\r
+\r
if "%1" == "" (\r
echo "Missing release ID, example %0 1-1"\r
echo "usage: %0 release_ID {target_path, default: %SystemRoot%\temp}\r
exit /B 1 \r
)\r
\r
-FOR %%s IN ( wxp wlh wnet ) DO (\r
+FOR %%s IN ( win7 wxp wlh wnet ) DO (\r
+ if exist %CD%\%%s\bin\Misc\Manual.htm (\r
+ set OSF=%%s !OSF!\r
+ )\r
+)\r
+echo Packaging installers for !OSF!\r
\r
+if "!OSF!" == "" (\r
+ echo "Missing components?"\r
+ echo "Must execute from gen1\branches\WinOF\WIX -- and --"\r
+ echo " .\win7,wnet,wxp,wlh\bin\ must be populated."\r
+ echo " run gen1\trunk\buildRelease.bat -or- gen1\trunk\etc\makebin"\r
+ exit /B 1\r
+)\r
+\r
+FOR %%s IN ( !OSF! ) DO (\r
echo Building %%s installers.\r
- if not exist %CD%\%%s\bin\Misc\Manual.htm (\r
- echo "Must execute from gen1\branches\WinOF\WIX -- and --"\r
- echo " .\wnet,wxp,wlh\bin\ must be populated."\r
- echo " run gen1\trunk\buildRelease.bat -or- gen1\trunk\etc\makebin"\r
- exit /B 1\r
- )\r
\r
rem create target structure\r
mkdir %MSI_DST%\%%s\r
rename wlh Server_2008-Vista-HPC\r
rename wnet Server_2003-XP64\r
rename wxp XP32\r
+if exist win7 rename win7 Windows7\r
popd\r
\r
IF EXIST %ZIP% del /F/Q %ZIP%\r
\r
<Include>\r
\r
- <?define WOFREL="v2.1 (RC0)" ?>\r
+ <?define WOFREL="v2.1 (pre-RC0)" ?>\r
\r
<?define WOFRELNUM=2.1.0 ?>\r
\r
<![CDATA[VersionNT64]]>\r
</Condition>\r
\r
- <Condition Message="[ProductName] requires Windows Server 2008 to install.">\r
- <![CDATA[(VersionNT=600)]]>\r
+ <Condition Message="[ProductName] requires Windows 7 or Server 2008 R2 to install.">\r
+ <![CDATA[(VersionNT=601)]]>\r
</Condition>\r
\r
<?include ..\..\common\requirements.inc ?>\r
rem CrossCertFilename - fully qualified path\filename of cross cert.\r
rem CertStoreName - name of certificate in 'MY' Cert store (certmgr).\r
\r
-rem example: signDrivers %CD%\cse1CCFilename My bin\hca\r
+rem example: signDrivers %CD%\Cross-Cert SWPublisher bin\hca\r
\r
rem cmd.exe /V:on (delayed environment variable expansion) is required!\r
set F=on\r
path > jnk.txt\r
findstr /c:"SelfSign" jnk.txt > jnk1.txt\r
if %errorlevel% EQU 1 (\r
- path "%PATH%;C:\WinDDK\6001.18001\bin\SelfSign"\r
+ path "%PATH%;C:\WinDDK\xxx\bin\SelfSign"\r
)\r
if exist jnk1.txt del /Q /F jnk1.txt\r
if exist jnk.txt del /Q /F jnk.txt\r
if exist %%f del /F /Q %%f\r
)\r
\r
-rem temp hack until inf2cat support /OS WIN7_xxx\r
- if "%%d" == "amd64" set OEA=Server2008_X64\r
- if "%%d" == "x86" set OEA=Server2008_X86\r
- if "%%d" == "ia64" set OEA=Server2008_IA64\r
+ rem set OS type for inf2cat\r
+ if "%%d" == "x86" set OEA=7_X86\r
+ if "%%d" == "amd64" set OEA=7_X64,Server2008R2_X64\r
+ if "%%d" == "ia64" set OEA=Server2008R2_IA64\r
\r
-rem if "%%d" == "amd64" set OEA=%OE%_X64,Vista_X64\r
-rem if "%%d" == "x86" set OEA=%OE%_X86,Vista_X86\r
-rem if "%%d" == "ia64" set OEA=%OE%_IA64\r
-\r
- echo %0 - Generating %%d .cat files for !OEA!\r
- inf2cat /driver:%CD%\%%d /os:!OEA!\r
+ echo %0 [%OE%] Generating %%d .cat files for !OEA!\r
+ inf2cat /driver:!CD! /os:!OEA!\r
if ERRORLEVEL 1 (\r
echo %CD% inf2cat failed\r
exit /B 1\r
)\r
- echo %0 - Signing %%d .cat files\r
+ echo %0 [%OE%] Signing %%d .cat files\r
for %%f in ( *.cat ) do (\r
- echo %0 - Signing %%d\%%f\r
- signtool sign /ac %1 /n %2 %TS% %DU% %%f\r
+ echo %0 [%OE%] Signing %%d\%%f\r
+ signtool sign /ac %1 /s "My" /n %2 %TS% %DU% %%f\r
if ERRORLEVEL 1 (\r
echo %0 signtool sign %%f failed?\r
echo %0 file %CD%\%%f\r
echo +\r
)\r
\r
- echo %0 - Signing %%d .sys files\r
+ echo %0 [%OE%] Signing %%d .sys files\r
for %%f in ( *.sys ) do (\r
- echo %0 - Signing %%d\%%f\r
- signtool sign /ac %1 /n %2 %TS% %DU% %%f\r
+ echo %0 [%OE%] Signing %%d\%%f\r
+ signtool sign /ac %1 /s "My" /n %2 %TS% %DU% %%f\r
if ERRORLEVEL 1 (\r
echo %0 signtool sign %%f failed?\r
echo %0 file %CD%\%%f\r
echo +\r
)\r
\r
- echo %0 - Verify %%d .cat + .sys files\r
+ echo %0 [%OE%] Verify %%d .cat + .sys files\r
for %%f in ( *.sys ) do (\r
set D=%%f\r
set C=!D:sys=cat!\r
if exist !C! (\r
- echo %0 - Verify %%d\!C! %%d\%%f\r
+ echo %0 [%OE%] Verify %%d\!C! %%d\%%f\r
signtool verify /q /kp /c !C! %%f\r
if ERRORLEVEL 1 (\r
echo %0 signtool verify /kp /c !C! %%f failed?\r
)\r
)\r
\r
+echo %0 [%OE%] Finished: %0 %1 %2\r
+echo +\r
endlocal\r
-echo %0 - Finished: %0 %1 %2 %OE% \r
<![CDATA[Msix64]]>\r
</Condition>\r
\r
- <Condition Message="[ProductName] requires Windows Server 2008 or Vista to install.">\r
- <![CDATA[(VersionNT=600)]]>\r
+ <Condition Message="[ProductName] requires Windows 7 or Server 2008 R2 to install.">\r
+ <![CDATA[(VersionNT=601)]]>\r
</Condition>\r
\r
<?include ..\..\common\requirements.inc ?>\r
<Condition Message="This package can be installed on x86 systems only">\r
<![CDATA[(Not Intel64) And (Not Msix64)]]></Condition>\r
\r
- <Condition Message="[ProductName] requires Windows Server 2008 or Vista to install.">\r
- <![CDATA[(VersionNT=600)]]></Condition>\r
+ <Condition Message="[ProductName] requires Windows 7 or Server 2008 R2 to install.">\r
+ <![CDATA[(VersionNT=601)]]></Condition>\r
\r
<?include ..\..\common\requirements.inc ?>\r
\r
<![CDATA[VersionNT64]]>\r
</Condition>\r
\r
- <Condition Message="[ProductName] requires Windows Server 2008 to install.">\r
- <![CDATA[(VersionNT=600)]]>\r
+ <Condition\r
+ Message="[ProductName] requires Windows Server 2008 to install.">\r
+ <![CDATA[(VersionNT=600 OR VersionNT=601)]]>\r
</Condition>\r
\r
<?include ..\..\common\requirements.inc ?>\r
Display="expand" Level="2" ConfigurableDirectory="INSTALLDIR"\r
AllowAdvertise="no" InstallDefault="local" Absent="allow">\r
<ComponentRef Id="cNetworkDirect" />\r
- <Condition Level="201"> IPOIB_EXISTS </Condition> \r
+ <Condition Level="201"> IPOIB_EXISTS </Condition>\r
</Feature>\r
-->\r
<Feature Id="fOSMS" Title="OpenSM Service Started" Level="5"\r
</Feature>\r
\r
<Feature Id="fSRP" Title="SRP" Level="5" Description="SCSI over RDMA"\r
- Display="expand" ConfigurableDirectory="INSTALLDIR"\r
- AllowAdvertise='no' InstallDefault='local' Absent='allow'>\r
+ Display="expand" ConfigurableDirectory="INSTALLDIR"\r
+ AllowAdvertise="no" InstallDefault="local" Absent="allow">\r
<ComponentRef Id="cSRP_driver_installed" />\r
</Feature>\r
\r
rem CrossCertFilename - fully qualified path\filename of cross cert.\r
rem CertStoreName - name of certificate in 'MY' Cert store (certmgr).\r
\r
-rem example: signDrivers %CD%\cse1CStore TestCert bin\hca\r
+rem example: signDrivers %CD%\Cross-Cert SWPublisher bin\hca\r
\r
rem cmd.exe /V:on (delayed environment variable expansion) is required!\r
set F=on\r
path > jnk.txt\r
findstr /c:"SelfSign" jnk.txt > jnk1.txt\r
if %errorlevel% EQU 1 (\r
- path "%PATH%;C:\WinDDK\6001.18001\bin\SelfSign"\r
+ path "%PATH%;C:\WinDDK\xxx\bin\SelfSign"\r
)\r
if exist jnk1.txt del /Q /F jnk1.txt\r
if exist jnk.txt del /Q /F jnk.txt\r
if "%%d" == "x86" set OEA=%OE%_X86,Vista_X86\r
if "%%d" == "ia64" set OEA=%OE%_IA64\r
\r
- echo %0 - Generating %%d .cat files for !OEA!\r
- inf2cat /driver:%CD%\%%d /os:!OEA!\r
+ echo %0 [%OE%] Generating %%d .cat files for !OEA!\r
+ inf2cat /driver:!CD! /os:!OEA!\r
if ERRORLEVEL 1 (\r
echo %CD% inf2cat failed\r
exit /B 1\r
)\r
- echo %0 - Signing %%d .cat files\r
+ echo %0 [%OE%] Signing %%d .cat files\r
for %%f in ( *.cat ) do (\r
- echo %0 - Signing %%d\%%f\r
- signtool sign /ac %1 /n %2 %TS% %DU% %%f\r
+ echo %0 [%OE%] Signing %%d\%%f\r
+ signtool sign /ac %1 /s "My" /n %2 %TS% %DU% %%f\r
if ERRORLEVEL 1 (\r
echo %0 signtool sign %%f failed?\r
echo %0 file %CD%\%%f\r
echo +\r
)\r
\r
- echo %0 - Signing %%d .sys files\r
+ echo %0 [%OE%] Signing %%d .sys files\r
for %%f in ( *.sys ) do (\r
- echo %0 - Signing %%d\%%f\r
- signtool sign /ac %1 /n %2 %TS% %DU% %%f\r
+ echo %0 [%OE%] Signing %%d\%%f\r
+ signtool sign /ac %1 /s "My" /n %2 %TS% %DU% %%f\r
if ERRORLEVEL 1 (\r
echo %0 signtool sign %%f failed?\r
echo %0 file %CD%\%%f\r
echo +\r
)\r
\r
- echo %0 - Verify %%d .cat + .sys files\r
+ echo %0 [%OE%] Verify %%d .cat + .sys files\r
for %%f in ( *.sys ) do (\r
set D=%%f\r
set C=!D:sys=cat!\r
if exist !C! (\r
- echo %0 - Verify %%d\!C! %%d\%%f\r
+ echo %0 [%OE%] Verify %%d\!C! %%d\%%f\r
signtool verify /q /kp /c !C! %%f\r
if ERRORLEVEL 1 (\r
echo %0 signtool verify /kp /c !C! %%f failed?\r
)\r
)\r
\r
+echo %0 [%OE%] Finished: %0 %1 %2\r
+echo +\r
endlocal\r
-echo %0 - Finished: %0 %1 %2 %OE% \r
<![CDATA[Msix64]]>\r
</Condition>\r
\r
- <Condition Message="[ProductName] requires Windows Server 2008 or Vista to install.">\r
- <![CDATA[(VersionNT=600)]]>\r
+ <Condition\r
+ Message="[ProductName] requires Windows Server 2008 or Vista to install.">\r
+ <![CDATA[(VersionNT=600 OR VersionNT=601)]]>\r
</Condition>\r
\r
<?include ..\..\common\requirements.inc ?>\r
</Feature>\r
\r
<Feature Id="fWSD" Title="WSD" Description="Winsock Direct Enabled"\r
- Display="expand" Level="1" ConfigurableDirectory="INSTALLDIR"\r
- AllowAdvertise='no' InstallDefault='local' Absent='allow'>\r
+ Display="expand" Level="1" ConfigurableDirectory="INSTALLDIR"\r
+ AllowAdvertise='no' InstallDefault='local' Absent='allow'>\r
<!-- skip WSD on Windows XP, IPoIB is required for WSD. -->\r
<Condition Level="200"><![CDATA[VersionNT=501]]></Condition>\r
<Condition Level="201"> IPOIB_EXISTS </Condition>\r
</Feature>\r
\r
<Feature Id="fSRP" Title="SRP" Level="5" Description="SCSI over RDMA"\r
- Display="expand" ConfigurableDirectory="INSTALLDIR"\r
- AllowAdvertise='no' InstallDefault='local' Absent='allow'>\r
+ Display="expand" ConfigurableDirectory="INSTALLDIR"\r
+ AllowAdvertise="no" InstallDefault="local" Absent="allow">\r
<ComponentRef Id="cSRP_driver_installed" />\r
</Feature>\r
\r
</Condition>\r
\r
<Condition Message="This package can be installed on x86 systems only">\r
- <![CDATA[(Not Intel64) And (Not Msix64)]]></Condition>\r
+ <![CDATA[(Not Intel64) And (Not Msix64)]]>\r
+ </Condition>\r
\r
- <Condition Message="[ProductName] requires Windows Server 2008 or Vista to install.">\r
- <![CDATA[(VersionNT=600)]]></Condition>\r
+ <Condition\r
+ Message="[ProductName] requires Windows Server 2008 or Vista to install.">\r
+ <![CDATA[(VersionNT=600 OR VersionNT=601)]]>\r
+ </Condition>\r
\r
<?include ..\..\common\requirements.inc ?>\r
\r
Description="Internet Protocols over InfiniBand" Display="expand"\r
ConfigurableDirectory="INSTALLDIR" AllowAdvertise="no"\r
InstallDefault="local" Absent="allow">\r
- <ComponentRef Id="IPoIB" />\r
+ <ComponentRef Id="IPoIB" />\r
</Feature>\r
\r
<Feature Id="fWSD" Title="WSD" Description="Winsock Direct Enabled"\r
Description="Open Subnet Management started as a local Windows Service"\r
Display="expand" ConfigurableDirectory="INSTALLDIR" AllowAdvertise="no"\r
InstallDefault="local" Absent="allow">\r
- <ComponentRef Id="OpenSM_Service_enabled" />\r
+ <ComponentRef Id="OpenSM_Service_enabled" />\r
</Feature>\r
\r
<Feature Id="fDAPL" Title="DAPL" Description="DAT+DAPL over InfiniBand"\r
</Feature>\r
\r
<Feature Id="fSRP" Title="SRP" Level="5" Description="SCSI over RDMA"\r
- Display="expand" ConfigurableDirectory="INSTALLDIR" AllowAdvertise="no"\r
- InstallDefault="local" Absent="allow">\r
+ Display="expand" ConfigurableDirectory="INSTALLDIR"\r
+ AllowAdvertise="no" InstallDefault="local" Absent="allow">\r
<!-- skip SRP on 32-bit Windows XP -->\r
<Condition Level="0">\r
<![CDATA[VersionNT=501 AND (Not Intel64 AND Not Msix64)]]>\r
</Condition>\r
- <ComponentRef Id="cSRP_driver_installed" />\r
+ <ComponentRef Id="cSRP_driver_installed" />\r
</Feature>\r
\r
<Feature Id="fVNIC" Title="QLogic-VNIC"\r
rem CrossCertFilename - fully qualified path\filename of cross cert.\r
rem CertStoreName - name of certificate in 'MY' Cert store (certmgr).\r
\r
-rem example: signDrivers %CD%\cse1CStore TestCert bin\hca\r
+rem example: signDrivers %CD%\Cross-Cert SWPublisher bin\hca\r
\r
rem cmd.exe /V:on (delayed environment variable expansion) is required!\r
set F=on\r
path > jnk.txt\r
findstr /c:"SelfSign" jnk.txt > jnk1.txt\r
if %errorlevel% EQU 1 (\r
- path "%PATH%;C:\WinDDK\6001.18001\bin\SelfSign"\r
+ path "%PATH%;C:\WinDDK\xxx\bin\SelfSign"\r
)\r
if exist jnk1.txt del /Q /F jnk1.txt\r
if exist jnk.txt del /Q /F jnk.txt\r
if "%%d" == "x86" set OEA=%OE%_X86\r
if "%%d" == "ia64" set OEA=%OE%_IA64\r
\r
- echo %0 - Generating %%d .cat files for !OEA!\r
- inf2cat /driver:%CD%\%%d /os:!OEA!\r
+ echo %0 [%OE%] Generating %%d .cat files for !OEA!\r
+ inf2cat /driver:!CD! /os:!OEA!\r
if ERRORLEVEL 1 (\r
echo %CD% inf2cat failed\r
exit /B 1\r
)\r
- echo %0 - Signing %%d .cat files\r
+ echo %0 [%OE%] Signing %%d .cat files\r
for %%f in ( *.cat ) do (\r
- echo %0 - Signing %%d\%%f\r
- signtool sign /ac %1 /n %2 %TS% %DU% %%f\r
+ echo %0 [%OE%] Signing %%d\%%f\r
+ signtool sign /ac %1 /s "My" /n %2 %TS% %DU% %%f\r
if ERRORLEVEL 1 (\r
echo %0 signtool sign %%f failed?\r
echo %0 file %CD%\%%f\r
echo +\r
)\r
\r
- echo %0 - Signing %%d .sys files\r
+ echo %0 [%OE%] Signing %%d .sys files\r
for %%f in ( *.sys ) do (\r
- echo %0 - Signing %%d\%%f\r
- signtool sign /ac %1 /n %2 %TS% %DU% %%f\r
+ echo %0 [%OE%] Signing %%d\%%f\r
+ signtool sign /ac %1 /s "My" /n %2 %TS% %DU% %%f\r
if ERRORLEVEL 1 (\r
echo %0 signtool sign %%f failed?\r
echo %0 file %CD%\%%f\r
echo +\r
)\r
\r
- echo %0 - Verify %%d .cat + .sys files\r
+ echo %0 [%OE%] Verify %%d .cat + .sys files\r
for %%f in ( *.sys ) do (\r
set D=%%f\r
set C=!D:sys=cat!\r
if exist !C! (\r
- echo %0 - Verify %%d\!C! %%d\%%f\r
+ echo %0 [%OE%] Verify %%d\!C! %%d\%%f\r
signtool verify /q /kp /c !C! %%f\r
if ERRORLEVEL 1 (\r
echo %0 signtool verify /kp /c !C! %%f failed?\r
)\r
)\r
\r
+echo %0 [%OE%] Finished: %0 %1 %2\r
+echo +\r
endlocal\r
-echo %0 - Finished: %0 %1 %2 %OE% \r
rem CrossCertFilename - fully qualified path\filename of cross cert.\r
rem CertStoreName - name of certificate in 'MY' Cert store (certmgr).\r
\r
-rem example: signDrivers %CD%\cse1CStore TestCert bin\hca\r
+rem example: signDrivers %CD%\Cross-Cert SWPublisher bin\hca\r
\r
rem cmd.exe /V:on (delayed environment variable expansion) is required!\r
set F=on\r
path > jnk.txt\r
findstr /c:"SelfSign" jnk.txt > jnk1.txt\r
if %errorlevel% EQU 1 (\r
- path "%PATH%;C:\WinDDK\6001.18001\bin\SelfSign"\r
+ path "%PATH%;C:\WinDDK\xxx\bin\SelfSign"\r
)\r
if exist jnk1.txt del /Q /F jnk1.txt\r
if exist jnk.txt del /Q /F jnk.txt\r
echo %0 - missing relative path %3\r
exit /B 1\r
)\r
-echo cwd %CD%\r
+echo cwd !CD!\r
\r
rem Sign drivers only for x86 architecture\r
\r
rem if "%%d" == "amd64" set OEA=%OE%_X64\r
rem if "%%d" == "ia64" set OEA=%OE%_IA64\r
\r
- echo %0 - Generating %%d .cat files for !OEA!\r
- inf2cat /driver:%CD%\%%d /os:!OEA!\r
+ echo %0 [%OE%] Generating %%d .cat files for !OEA!\r
+ inf2cat /driver:!CD! /os:!OEA!\r
if ERRORLEVEL 1 (\r
echo %CD% inf2cat failed\r
exit /B 1\r
)\r
- echo %0 - Signing %%d .cat files\r
+ echo %0 [%OE%] Signing %%d .cat files\r
for %%f in ( *.cat ) do (\r
- echo %0 - Signing %%d\%%f\r
- signtool sign /ac %1 /n %2 %TS% %DU% %%f\r
+ echo %0 [%OE%] Signing %%d\%%f\r
+ signtool sign /ac %1 /s "My" /n %2 %TS% %DU% %%f\r
if ERRORLEVEL 1 (\r
echo %0 signtool sign %%f failed?\r
echo %0 file %CD%\%%f\r
echo +\r
)\r
\r
- echo %0 - Signing %%d .sys files\r
+ echo %0 [%OE%] Signing %%d .sys files\r
for %%f in ( *.sys ) do (\r
- echo %0 - Signing %%d\%%f\r
- signtool sign /ac %1 /n %2 %TS% %DU% %%f\r
+ echo %0 [%OE%] Signing %%d\%%f\r
+ signtool sign /ac %1 /s "My" /n %2 %TS% %DU% %%f\r
if ERRORLEVEL 1 (\r
echo %0 signtool sign %%f failed?\r
echo %0 file %CD%\%%f\r
echo +\r
)\r
\r
- echo %0 - Verify %%d .cat + .sys files\r
+ echo %0 [%OE%] Verify %%d .cat + .sys files\r
for %%f in ( *.sys ) do (\r
set D=%%f\r
set C=!D:sys=cat!\r
if exist !C! (\r
- echo %0 - Verify %%d\!C! %%d\%%f\r
+ echo %0 [%OE%] Verify %%d\!C! %%d\%%f\r
signtool verify /q /kp /c !C! %%f\r
if ERRORLEVEL 1 (\r
echo %0 signtool verify /kp /c !C! %%f failed?\r
)\r
)\r
\r
+echo %0 [%OE%] Finished: %0 %1 %2\r
+echo +\r
endlocal\r
-echo %0 - Finished: %0 %1 %2 %OE% \r
IN ib_al_handle_t h_al,\r
IN OUT net32_t* const p_cid );\r
\r
-void\r
+ib_api_status_t\r
kal_cep_config(\r
IN ib_al_handle_t h_al,\r
IN net32_t cid,\r
IN uint8_t rnr_nak_timeout,\r
IN OUT ib_qp_mod_t* const p_init OPTIONAL );\r
\r
-ib_api_status_t\r
-kal_cep_config_pre_rep_copy_cid(\r
- IN ib_al_handle_t h_al,\r
- IN net32_t cid,\r
- IN al_pfn_cep_cb_t pfn_cb,\r
- IN void* context,\r
- IN ib_pfn_destroy_cb_t pfn_destroy_cb,\r
- IN const iba_cm_rep* const p_cm_rep,\r
- IN uint8_t rnr_nak_timeout,\r
- IN OUT net32_t* const p_cid,\r
- OUT ib_qp_mod_t* const p_init );\r
-\r
void\r
kal_cep_destroy(\r
IN ib_al_handle_t h_al,\r
IN net32_t cid,\r
IN IRP* const p_irp );\r
\r
-NTSTATUS\r
-al_cep_get_cid(\r
- IN ib_al_handle_t h_al,\r
- IN net32_t const cid,\r
- IN PIRP h_ioctl\r
- );\r
-\r
NTSTATUS\r
al_cep_get_pdata(\r
IN ib_al_handle_t h_al,\r
IN OUT uint8_t *p_psize,\r
OUT uint8_t* pdata );\r
\r
+void*\r
+kal_cep_get_context(\r
+ IN ib_al_handle_t h_al,\r
+ IN net32_t cid,\r
+ IN al_pfn_cep_cb_t pfn_cb,\r
+ IN ib_pfn_destroy_cb_t pfn_addref );\r
#endif /* CL_KERNEL */\r
\r
\r
#define AL_DEVICE_NAME L"\\Device\\ibal"\r
#define ALDEV_KEY (0x3B) /* Matches FILE_DEVICE_INFINIBAND from wdm.h */\r
\r
-#define AL_IOCTL_VERSION (11)\r
+#define AL_IOCTL_VERSION (12)\r
\r
/* max number of devices with non-default pkey */\r
#define MAX_NUM_PKEY 16\r
ual_cep_get_timewait,\r
ual_cep_get_event,\r
ual_cep_poll,\r
- ual_cep_get_req_cid,\r
ual_cep_get_pdata,\r
\r
al_cep_maxops\r
ual_ndi_dreq_cm_ioctl_cmd,\r
ual_ndi_noop,\r
ual_ndi_notify_dreq_cmd,\r
+ ual_ndi_cancel_cm_irps,\r
+ ual_ndi_listen_cm_cmd,\r
+ ual_ndi_get_req_cm_cmd,\r
\r
al_ndi_maxops\r
\r
#define UAL_NDI_DREQ_CM IOCTL_CODE(ALDEV_KEY, ual_ndi_dreq_cm_ioctl_cmd)\r
#define UAL_NDI_NOOP IOCTL_CODE(ALDEV_KEY, ual_ndi_noop)\r
#define UAL_NDI_NOTIFY_DREQ IOCTL_CODE(ALDEV_KEY, ual_ndi_notify_dreq_cmd)\r
+#define UAL_NDI_CANCEL_CM_IRPS IOCTL_CODE(ALDEV_KEY, ual_ndi_cancel_cm_irps)\r
+#define UAL_NDI_LISTEN_CM IOCTL_CODE(ALDEV_KEY, ual_ndi_listen_cm_cmd)\r
+#define UAL_NDI_GET_REQ_CM IOCTL_CODE(ALDEV_KEY, ual_ndi_get_req_cm_cmd)\r
\r
/*\r
* Various Operation Allowable on the System Helper\r
#define UAL_CEP_GET_TIMEWAIT IOCTL_CODE(ALDEV_KEY, ual_cep_get_timewait)\r
#define UAL_CEP_GET_EVENT IOCTL_CODE(ALDEV_KEY, ual_cep_get_event)\r
#define UAL_CEP_POLL IOCTL_CODE(ALDEV_KEY, ual_cep_poll)\r
-#define UAL_CEP_GET_REQ_CID IOCTL_CODE(ALDEV_KEY, ual_cep_get_req_cid)\r
#define UAL_CEP_GET_PDATA IOCTL_CODE(ALDEV_KEY, ual_cep_get_pdata)\r
\r
\r
break;\r
}\r
status = init_conn_qp( (al_conn_qp_t*)h_qp, h_pd, p_qp_create, p_umv_buf );\r
-#ifdef CL_KERNEL\r
- if( status == IB_SUCCESS && !NT_SUCCESS( ndi_qp_init(h_qp) ) )\r
- status = IB_ERROR;\r
-#endif\r
break;\r
\r
case IB_QPT_UNRELIABLE_DGRM:\r
case IB_QPT_RELIABLE_CONN:\r
case IB_QPT_UNRELIABLE_CONN:\r
al_destroy_cep( h_qp->obj.h_al, &((al_conn_qp_t*)h_qp)->cid, FALSE );\r
-#ifdef CL_KERNEL\r
- ndi_qp_destroy( h_qp );\r
-#endif\r
\r
/* Fall through. */\r
case IB_QPT_UNRELIABLE_DGRM:\r
CL_ASSERT( p_obj );\r
h_qp = PARENT_STRUCT( p_obj, ib_qp_t, obj );\r
\r
-#ifdef CL_KERNEL\r
- ndi_qp_free( h_qp );\r
-#endif\r
-\r
destroy_al_obj( p_obj );\r
cl_free( h_qp );\r
}\r
IN const ib_qp_handle_t h_qp,\r
IN const ib_mcast_req_t* const p_mcast_req );\r
\r
-#ifdef CL_KERNEL\r
- ndi_qp_csq_t *p_irp_queue;\r
-#endif\r
-\r
} ib_qp_t;\r
\r
\r
* NDI stuff - TODO: manage above core kernel CM code\r
*/\r
\r
- /* IRP list head */\r
- LIST_ENTRY irp_que;\r
-\r
/* private data of REQ, REP, REJ CM requests */ \r
uint8_t psize;\r
uint8_t pdata[IB_REP_PDATA_SIZE];\r
* CEP manager API\r
******************************************************************************/\r
\r
-static inline void \r
-__complete_ndi_irp(\r
- IN PIRP p_irp,\r
- IN ib_mad_element_t* p_mad )\r
-{\r
- net32_t* p_new_cid = (net32_t*)cl_ioctl_out_buf( p_irp );\r
- kcep_t* p_cep = (kcep_t*)p_mad->send_context1;\r
-\r
- AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_CM,\r
- ("Completing al_cep_get_cid IRP with CID = %d\n", p_cep->cid) );\r
-\r
- *p_new_cid = p_cep->cid;\r
- p_irp->IoStatus.Information = sizeof(uint32_t);\r
- p_irp->IoStatus.Status = STATUS_SUCCESS;\r
- IoCompleteRequest( p_irp, IO_NETWORK_INCREMENT );\r
- ib_put_mad( p_mad );\r
-}\r
-\r
\r
/* Called with the CEP and CEP manager locks held */\r
static ib_api_status_t\r
if ( p_cep->state == CEP_STATE_LISTEN &&\r
(p_cep->sid & ~0x0ffffffI64) == IB_REQ_CM_RDMA_SID_PREFIX )\r
{ /* Try to complete pending IRP, if any */\r
- PIRP p_irp;\r
- PLIST_ENTRY p_list_entry;\r
mad_cm_req_t* p_req = (mad_cm_req_t*)ib_get_mad_buf( p_mad );\r
ib_cm_rdma_req_t *p_rdma_req = (ib_cm_rdma_req_t *)p_req->pdata;\r
\r
p_rdma_req->maj_min_ver, p_rdma_req->ipv ) );\r
return IB_UNSUPPORTED;\r
}\r
- \r
- /* get a pending IRP */\r
- if ( !IsListEmpty( &p_cep->irp_que ) )\r
- {\r
- // get IRP\r
- p_list_entry = RemoveHeadList( &p_cep->irp_que );\r
- p_irp = (PIRP)CONTAINING_RECORD( p_list_entry, IRP, Tail.Overlay.ListEntry );\r
-\r
- // complete GetConnectionReq IRP\r
-#pragma warning(push, 3)\r
- IoSetCancelRoutine( p_irp, NULL );\r
-#pragma warning(pop)\r
-\r
- __complete_ndi_irp( p_irp, p_mad );\r
-\r
- AL_EXIT( AL_DBG_CM );\r
- return IB_PENDING;\r
- }\r
}\r
\r
/* Queue this MAD for processing. */\r
\r
p_cep->p_cid->p_cep = p_cep;\r
\r
- InitializeListHead( &p_cep->irp_que );\r
-\r
ref_al_obj( &gp_cep_mgr->obj );\r
\r
AL_EXIT( AL_DBG_CM );\r
return IB_SUCCESS;\r
}\r
\r
-void\r
+ib_api_status_t\r
kal_cep_config(\r
IN ib_al_handle_t h_al,\r
IN net32_t cid,\r
\r
KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );\r
p_cep = __lookup_cep( h_al, cid );\r
- CL_ASSERT( p_cep );\r
+ if( p_cep == NULL )\r
+ {\r
+ KeReleaseInStackQueuedSpinLock( &hdl );\r
+ return IB_INVALID_HANDLE;\r
+ }\r
\r
p_cep->pfn_cb = pfn_cb;\r
p_cep->context = context;\r
p_cep->pfn_destroy_cb = pfn_destroy_cb;\r
\r
KeReleaseInStackQueuedSpinLock( &hdl );\r
+ return IB_SUCCESS;\r
}\r
\r
static inline void\r
status = kal_cep_alloc(h_al, p_cid);\r
if ( status == IB_SUCCESS )\r
{\r
- kal_cep_config(h_al, *p_cid, pfn_cb, context, pfn_destroy_cb);\r
+ status = kal_cep_config(h_al, *p_cid, pfn_cb, context, pfn_destroy_cb);\r
}\r
\r
AL_EXIT( AL_DBG_CM );\r
context = p_cep->context;\r
pfn_destroy_cb = p_cep->pfn_destroy_cb;\r
\r
- /* Cancel any queued IRP */\r
- __cep_complete_irp( p_cep, STATUS_CANCELLED, IO_NO_INCREMENT );\r
-\r
- while( !IsListEmpty( &p_cep->irp_que ) )\r
- {\r
- LIST_ENTRY* p_list_entry;\r
- IRP* p_irp;\r
-\r
- // get IRP\r
- p_list_entry = RemoveHeadList( &p_cep->irp_que );\r
- p_irp = (PIRP)CONTAINING_RECORD( p_list_entry, IRP, Tail.Overlay.ListEntry );\r
-\r
- // complete GetConnectionReq IRP\r
-#pragma warning(push, 3)\r
- IoSetCancelRoutine( p_irp, NULL );\r
-#pragma warning(pop)\r
-\r
- p_irp->IoStatus.Information = 0;\r
- p_irp->IoStatus.Status = STATUS_CANCELLED;\r
- IoCompleteRequest( p_irp, IO_NETWORK_INCREMENT );\r
- }\r
-\r
__unbind_cep( p_cep );\r
ref_cnt = __cleanup_cep( p_cep );\r
if( reusable )\r
}\r
\r
\r
-ib_api_status_t\r
-kal_cep_config_pre_rep_copy_cid(\r
- IN ib_al_handle_t h_al,\r
- IN net32_t cid,\r
- IN al_pfn_cep_cb_t pfn_cb,\r
- IN void* context,\r
- IN ib_pfn_destroy_cb_t pfn_destroy_cb,\r
- IN const iba_cm_rep* const p_cm_rep,\r
- IN uint8_t rnr_nak_timeout,\r
- IN OUT net32_t* const p_cid,\r
- OUT ib_qp_mod_t* const p_init )\r
-{\r
- kcep_t *p_cep;\r
- KLOCK_QUEUE_HANDLE hdl;\r
- ib_api_status_t status;\r
-\r
- CL_ASSERT( h_al );\r
- CL_ASSERT( p_cm_rep );\r
- CL_ASSERT( p_init );\r
-\r
- KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );\r
- if (*p_cid != AL_INVALID_CID)\r
- {\r
- status = IB_RESOURCE_BUSY;\r
- goto out;\r
- }\r
-\r
- p_cep = __lookup_cep( h_al, cid );\r
- if (!p_cep )\r
- {\r
- status = IB_INVALID_HANDLE;\r
- goto out;\r
- }\r
-\r
- status = __al_cep_pre_rep( p_cep, p_cm_rep, rnr_nak_timeout, p_init );\r
- if ( status == IB_SUCCESS )\r
- {\r
- p_cep->pfn_cb = pfn_cb;\r
- p_cep->context = context;\r
- p_cep->pfn_destroy_cb = pfn_destroy_cb;\r
- *p_cid = cid;\r
- }\r
-\r
-out:\r
- KeReleaseInStackQueuedSpinLock( &hdl );\r
- return status;\r
-}\r
-\r
-\r
ib_api_status_t\r
kal_cep_pre_rep(\r
IN ib_al_handle_t h_al,\r
AL_EXIT( AL_DBG_CM );\r
}\r
\r
-NTSTATUS\r
-al_cep_get_cid(\r
- IN ib_al_handle_t h_al,\r
- IN net32_t const cid,\r
- IN PIRP p_irp\r
- )\r
-{\r
- kcep_t *p_cep;\r
- NTSTATUS nt_status;\r
- KLOCK_QUEUE_HANDLE hdl;\r
- ib_mad_element_t* p_mad = NULL;\r
-\r
- AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_CM, ("[ CID = %d\n", cid) );\r
- KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );\r
-\r
- p_cep = __lookup_cep( h_al, cid );\r
- if( !p_cep )\r
- {\r
- p_irp->IoStatus.Information = 0;\r
- p_irp->IoStatus.Status = STATUS_INVALID_PARAMETER;\r
- IoCompleteRequest( p_irp, IO_NETWORK_INCREMENT );\r
- nt_status = STATUS_EVENT_DONE;\r
- goto exit;\r
- }\r
-\r
- if( !p_cep->p_mad_head )\r
- { /* no pending MADs - queue the IRP */ \r
- p_cep->signalled = FALSE;\r
- InsertTailList( &p_cep->irp_que, &p_irp->Tail.Overlay.ListEntry );\r
- p_irp->Tail.Overlay.DriverContext[0] = (void*)(size_t)cid;\r
- p_irp->Tail.Overlay.DriverContext[1] = (void*)h_al;\r
-#pragma warning(push, 3)\r
- IoSetCancelRoutine( p_irp, __cep_cancel_ndi_irp );\r
-#pragma warning(pop)\r
- IoMarkIrpPending( p_irp );\r
- nt_status = STATUS_PENDING;\r
- goto exit;\r
- }\r
-\r
- /* Set the MAD. */\r
- p_mad = p_cep->p_mad_head;\r
- p_cep->p_mad_head = p_mad->p_next;\r
- p_mad->p_next = NULL;\r
-\r
- /* complete the IRP */\r
- __complete_ndi_irp( p_irp, p_mad );\r
- nt_status = STATUS_EVENT_DONE;\r
- \r
-exit:\r
- KeReleaseInStackQueuedSpinLock( &hdl );\r
- AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_CM, ("] returned %08x\n", nt_status) );\r
- return nt_status;\r
-}\r
-\r
\r
NTSTATUS\r
al_cep_get_pdata(\r
AL_EXIT( AL_DBG_CM );\r
return STATUS_SUCCESS;\r
}\r
+\r
+\r
+/*\r
+ * This function is designed to support moving the NetorkDirect IRP queue to the CEP\r
+ * without performing major surgery on the CEP manager.\r
+ *\r
+ * It retrieves the context associated with a CEP, using the pfn_addref function\r
+ * to prevent the context from being destroyed after it is returned.\r
+ *\r
+ * It returns NULL if there is no context, requiring contexts to be pointers.\r
+ */\r
+void*\r
+kal_cep_get_context(\r
+ IN ib_al_handle_t h_al,\r
+ IN net32_t cid,\r
+ IN al_pfn_cep_cb_t pfn_cb,\r
+ IN ib_pfn_destroy_cb_t pfn_addref )\r
+{\r
+ kcep_t *p_cep;\r
+ void* context = NULL;\r
+ KLOCK_QUEUE_HANDLE hdl;\r
+\r
+ AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_CM, ("[ CID = %d\n", cid) );\r
+\r
+ CL_ASSERT( h_al );\r
+ CL_ASSERT( pfn_addref );\r
+\r
+ KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );\r
+ p_cep = __lookup_cep( h_al, cid );\r
+ if( !p_cep )\r
+ {\r
+ AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, \r
+ ("CEP not found for cid %d, h_al %p\n", cid, h_al ));\r
+ goto out;\r
+ }\r
+\r
+ if( p_cep->pfn_cb != pfn_cb )\r
+ {\r
+ AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
+ ("CEP callback mismatch for cid %d, h_al %p\n", cid, h_al ));\r
+ goto out;\r
+ }\r
+\r
+ context = p_cep->context;\r
+ if( context != NULL )\r
+ {\r
+ pfn_addref( context );\r
+ }\r
+\r
+out:\r
+ KeReleaseInStackQueuedSpinLock( &hdl );\r
+ AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_CM, ("] returning %p\n", context) );\r
+ return context;\r
+}\r
\r
NTSTATUS\r
__ndi_send_rep(\r
- IN ib_qp_handle_t h_qp,\r
+ IN nd_csq_t *p_csq,\r
IN PIRP p_irp\r
);\r
\r
IN IRP* p_irp\r
);\r
\r
+NTSTATUS\r
+__ndi_get_req(\r
+ IN nd_csq_t *p_csq,\r
+ IN IRP* p_irp\r
+ );\r
+\r
static void\r
__ndi_queue_drep(\r
IN IRP *p_irp\r
);\r
\r
+\r
/*******************************************************************\r
*\r
* Helpers\r
\r
static inline void\r
__ndi_complete_irp(\r
- IN ib_qp_handle_t h_qp,\r
+ IN nd_csq_t* p_csq,\r
IN PIRP p_irp,\r
IN NTSTATUS status\r
)\r
{\r
- AL_ENTER( AL_DBG_NDI );\r
+ AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI, ("[ CID = %d\n", p_csq->cid) );\r
\r
CL_ASSERT( p_irp );\r
CL_ASSERT( p_irp->Tail.Overlay.DriverContext[1] == NULL );\r
p_irp->IoStatus.Information = 0;\r
IoCompleteRequest( p_irp, 0 );\r
}\r
- deref_al_obj( &h_qp->obj ); /* Release IRP reference */\r
+ nd_csq_release( p_csq ); /* Release IRP reference */\r
\r
AL_EXIT( AL_DBG_NDI );\r
}\r
*/\r
static void\r
__cep_timewait_qp(\r
- IN const ib_qp_handle_t h_qp )\r
+ IN nd_csq_t *p_csq )\r
{\r
uint64_t timewait = 0;\r
+ ib_qp_handle_t h_qp;\r
ib_qp_mod_t qp_mod;\r
ib_api_status_t status;\r
\r
AL_ENTER( AL_DBG_CM );\r
\r
- CL_ASSERT( h_qp );\r
+ CL_ASSERT( p_csq != NULL );\r
\r
/*\r
* The CM should have set the proper timewait time-out value. Reset\r
* the QP and let it enter the timewait state.\r
*/\r
- if( al_cep_get_timewait( h_qp->obj.h_al,\r
- ((al_conn_qp_t*)h_qp)->cid, &timewait ) == IB_SUCCESS )\r
+ if( al_cep_get_timewait( p_csq->h_al, p_csq->cid, &timewait ) == IB_SUCCESS )\r
{\r
+ h_qp = CONTAINING_RECORD(\r
+ al_hdl_ref( p_csq->h_al, p_csq->h_qp, AL_OBJ_TYPE_H_QP ),\r
+ ib_qp_t,\r
+ obj );\r
+\r
/* Special checks on the QP state for error handling - see above. */\r
if( !h_qp || !AL_OBJ_IS_TYPE( h_qp, AL_OBJ_TYPE_H_QP ) ||\r
( (h_qp->obj.state != CL_INITIALIZED) && \r
status = h_qp->pfn_modify_qp( h_qp, &qp_mod, NULL );\r
if( status != IB_SUCCESS )\r
{\r
- AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
+ AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
("pfn_modify_qp to IB_QPS_ERROR returned %s\n",\r
ib_get_err_str( status )) );\r
- return;\r
}\r
-\r
-#ifdef CL_KERNEL\r
- /* Store the timestamp after which the QP exits timewait. */\r
- h_qp->timewait = cl_get_time_stamp() + timewait;\r
-#endif /* CL_KERNEL */\r
+ else\r
+ {\r
+ /* Store the timestamp after which the QP exits timewait. */\r
+ h_qp->timewait = cl_get_time_stamp() + timewait;\r
+ }\r
+ deref_al_obj( &h_qp->obj );\r
}\r
\r
AL_EXIT( AL_DBG_CM );\r
\r
static ib_api_status_t\r
__ndi_qp2rts(\r
- IN ib_qp_handle_t const h_qp,\r
+ IN nd_csq_t* p_csq,\r
IN PIRP p_irp\r
)\r
{\r
ib_api_status_t status;\r
+ ib_qp_handle_t h_qp;\r
ib_qp_mod_t qp_mod;\r
\r
- AL_ENTER( AL_DBG_NDI );\r
+ AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI,\r
+ ("[ CID = %d\n", p_csq->cid) );\r
+\r
+ h_qp = CONTAINING_RECORD(\r
+ al_hdl_ref( p_csq->h_al, p_csq->h_qp, AL_OBJ_TYPE_H_QP ),\r
+ ib_qp_t,\r
+ obj );\r
+ if( h_qp == NULL )\r
+ {\r
+ AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
+ ("Bad QP %I64d\n", p_csq->h_qp) );\r
+ status = IB_INVALID_HANDLE;\r
+ goto err;\r
+ }\r
+\r
+ AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI,\r
+ ("QP %p state %d\n", h_qp, h_qp->state) );\r
\r
/* fill required qp attributes */\r
- status = al_cep_get_rtr_attr( qp_get_al( h_qp ), \r
- ((al_conn_qp_t*)h_qp)->cid, &qp_mod );\r
+ status = al_cep_get_rtr_attr( p_csq->h_al, p_csq->cid, &qp_mod );\r
if ( status != IB_SUCCESS )\r
{\r
AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
- ("al_cep_get_rtr_attr returned %s\n", ib_get_err_str( status )) );\r
+ ("al_cep_get_rtr_attr for CID %d returned %s\n",\r
+ p_csq->cid, ib_get_err_str( status )) );\r
goto exit;\r
}\r
\r
if ( status != IB_SUCCESS )\r
{\r
AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
- ("ndi_modify_qp to RTR returned %s.\n", ib_get_err_str(status) ) );\r
+ ("ndi_modify_qp %p from %d to RTR returned %s.\n",\r
+ h_qp, h_qp->state, ib_get_err_str(status) ) );\r
goto exit;\r
}\r
\r
/* fill required qp attributes */\r
- status = al_cep_get_rts_attr( qp_get_al( h_qp ), \r
- ((al_conn_qp_t*)h_qp)->cid, &qp_mod );\r
+ status = al_cep_get_rts_attr( p_csq->h_al, p_csq->cid, &qp_mod );\r
if ( status != IB_SUCCESS )\r
{\r
AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
- ("al_cep_get_rts_attr returned %s\n", ib_get_err_str( status )) );\r
+ ("al_cep_get_rts_attr for CID %d returned %s\n",\r
+ p_csq->cid, ib_get_err_str( status )) );\r
goto exit;\r
}\r
\r
if ( status != IB_SUCCESS )\r
{\r
AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
- ("ndi_modify_qp to RTS returned %s.\n", ib_get_err_str(status) ) );\r
+ ("ndi_modify_qp %p from %d to RTS returned %s.\n",\r
+ h_qp, h_qp->state, ib_get_err_str(status) ) );\r
}\r
\r
exit:\r
+ deref_al_obj( &h_qp->obj );\r
+err:\r
AL_EXIT( AL_DBG_NDI );\r
return status;\r
}\r
)\r
{\r
NTSTATUS status;\r
- ndi_qp_csq_t *p_ndi_csq = (ndi_qp_csq_t*)pCsq;\r
+ nd_csq_t *p_ndi_csq = CONTAINING_RECORD( pCsq, nd_csq_t, csq );\r
\r
- AL_ENTER( AL_DBG_NDI );\r
+ AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI, ("[ CID = %d\n", p_ndi_csq->cid) );\r
switch( (ULONG_PTR)Context )\r
{\r
+ case NDI_CM_LISTEN:\r
+ status = __ndi_get_req( p_ndi_csq, pIrp );\r
+ break;\r
+\r
case NDI_CM_CONNECTING_QPR_SENT:\r
status = __ndi_pr_query( pIrp );\r
break;\r
status = __ndi_send_req( pIrp );\r
break;\r
\r
- case NDI_CM_CONNECTING_REP_SENT:\r
- status = __ndi_send_rep( p_ndi_csq->h_qp, pIrp );\r
- break;\r
-\r
case NDI_CM_DISCONNECTING:\r
status = __ndi_send_dreq( pIrp );\r
break;\r
\r
+ case NDI_CM_CONNECTED_DREQ_RCVD:\r
+ if( p_ndi_csq->state == NDI_CM_LISTEN )\r
+ {\r
+ AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_NDI,\r
+ ("] Invalid state (%d).\n", p_ndi_csq->state) );\r
+ return STATUS_INVALID_DEVICE_REQUEST;\r
+ }\r
+\r
+ /*\r
+ * Overwrite the context so that the state change\r
+ * below turns into a noop.\r
+ */\r
+ Context = (VOID*)(ULONG_PTR)p_ndi_csq->state;\r
+ status = STATUS_PENDING;\r
+ break;\r
+\r
default:\r
status = STATUS_INVALID_DEVICE_REQUEST;\r
ASSERT( FALSE );\r
}\r
\r
- if( status == STATUS_SUCCESS )\r
+ ASSERT( status == STATUS_PENDING || !NT_SUCCESS( status ) );\r
+ if( NT_SUCCESS( status ) )\r
{\r
+ AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI, ("] Queueing IRP\n") );\r
p_ndi_csq->state = (ndi_cm_state_t)(ULONG_PTR)Context;\r
InsertTailList( &p_ndi_csq->queue, &pIrp->Tail.Overlay.ListEntry );\r
- ref_al_obj( &p_ndi_csq->h_qp->obj ); /* Take IRP reference. */\r
+ nd_csq_ref( p_ndi_csq ); /* Take IRP reference. */\r
}\r
AL_EXIT( AL_DBG_NDI );\r
return status;\r
PIRP nextIrp = NULL;\r
PLIST_ENTRY nextEntry;\r
PLIST_ENTRY listHead;\r
- ndi_qp_csq_t *p_ndi_csq = (ndi_qp_csq_t*)Csq;\r
+ nd_csq_t *p_ndi_csq = (nd_csq_t*)Csq;\r
\r
AL_ENTER( AL_DBG_NDI );\r
\r
\r
static VOID __ndi_acquire_lock(\r
IN PIO_CSQ Csq,\r
- OUT PKIRQL Irql\r
+ OUT PKIRQL pIrql\r
)\r
{\r
- ndi_qp_csq_t *p_ndi_csq = (ndi_qp_csq_t*)Csq;\r
- ib_qp_handle_t h_qp = p_ndi_csq->h_qp;\r
- UNUSED_PARAM( Irql );\r
+ nd_csq_t *p_ndi_csq = (nd_csq_t*)Csq;\r
\r
- AL_ENTER( AL_DBG_NDI );\r
- cl_spinlock_acquire( &h_qp->obj.lock );\r
- AL_EXIT( AL_DBG_NDI );\r
+ KeAcquireSpinLock( &p_ndi_csq->lock, pIrql );\r
}\r
\r
static VOID __ndi_release_lock(\r
IN KIRQL Irql\r
)\r
{\r
- ndi_qp_csq_t *p_ndi_csq = (ndi_qp_csq_t*)Csq;\r
- ib_qp_handle_t h_qp = p_ndi_csq->h_qp;\r
- UNUSED_PARAM( Irql );\r
+ nd_csq_t *p_ndi_csq = (nd_csq_t*)Csq;\r
\r
- AL_ENTER( AL_DBG_NDI );\r
- cl_spinlock_release( &h_qp->obj.lock );\r
- AL_EXIT( AL_DBG_NDI );\r
+ KeReleaseSpinLock( &p_ndi_csq->lock, Irql );\r
}\r
\r
static VOID __ndi_complete_cancelled_irp(\r
IN PIRP p_irp\r
)\r
{\r
- ndi_qp_csq_t *p_ndi_csq = (ndi_qp_csq_t*)Csq;\r
- ib_qp_handle_t h_qp = p_ndi_csq->h_qp;\r
+ nd_csq_t *p_ndi_csq = (nd_csq_t*)Csq;\r
KIRQL irql;\r
ib_query_handle_t h_query;\r
\r
* SA callback by the CSQ lock.\r
*/\r
#pragma warning( disable:4305 )\r
- h_query = InterlockedExchangePointer( &h_qp->p_irp_queue->h_query, NULL );\r
+ h_query = InterlockedExchangePointer( &p_ndi_csq->h_query, NULL );\r
#pragma warning( default:4305 )\r
if( h_query != NULL )\r
al_cancel_sa_req( &h_query->sa_req );\r
\r
- /* Always try to destroy the CEP. The CEP manager handles invalid CIDs. */\r
- al_destroy_cep( qp_get_al( h_qp ), &((al_conn_qp_t*)h_qp)->cid, TRUE );\r
-\r
if( p_ndi_csq->state != NDI_CM_INVALID )\r
p_ndi_csq->state = NDI_CM_IDLE;\r
\r
__fallthrough;\r
\r
case UAL_NDI_NOTIFY_DREQ:\r
- __ndi_complete_irp( h_qp, p_irp, STATUS_CANCELLED );\r
+ case UAL_NDI_GET_REQ_CM:\r
+ __ndi_complete_irp( p_ndi_csq, p_irp, STATUS_CANCELLED );\r
break;\r
\r
case UAL_NDI_DREQ_CM:\r
\r
\r
NTSTATUS\r
-ndi_qp_init(\r
- IN ib_qp_handle_t h_qp )\r
+nd_csq_init(\r
+ IN ib_al_handle_t h_al,\r
+ IN net32_t cid,\r
+ IN uint64_t h_qp,\r
+ OUT nd_csq_t **pp_csq )\r
{\r
-\r
+ nd_csq_t *p_nd_csq;\r
NTSTATUS status;\r
+ ib_api_status_t ib_status;\r
\r
AL_ENTER( AL_DBG_NDI );\r
\r
- if ( h_qp->type != IB_QPT_RELIABLE_CONN )\r
- {\r
- AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,\r
- ("Only RC QP type is supported \n"));\r
- status = STATUS_SUCCESS;\r
- goto exit;\r
- }\r
- \r
- h_qp->p_irp_queue = (ndi_qp_csq_t*)cl_zalloc(sizeof(ndi_qp_csq_t));\r
- if (!h_qp->p_irp_queue)\r
+ p_nd_csq = (nd_csq_t*)cl_zalloc( sizeof(*p_nd_csq) );\r
+ if( p_nd_csq == NULL )\r
{\r
status = STATUS_NO_MEMORY;\r
goto exit;\r
}\r
\r
- status = IoCsqInitializeEx( &h_qp->p_irp_queue->csq, \r
+ KeInitializeSpinLock( &p_nd_csq->lock );\r
+ InitializeListHead( &p_nd_csq->queue );\r
+ p_nd_csq->h_al = h_al;\r
+ p_nd_csq->h_qp = h_qp;\r
+ p_nd_csq->h_query = NULL;\r
+ p_nd_csq->state = NDI_CM_IDLE;\r
+ p_nd_csq->cid = cid;\r
+\r
+ status = IoCsqInitializeEx( &p_nd_csq->csq, \r
__ndi_insert_irp_ex, __ndi_remove_irp,\r
__ndi_peek_next_irp, __ndi_acquire_lock,\r
__ndi_release_lock, __ndi_complete_cancelled_irp );\r
if ( !NT_SUCCESS( status ) )\r
+ {\r
+ cl_free( p_nd_csq );\r
goto exit;\r
+ }\r
\r
- InitializeListHead( &h_qp->p_irp_queue->queue );\r
- h_qp->p_irp_queue->h_qp = h_qp;\r
- h_qp->p_irp_queue->h_query = NULL;\r
- h_qp->p_irp_queue->state = NDI_CM_IDLE;\r
+ /*\r
+ * One reference for the CEP, one for the caller (so that if the CEP\r
+ * gets destroyed we don't blow up.)\r
+ */\r
+ p_nd_csq->ref_cnt = 2;\r
+\r
+ ib_status = kal_cep_config(\r
+ h_al, cid, nd_cm_handler, p_nd_csq, nd_csq_release );\r
+\r
+ if( ib_status != IB_SUCCESS )\r
+ {\r
+ status = STATUS_UNSUCCESSFUL;\r
+ cl_free( p_nd_csq );\r
+ goto exit;\r
+ }\r
+\r
+ *pp_csq = p_nd_csq;\r
status = STATUS_SUCCESS;\r
\r
-AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,\r
- ("Creating h_qp %#I64x, uhdl %#I64x \n", \r
- (uint64_t)(ULONG_PTR)h_qp, h_qp->obj.hdl ) );\r
+ AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,\r
+ ("Creating CSQ %p, uhdl %#I64x \n", p_nd_csq, h_qp) );\r
\r
exit:\r
AL_EXIT( AL_DBG_NDI );\r
return status;\r
}\r
\r
-#pragma warning(disable:4706)\r
+\r
void\r
-ndi_qp_destroy(\r
- IN ib_qp_handle_t h_qp )\r
+ndi_cancel_cm_irps(\r
+ IN nd_csq_t *p_nd_csq )\r
{\r
- KIRQL irql;\r
PIRP Irp;\r
\r
- AL_ENTER( AL_DBG_NDI );\r
+ AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI,\r
+ ("[ CSQ %p (CID = %d)\n", \r
+ p_nd_csq, p_nd_csq->cid ) );\r
\r
- if (h_qp->type == IB_QPT_RELIABLE_CONN && h_qp->p_irp_queue)\r
+ /* cancel pending IRPS for NDI type CQ */\r
+ AL_ENTER( AL_DBG_NDI );\r
+ for( Irp = IoCsqRemoveNextIrp( &p_nd_csq->csq, NULL );\r
+ Irp != NULL;\r
+ Irp = IoCsqRemoveNextIrp( &p_nd_csq->csq, NULL ) )\r
{\r
- AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,\r
- ("Destroying h_qp %#I64x, uhdl %#I64x, cid %d\n", \r
- (uint64_t)(ULONG_PTR)h_qp, h_qp->obj.hdl, ((al_conn_qp_t*)h_qp)->cid ) );\r
+ __ndi_complete_cancelled_irp( &p_nd_csq->csq, Irp );\r
+ }\r
+ for( Irp = IoCsqRemoveNextIrp( &p_nd_csq->csq, (VOID*)(ULONG_PTR)UAL_NDI_NOTIFY_DREQ );\r
+ Irp != NULL;\r
+ Irp = IoCsqRemoveNextIrp( &p_nd_csq->csq, (VOID*)(ULONG_PTR)UAL_NDI_NOTIFY_DREQ ) )\r
+ {\r
+ __ndi_complete_cancelled_irp( &p_nd_csq->csq, Irp );\r
+ }\r
\r
- /* Move the state before flushing, so that all new IRPs fail to queue. */\r
- __ndi_acquire_lock( &h_qp->p_irp_queue->csq, &irql );\r
- h_qp->p_irp_queue->state = NDI_CM_INVALID;\r
- __ndi_release_lock( &h_qp->p_irp_queue->csq, irql );\r
+ AL_EXIT( AL_DBG_NDI );\r
+}\r
\r
- /* cancel pending IRPS for NDI type CQ */\r
- AL_ENTER( AL_DBG_NDI );\r
- while( Irp = IoCsqRemoveNextIrp( &h_qp->p_irp_queue->csq, NULL ) )\r
- {\r
- AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI, \r
- ("h_qp %#I64x, uhdl %#I64x, ref_cnt %d\n", \r
- (uint64_t)(ULONG_PTR)h_qp, h_qp->obj.hdl, h_qp->obj.ref_cnt ) );\r
\r
- __ndi_complete_cancelled_irp( &h_qp->p_irp_queue->csq, Irp );\r
- }\r
- while( Irp = IoCsqRemoveNextIrp(\r
- &h_qp->p_irp_queue->csq, (VOID*)(ULONG_PTR)UAL_NDI_NOTIFY_DREQ ) )\r
- {\r
- AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI, \r
- ("h_qp %#I64x, uhdl %#I64x, ref_cnt %d\n", \r
- (uint64_t)(ULONG_PTR)h_qp, h_qp->obj.hdl, h_qp->obj.ref_cnt ) );\r
+void\r
+nd_csq_destroy(\r
+ IN nd_csq_t *p_nd_csq )\r
+{\r
+ KIRQL irql;\r
\r
- __ndi_complete_cancelled_irp( &h_qp->p_irp_queue->csq, Irp );\r
- }\r
- AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI, \r
- ("h_qp %#I64x, uhdl %#I64x, ref_cnt %d\n", \r
- (uint64_t)(ULONG_PTR)h_qp, h_qp->obj.hdl, h_qp->obj.ref_cnt ) );\r
- }\r
+ AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI,\r
+ ("[ CSQ %p (CID = %d)\n", \r
+ p_nd_csq, p_nd_csq->cid ) );\r
+\r
+ /* Move the state before flushing, so that all new IRPs fail to queue. */\r
+ __ndi_acquire_lock( &p_nd_csq->csq, &irql );\r
+ p_nd_csq->state = NDI_CM_INVALID;\r
+ __ndi_release_lock( &p_nd_csq->csq, irql );\r
+\r
+ /* cancel pending IRPS */\r
+ ndi_cancel_cm_irps( p_nd_csq );\r
+\r
+ cl_free( p_nd_csq );\r
\r
AL_EXIT( AL_DBG_NDI );\r
}\r
-#pragma warning(default:4706)\r
\r
\r
void\r
-ndi_qp_free(\r
- IN ib_qp_handle_t h_qp )\r
+nd_csq_ref( nd_csq_t* p_csq )\r
{\r
- AL_ENTER( AL_DBG_NDI );\r
+ InterlockedIncrement( &p_csq->ref_cnt );\r
+}\r
\r
- if (h_qp->type == IB_QPT_RELIABLE_CONN && h_qp->p_irp_queue)\r
+\r
+void\r
+nd_csq_release( nd_csq_t* p_csq )\r
+{\r
+ if( InterlockedDecrement( &p_csq->ref_cnt ) == 0 )\r
{\r
- /* free NDI context */\r
- cl_free( h_qp->p_irp_queue );\r
- h_qp->p_irp_queue = NULL;\r
+ nd_csq_destroy( p_csq );\r
}\r
-\r
- AL_EXIT( AL_DBG_NDI );\r
}\r
\r
\r
static inline void\r
-__ndi_complete_req_irp(\r
- IN ib_qp_handle_t h_qp,\r
- IN NTSTATUS code\r
- )\r
+__ndi_timeout_req_irp(\r
+ __in nd_csq_t* p_csq )\r
{\r
PIRP Irp;\r
KIRQL irql;\r
\r
AL_ENTER( AL_DBG_NDI );\r
- Irp = IoCsqRemoveNextIrp( &h_qp->p_irp_queue->csq, (VOID*)(ULONG_PTR)UAL_NDI_REQ_CM );\r
- if ( Irp )\r
+ Irp = IoCsqRemoveNextIrp( &p_csq->csq, (VOID*)(ULONG_PTR)UAL_NDI_REQ_CM );\r
+ if( Irp )\r
{\r
- __ndi_acquire_lock( &h_qp->p_irp_queue->csq, &irql );\r
- if( h_qp->p_irp_queue->state != NDI_CM_INVALID )\r
- h_qp->p_irp_queue->state = NDI_CM_IDLE;\r
- __ndi_release_lock( &h_qp->p_irp_queue->csq, irql );\r
- __ndi_complete_irp( h_qp, Irp, code );\r
+ __ndi_acquire_lock( &p_csq->csq, &irql );\r
+ if( p_csq->state != NDI_CM_INVALID )\r
+ p_csq->state = NDI_CM_IDLE;\r
+ __ndi_release_lock( &p_csq->csq, irql );\r
+ __ndi_complete_irp( p_csq, Irp, STATUS_TIMEOUT );\r
}\r
- al_destroy_cep( qp_get_al( h_qp ), &((al_conn_qp_t*)h_qp)->cid, TRUE );\r
AL_EXIT( AL_DBG_NDI );\r
}\r
\r
\r
static void\r
__ndi_notify_dreq(\r
- IN ib_qp_handle_t const h_qp )\r
+ __in nd_csq_t* p_csq )\r
{\r
- IRP *p_irp = IoCsqRemoveNextIrp(\r
- &h_qp->p_irp_queue->csq, (VOID*)(ULONG_PTR)UAL_NDI_NOTIFY_DREQ );\r
-\r
- if( p_irp )\r
+ IRP *p_irp;\r
+ do\r
{\r
- __ndi_complete_irp( h_qp, p_irp, STATUS_SUCCESS );\r
- }\r
+ p_irp = IoCsqRemoveNextIrp(\r
+ &p_csq->csq, (VOID*)(ULONG_PTR)UAL_NDI_NOTIFY_DREQ );\r
+\r
+ if( p_irp )\r
+ {\r
+ __ndi_complete_irp( p_csq, p_irp, STATUS_SUCCESS );\r
+ }\r
+\r
+ } while ( p_irp );\r
}\r
\r
\r
static void\r
__ndi_proc_dreq(\r
- IN ib_qp_handle_t const h_qp )\r
+ IN nd_csq_t *p_csq)\r
{\r
IRP *p_irp;\r
KIRQL irql;\r
- ndi_cm_state_t old_state;\r
\r
- __ndi_notify_dreq( h_qp );\r
+ __ndi_notify_dreq( p_csq );\r
\r
- __ndi_acquire_lock( &h_qp->p_irp_queue->csq, &irql );\r
- old_state = h_qp->p_irp_queue->state;\r
- if( old_state == NDI_CM_CONNECTED )\r
+ __ndi_acquire_lock( &p_csq->csq, &irql );\r
+ if( p_csq->state == NDI_CM_CONNECTED )\r
{\r
- h_qp->p_irp_queue->state = NDI_CM_CONNECTED_DREQ_RCVD;\r
+ p_csq->state = NDI_CM_CONNECTED_DREQ_RCVD;\r
}\r
- __ndi_release_lock( &h_qp->p_irp_queue->csq, irql );\r
+ __ndi_release_lock( &p_csq->csq, irql );\r
\r
p_irp = IoCsqRemoveNextIrp(\r
- &h_qp->p_irp_queue->csq, (VOID*)(ULONG_PTR)UAL_NDI_DREQ_CM );\r
+ &p_csq->csq, (VOID*)(ULONG_PTR)UAL_NDI_DREQ_CM );\r
if( p_irp != NULL )\r
{\r
__ndi_queue_drep( p_irp );\r
*/\r
static void\r
__ndi_proc_rej(\r
- IN ib_qp_handle_t const h_qp,\r
+ IN nd_csq_t* p_csq,\r
IN const mad_cm_rej_t* const p_rej )\r
{\r
KIRQL irql;\r
AL_ENTER( AL_DBG_NDI );\r
\r
AL_PRINT(TRACE_LEVEL_ERROR, AL_DBG_ERROR, \r
- ("p_rej %p, h_qp %#I64x, uhdl %#I64x, connect reject, reason=%hd\n", \r
- p_rej, (uint64_t)(ULONG_PTR)h_qp, h_qp->obj.hdl, cl_ntoh16(p_rej->reason) ) );\r
+ ("p_rej %p, CID=%d, uhdl %#I64x, connect reject, reason=%hd\n", \r
+ p_rej, p_csq->cid, p_csq->h_qp, cl_ntoh16(p_rej->reason) ) );\r
\r
- p_irp = IoCsqRemoveNextIrp( &h_qp->p_irp_queue->csq, NULL );\r
- __ndi_notify_dreq( h_qp );\r
- __ndi_acquire_lock( &h_qp->p_irp_queue->csq, &irql );\r
+ p_irp = IoCsqRemoveNextIrp( &p_csq->csq, NULL );\r
+ __ndi_notify_dreq( p_csq );\r
+ __ndi_acquire_lock( &p_csq->csq, &irql );\r
if( p_irp != NULL )\r
{\r
switch( cl_ioctl_ctl_code( p_irp ) )\r
{\r
case UAL_NDI_REQ_CM:\r
- if( h_qp->p_irp_queue->state != NDI_CM_INVALID )\r
- h_qp->p_irp_queue->state = NDI_CM_IDLE;\r
- if( p_rej->reason == IB_REJ_TIMEOUT )\r
- __ndi_complete_irp( h_qp, p_irp, STATUS_TIMEOUT );\r
+ if( p_csq->state != NDI_CM_INVALID )\r
+ p_csq->state = NDI_CM_IDLE;\r
+ if( p_rej->reason == IB_REJ_USER_DEFINED )\r
+ __ndi_complete_irp( p_csq, p_irp, STATUS_CONNECTION_REFUSED );\r
else\r
- __ndi_complete_irp( h_qp, p_irp, STATUS_CONNECTION_REFUSED );\r
+ __ndi_complete_irp( p_csq, p_irp, STATUS_TIMEOUT );\r
\r
- al_destroy_cep(\r
- qp_get_al( h_qp ), &((al_conn_qp_t*)h_qp)->cid, TRUE );\r
+ /* We leave the CEP active so that the private data can be retrieved. */\r
break;\r
\r
case UAL_NDI_DREQ_CM:\r
__ndi_queue_drep( p_irp );\r
break;\r
+\r
+ case UAL_NDI_NOTIFY_DREQ:\r
+ __ndi_complete_irp( p_csq, p_irp, STATUS_CONNECTION_ABORTED );\r
+ break;\r
+\r
+ default:\r
+ ASSERT( cl_ioctl_ctl_code( p_irp ) == UAL_NDI_REQ_CM ||\r
+ cl_ioctl_ctl_code( p_irp ) == UAL_NDI_DREQ_CM ||\r
+ cl_ioctl_ctl_code( p_irp ) == UAL_NDI_NOTIFY_DREQ );\r
}\r
}\r
- else if( h_qp->p_irp_queue->state == NDI_CM_CONNECTED )\r
+ else if( p_csq->state == NDI_CM_CONNECTED || p_csq->state == NDI_CM_CONNECTING_REQ_RCVD )\r
{\r
- if( h_qp->p_irp_queue->state != NDI_CM_INVALID )\r
- h_qp->p_irp_queue->state = NDI_CM_CONNECTED_DREQ_RCVD;\r
+ p_csq->state = NDI_CM_CONNECTED_DREQ_RCVD;\r
}\r
- __ndi_release_lock( &h_qp->p_irp_queue->csq, irql );\r
+ __ndi_release_lock( &p_csq->csq, irql );\r
\r
AL_EXIT( AL_DBG_NDI );\r
}\r
\r
\r
+static void\r
+__ndi_proc_req(\r
+ IN nd_csq_t* p_csq,\r
+ IN net32_t new_cid,\r
+ IN ib_mad_element_t *p_mad )\r
+{\r
+ IRP* p_irp;\r
+ KIRQL irql;\r
+ NTSTATUS status;\r
+ nd_csq_t* p_new_csq;\r
+\r
+ AL_ENTER( AL_DBG_NDI );\r
+\r
+ AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI ,("CID = %d\n", p_csq->cid));\r
+\r
+ status = nd_csq_init( p_csq->h_al, new_cid, 0, &p_new_csq );\r
+ if( status != STATUS_SUCCESS )\r
+ {\r
+ // Ignore the request.\r
+ kal_cep_destroy( p_csq->h_al, new_cid, STATUS_NO_MORE_ENTRIES );\r
+ ib_put_mad( p_mad );\r
+ return;\r
+ }\r
+\r
+ __ndi_acquire_lock( &p_new_csq->csq, &irql );\r
+ p_new_csq->state = NDI_CM_CONNECTING_REQ_RCVD;\r
+ __ndi_release_lock( &p_new_csq->csq, irql );\r
+ nd_csq_release( p_new_csq );\r
+\r
+ p_irp = IoCsqRemoveNextIrp( &p_csq->csq, (VOID*)(ULONG_PTR)UAL_NDI_GET_REQ_CM );\r
+ if( p_irp == NULL )\r
+ {\r
+ p_mad->send_context1 = (VOID*)(ULONG_PTR)new_cid;\r
+ __ndi_acquire_lock( &p_csq->csq, &irql );\r
+ if( p_csq->p_mad_head == NULL )\r
+ {\r
+ p_csq->p_mad_head = p_mad;\r
+ }\r
+ else\r
+ {\r
+ p_csq->p_mad_tail->p_next = p_mad;\r
+ }\r
+ p_csq->p_mad_tail = p_mad;\r
+ __ndi_release_lock( &p_csq->csq, irql );\r
+ }\r
+ else\r
+ {\r
+ *(net32_t*)cl_ioctl_out_buf( p_irp ) = new_cid;\r
+ __ndi_complete_irp( p_csq, p_irp, STATUS_SUCCESS );\r
+ ib_put_mad( p_mad );\r
+ }\r
+\r
+ AL_EXIT( AL_DBG_NDI );\r
+ return;\r
+}\r
+\r
+\r
static void\r
__ndi_proc_rep(\r
- IN ib_qp_handle_t const h_qp,\r
- IN net32_t cid )\r
+ IN nd_csq_t* p_csq )\r
{\r
- ndi_qp_csq_t *p_ndi_csq = h_qp->p_irp_queue;\r
IRP* p_irp;\r
KIRQL irql;\r
\r
AL_ENTER( AL_DBG_NDI );\r
\r
- AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI ,("h_qp = 0x%p\n", h_qp));\r
+ AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI ,("CID = %d\n", p_csq->cid));\r
\r
- p_irp = IoCsqRemoveNextIrp( &h_qp->p_irp_queue->csq, (VOID*)(ULONG_PTR)UAL_NDI_REQ_CM );\r
- __ndi_acquire_lock( &p_ndi_csq->csq, &irql );\r
+ p_irp = IoCsqRemoveNextIrp( &p_csq->csq, (VOID*)(ULONG_PTR)UAL_NDI_REQ_CM );\r
+ __ndi_acquire_lock( &p_csq->csq, &irql );\r
if( p_irp == NULL )\r
{\r
AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, \r
- ("Not the expected state %s\n", State2String( p_ndi_csq->state )));\r
- CL_ASSERT( IsListEmpty( &h_qp->p_irp_queue->queue ) );\r
- al_cep_rej( qp_get_al( h_qp ), cid, IB_REJ_INVALID_COMM_INSTANCE, NULL, 0, NULL, 0 );\r
+ ("Not the expected state %s\n", State2String( p_csq->state )));\r
+ CL_ASSERT( IsListEmpty( &p_csq->queue ) );\r
+ al_cep_rej( p_csq->h_al, p_csq->cid, IB_REJ_INVALID_COMM_INSTANCE, NULL, 0, NULL, 0 );\r
}\r
else\r
{\r
- p_ndi_csq->state = NDI_CM_CONNECTING_REP_RCVD;\r
+ p_csq->state = NDI_CM_CONNECTING_REP_RCVD;\r
\r
- __ndi_complete_irp( h_qp, p_irp, STATUS_SUCCESS );\r
+ __ndi_complete_irp( p_csq, p_irp, STATUS_SUCCESS );\r
}\r
- __ndi_release_lock( &p_ndi_csq->csq, irql );\r
+ __ndi_release_lock( &p_csq->csq, irql );\r
\r
AL_EXIT( AL_DBG_NDI );\r
return;\r
IN DEVICE_OBJECT* p_dev_obj,\r
IN PIRP p_irp )\r
{\r
- ib_qp_handle_t h_qp = p_irp->Tail.Overlay.DriverContext[0];\r
+ nd_csq_t* p_csq = p_irp->Tail.Overlay.DriverContext[0];\r
+ ib_qp_handle_t h_qp;\r
ib_qp_mod_t qp_mod;\r
ib_api_status_t status;\r
uint64_t timewait_us;\r
CL_ASSERT( p_irp->Tail.Overlay.DriverContext[1] );\r
IoFreeWorkItem( p_irp->Tail.Overlay.DriverContext[1] );\r
p_irp->Tail.Overlay.DriverContext[1] = NULL;\r
- deref_al_obj( &h_qp->obj ); /* Release work item reference. */\r
-\r
- status = al_cep_get_timewait( qp_get_al( h_qp ), \r
- ((al_conn_qp_t*)h_qp)->cid, &timewait_us );\r
\r
+ status = al_cep_get_timewait( p_csq->h_al, p_csq->cid, &timewait_us );\r
if (status != IB_SUCCESS)\r
{\r
nt_status = STATUS_CONNECTION_INVALID;\r
}\r
\r
/* Store the timestamp after which the QP exits timewait. */\r
- h_qp->timewait = cl_get_time_stamp() + timewait_us;\r
+ h_qp = CONTAINING_RECORD(\r
+ al_hdl_ref( p_csq->h_al, p_csq->h_qp, AL_OBJ_TYPE_H_QP ),\r
+ ib_qp_t,\r
+ obj );\r
+ if( h_qp != NULL )\r
+ {\r
+ h_qp->timewait = cl_get_time_stamp() + timewait_us;\r
+ }\r
\r
- al_destroy_cep( qp_get_al( h_qp ), &((al_conn_qp_t*)h_qp)->cid, TRUE );\r
+ /* Send the DREP. */\r
+ al_cep_drep( p_csq->h_al, p_csq->cid, NULL, 0 );\r
\r
/* bring QP to error state */\r
- cl_memclr( &qp_mod, sizeof(qp_mod) );\r
- qp_mod.req_state = IB_QPS_ERROR;\r
- \r
- status = ndi_modify_qp( h_qp, &qp_mod, \r
- cl_ioctl_out_size( p_irp ), cl_ioctl_out_buf( p_irp ) );\r
- if ( status != IB_SUCCESS )\r
+ if( h_qp != NULL )\r
{\r
- AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
- ("ndi_modify_qp to ERROR returned %s.\n", ib_get_err_str(status) ) );\r
+ cl_memclr( &qp_mod, sizeof(qp_mod) );\r
+ qp_mod.req_state = IB_QPS_ERROR;\r
+ \r
+ status = ndi_modify_qp( h_qp, &qp_mod, \r
+ cl_ioctl_out_size( p_irp ), cl_ioctl_out_buf( p_irp ) );\r
+ if ( status != IB_SUCCESS )\r
+ {\r
+ AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
+ ("ndi_modify_qp to ERROR returned %s.\n", ib_get_err_str(status) ) );\r
+ }\r
+ deref_al_obj( &h_qp->obj );\r
}\r
\r
nt_status = ib_to_ntstatus( status );\r
\r
exit:\r
- __ndi_acquire_lock( &h_qp->p_irp_queue->csq, &irql );\r
- if( h_qp->p_irp_queue->state != NDI_CM_INVALID )\r
- h_qp->p_irp_queue->state = NDI_CM_IDLE;\r
- __ndi_release_lock( &h_qp->p_irp_queue->csq, irql );\r
+ __ndi_acquire_lock( &p_csq->csq, &irql );\r
+ if( p_csq->state != NDI_CM_INVALID )\r
+ p_csq->state = NDI_CM_IDLE;\r
+ __ndi_release_lock( &p_csq->csq, irql );\r
\r
- __ndi_complete_irp( h_qp, p_irp, nt_status );\r
+ __ndi_complete_irp( p_csq, p_irp, nt_status );\r
+ nd_csq_release( p_csq ); /* Release work item reference. */\r
AL_EXIT( AL_DBG_NDI );\r
}\r
\r
\r
static void\r
__ndi_proc_drep(\r
- IN ib_qp_handle_t const h_qp )\r
+ IN nd_csq_t* p_csq )\r
{\r
IRP* p_irp;\r
\r
AL_ENTER( AL_DBG_NDI );\r
\r
p_irp = IoCsqRemoveNextIrp(\r
- &h_qp->p_irp_queue->csq, (VOID*)(ULONG_PTR)UAL_NDI_DREQ_CM );\r
+ &p_csq->csq, (VOID*)(ULONG_PTR)UAL_NDI_DREQ_CM );\r
if( p_irp != NULL )\r
{\r
+ CL_ASSERT( p_irp->Tail.Overlay.DriverContext[0] == p_csq );\r
__ndi_queue_drep( p_irp );\r
}\r
\r
}\r
\r
\r
-static void\r
-__ndi_cm_handler(\r
+void\r
+nd_cm_handler(\r
IN const ib_al_handle_t h_al,\r
IN const net32_t cid )\r
{\r
\r
while( al_cep_poll( h_al, cid, &context, &new_cid, &p_mad_el ) == IB_SUCCESS )\r
{\r
- ib_mad_t*p_mad = ib_get_mad_buf( p_mad_el );\r
- ib_qp_handle_t h_qp = (ib_qp_handle_t)context;\r
+ ib_mad_t* p_mad = ib_get_mad_buf( p_mad_el );\r
+ nd_csq_t* p_csq = (nd_csq_t*)context;\r
+\r
+ CL_ASSERT( p_csq != NULL );\r
+ CL_ASSERT( p_csq->cid == cid );\r
\r
if( p_mad_el->status != IB_SUCCESS )\r
{\r
{\r
case CM_REQ_ATTR_ID:\r
AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,\r
- ("REQ timeouted for CEP with cid %d, h_al %p, context %p, new_cid %d .\n", \r
- cid, h_al, h_qp, new_cid ) );\r
- __ndi_complete_req_irp( h_qp, STATUS_TIMEOUT );\r
+ ("REQ timed out for CEP with cid %d, h_al %p, context %p.\n", \r
+ cid, h_al, p_csq ) );\r
+ __ndi_timeout_req_irp( p_csq );\r
break;\r
\r
case CM_REP_ATTR_ID:\r
AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,\r
- ("REP timeouted for CEP with cid %d, h_al %p, context %p, new_cid %d .\n", \r
- cid, h_al, h_qp, new_cid ) );\r
+ ("REP timed out for CEP with cid %d, h_al %p, context %p.\n", \r
+ cid, h_al, p_csq ) );\r
break;\r
\r
case CM_DREQ_ATTR_ID:\r
AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,\r
- ("DREQ timeouted for CEP with cid %d, h_al %p, context %p, new_cid %d .\n", \r
- cid, h_al, h_qp, new_cid ) );\r
- __ndi_proc_drep( h_qp );\r
+ ("DREQ timed out for CEP with cid %d, h_al %p, context %p.\n", \r
+ cid, h_al, p_csq ) );\r
+ __ndi_proc_drep( p_csq );\r
break;\r
\r
default:\r
AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
("Unhandled failed MAD attr ID %d for CEP with cid %d, h_al %p, context %p, new_cid %d .\n", \r
- p_mad->attr_id, cid, h_al, h_qp, new_cid ) );\r
+ p_mad->attr_id, cid, h_al, p_csq, new_cid ) );\r
break;\r
}\r
}\r
{\r
switch( p_mad->attr_id )\r
{\r
+ case CM_REQ_ATTR_ID:\r
+ AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,\r
+ ("REQ received for CEP with cid %d, h_al %p, context %p.\n", \r
+ cid, h_al, p_csq ) );\r
+ __ndi_proc_req( p_csq, new_cid, p_mad_el );\r
+ continue;\r
+\r
case CM_REP_ATTR_ID:\r
AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,\r
- ("REP received for CEP with cid %d, h_al %p, context %p, new_cid %d .\n", \r
- cid, h_al, h_qp, new_cid ) );\r
- CL_ASSERT( ((al_conn_qp_t*)h_qp)->cid == (int32_t)cid || \r
- ((al_conn_qp_t*)h_qp)->cid == AL_INVALID_CID ||\r
- ((al_conn_qp_t*)h_qp)->cid == AL_RESERVED_CID );\r
- __ndi_proc_rep( h_qp, cid );\r
+ ("REP received for CEP with cid %d, h_al %p, context %p.\n", \r
+ cid, h_al, p_csq ) );\r
+ __ndi_proc_rep( p_csq );\r
break;\r
\r
case CM_REJ_ATTR_ID:\r
AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,\r
- ("REJ received for CEP with cid %d, h_al %p, context %p, new_cid %d .\n", \r
- cid, h_al, h_qp, new_cid ) );\r
- __ndi_proc_rej( h_qp, (mad_cm_rej_t*)p_mad );\r
+ ("REJ received for CEP with cid %d, h_al %p, context %p.\n", \r
+ cid, h_al, p_csq ) );\r
+ __ndi_proc_rej( p_csq, (mad_cm_rej_t*)p_mad );\r
break;\r
\r
case CM_DREQ_ATTR_ID:\r
AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,\r
- ("DREQ received for CEP with cid %d, h_al %p, context %p, new_cid %d .\n", \r
- cid, h_al, h_qp, new_cid ) );\r
- CL_ASSERT( ((al_conn_qp_t*)h_qp)->cid == (int32_t)cid || \r
- ((al_conn_qp_t*)h_qp)->cid == AL_INVALID_CID ||\r
- ((al_conn_qp_t*)h_qp)->cid == AL_RESERVED_CID );\r
- __ndi_proc_dreq( h_qp );\r
+ ("DREQ received for CEP with cid %d, h_al %p, context %p.\n", \r
+ cid, h_al, p_csq ) );\r
+ __ndi_proc_dreq( p_csq );\r
break;\r
\r
case CM_DREP_ATTR_ID:\r
AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,\r
- ("DREP received for CEP with cid %d, h_al %p, context %p, new_cid %d .\n", \r
- cid, h_al, h_qp, new_cid ) );\r
- __ndi_proc_drep( h_qp );\r
+ ("DREP received for CEP with cid %d, h_al %p, context %p.\n", \r
+ cid, h_al, p_csq ) );\r
+ __ndi_proc_drep( p_csq );\r
break;\r
\r
case CM_RTU_ATTR_ID:\r
AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,\r
- ("RTU received for CEP with cid %d, h_al %p, context %p, new_cid %d.\n",\r
- cid, h_al, h_qp, new_cid ) );\r
+ ("RTU received for CEP with cid %d, h_al %p, context %p.\n",\r
+ cid, h_al, p_csq ) );\r
break;\r
\r
default:\r
AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
("Unhandled MAD attr ID %d for CEP with cid %d, h_al %p, context %p, new_cid %d .\n", \r
- p_mad->attr_id, cid, h_al, h_qp, new_cid ) );\r
+ p_mad->attr_id, cid, h_al, p_csq, new_cid ) );\r
}\r
}\r
\r
\r
static void\r
__ndi_fill_cm_req(\r
- IN ib_qp_handle_t const h_qp,\r
+ IN net32_t qpn,\r
IN ual_ndi_req_cm_ioctl_in_t *p_req,\r
IN ib_path_rec_t *p_path_rec,\r
- OUT ib_cm_req_t *p_cm_req)\r
+ OUT iba_cm_req *p_cm_req)\r
{\r
AL_ENTER( AL_DBG_NDI );\r
\r
- memset( p_cm_req, 0, sizeof(ib_cm_req_t) );\r
+ memset( p_cm_req, 0, sizeof(*p_cm_req) );\r
\r
- p_cm_req->svc_id = IB_REQ_CM_RDMA_SID_PREFIX | (p_req->prot << 16) | p_req->dst_port;\r
- p_cm_req->max_cm_retries = g_max_cm_retries;\r
- p_cm_req->p_primary_path = p_path_rec; \r
-\r
- p_cm_req->p_req_pdata = (uint8_t *)&p_req->pdata;\r
- p_cm_req->req_length = sizeof(p_req->pdata);\r
+ p_cm_req->service_id = IB_REQ_CM_RDMA_SID_PREFIX | (p_req->prot << 16) | p_req->dst_port;\r
+ p_cm_req->p_primary_path = p_path_rec;\r
\r
+ p_cm_req->qpn = qpn;\r
p_cm_req->qp_type = IB_QPT_RELIABLE_CONN;\r
- p_cm_req->h_qp = h_qp;\r
+ p_cm_req->starting_psn = qpn;\r
+\r
+ p_cm_req->p_pdata = (uint8_t *)&p_req->pdata;\r
+ p_cm_req->pdata_len = sizeof(p_req->pdata);\r
+\r
+ p_cm_req->max_cm_retries = g_max_cm_retries;\r
p_cm_req->resp_res = p_req->resp_res;\r
p_cm_req->init_depth = p_req->init_depth;\r
\r
else if( p_cm_req->local_resp_timeout < CM_MIN_LOCAL_TIMEOUT )\r
p_cm_req->local_resp_timeout = CM_MIN_LOCAL_TIMEOUT;\r
\r
- p_cm_req->rnr_nak_timeout = QP_ATTRIB_RNR_NAK_TIMEOUT;\r
p_cm_req->rnr_retry_cnt = QP_ATTRIB_RNR_RETRY;\r
p_cm_req->retry_cnt = g_qp_retries;\r
- p_cm_req->p_alt_path = NULL;\r
\r
AL_EXIT( AL_DBG_NDI );\r
}\r
)\r
{\r
ib_api_status_t status;\r
- ib_qp_handle_t h_qp = (ib_qp_handle_t)p_irp->Tail.Overlay.DriverContext[0];\r
+ nd_csq_t* p_csq = (nd_csq_t*)p_irp->Tail.Overlay.DriverContext[0];\r
ib_path_rec_t *p_path_rec = p_irp->Tail.Overlay.DriverContext[1];\r
ual_ndi_req_cm_ioctl_in_t *p_req = \r
(ual_ndi_req_cm_ioctl_in_t*)cl_ioctl_in_buf( p_irp );\r
NTSTATUS nt_status;\r
- ib_cm_req_t cm_req;\r
- ib_qp_mod_t qp_mod;\r
- al_conn_qp_t *p_qp;\r
+ ib_qp_handle_t h_qp;\r
+ iba_cm_req cm_req;\r
\r
- AL_ENTER( AL_DBG_NDI );\r
+ AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI,\r
+ ("[ CID = %d, h_al %p, context %p\n",\r
+ p_req->cid, p_csq->h_al, p_csq) );\r
\r
p_irp->Tail.Overlay.DriverContext[1] = NULL;\r
\r
- if( h_qp->p_irp_queue->state != NDI_CM_CONNECTING_QPR_SENT &&\r
- h_qp->p_irp_queue->state != NDI_CM_IDLE )\r
+ if( p_csq->state != NDI_CM_CONNECTING_QPR_SENT &&\r
+ p_csq->state != NDI_CM_IDLE )\r
{\r
AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
- ("Unexpected state: %d\n", h_qp->p_irp_queue->state) );\r
+ ("Unexpected state: %d\n", p_csq->state) );\r
return STATUS_CONNECTION_ACTIVE;\r
}\r
\r
- /* Get a CEP and bind it to the QP. */\r
- p_qp = (al_conn_qp_t*)h_qp;\r
- cl_spinlock_acquire( &h_qp->obj.lock );\r
- if( h_qp->obj.state != CL_DESTROYING && p_qp->cid == AL_INVALID_CID )\r
+ h_qp = CONTAINING_RECORD(\r
+ al_hdl_ref( p_csq->h_al, p_req->h_qp, AL_OBJ_TYPE_H_QP ),\r
+ ib_qp_t,\r
+ obj );\r
+ if( !h_qp )\r
{\r
- status = al_create_cep( qp_get_al( h_qp ), __ndi_cm_handler,\r
- &h_qp->obj, deref_al_obj, &p_qp->cid );\r
- }\r
- else \r
- {\r
- status = IB_RESOURCE_BUSY;\r
- }\r
- cl_spinlock_release( &h_qp->obj.lock );\r
- if( status != IB_SUCCESS )\r
- {\r
- h_qp->p_irp_queue->state = NDI_CM_IDLE;\r
+ /* The QP was valid when the IOCTL first came in... */\r
AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
- ("al_create_cep returned %s.\n", ib_get_err_str( status )) );\r
- return ib_to_ntstatus( status );\r
+ ("Invalid QP: %I64d\n", p_req->h_qp) );\r
+ return STATUS_CONNECTION_ABORTED;\r
}\r
- AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,\r
- ("Created Active CEP with cid %d, h_al %p, context %p\n",\r
- p_qp->cid, qp_get_al( h_qp ), h_qp ) );\r
-\r
- ref_al_obj( &h_qp->obj ); /* Take CEP reference. */\r
\r
/* Format ib_cm_req_t structure */\r
- __ndi_fill_cm_req( h_qp, p_req, p_path_rec, &cm_req );\r
+ __ndi_fill_cm_req( h_qp->num, p_req, p_path_rec, &cm_req );\r
+ deref_al_obj( &h_qp->obj );\r
\r
/* prepare CEP for connection */\r
- status = al_cep_pre_req( qp_get_al( h_qp ), p_qp->cid, &cm_req, &qp_mod );\r
+ status = kal_cep_pre_req(\r
+ p_csq->h_al, p_csq->cid, &cm_req, QP_ATTRIB_RNR_NAK_TIMEOUT, NULL );\r
if( status != STATUS_SUCCESS )\r
{\r
AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
}\r
\r
/* send CM REQ */\r
- status = al_cep_send_req( qp_get_al( h_qp ), p_qp->cid );\r
+ status = al_cep_send_req( p_csq->h_al, p_csq->cid );\r
if( status != IB_SUCCESS )\r
{\r
AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
\r
/* SUCCESS ! */\r
AL_EXIT( AL_DBG_NDI );\r
- return STATUS_SUCCESS;\r
+ return STATUS_PENDING;\r
\r
error:\r
- al_destroy_cep( qp_get_al( h_qp ), &p_qp->cid, TRUE );\r
- \r
switch( status )\r
{\r
case IB_INVALID_HANDLE:\r
nt_status = ib_to_ntstatus( status );\r
}\r
\r
- h_qp->p_irp_queue->state = NDI_CM_IDLE;\r
+ p_csq->state = NDI_CM_IDLE;\r
AL_EXIT( AL_DBG_NDI );\r
return nt_status;\r
}\r
cl_ioctl_handle_t p_irp;\r
uint8_t pkt_life;\r
ib_path_rec_t *p_path_rec;\r
- ib_qp_handle_t h_qp = (ib_qp_handle_t)p_query_rec->query_context;\r
+ nd_csq_t* p_csq = (nd_csq_t*)p_query_rec->query_context;\r
NTSTATUS status;\r
KIRQL irql;\r
\r
("status is %d, count is %d, context %p\n", p_query_rec->status,\r
p_query_rec->result_cnt, p_query_rec->query_context) );\r
\r
- p_irp = IoCsqRemoveNextIrp( &h_qp->p_irp_queue->csq, (VOID*)(ULONG_PTR)UAL_NDI_REQ_CM );\r
+ p_irp = IoCsqRemoveNextIrp( &p_csq->csq, (VOID*)(ULONG_PTR)UAL_NDI_REQ_CM );\r
if( p_irp == NULL )\r
{\r
goto exit;\r
}\r
\r
#pragma warning( disable:4305 )\r
- InterlockedExchangePointer( &h_qp->p_irp_queue->h_query, NULL );\r
+ InterlockedExchangePointer( &p_csq->h_query, NULL );\r
#pragma warning( default:4305 )\r
\r
if( p_query_rec->status != IB_SUCCESS || p_query_rec->result_cnt == 0 )\r
{\r
- __ndi_acquire_lock( &h_qp->p_irp_queue->csq, &irql );\r
- if( h_qp->p_irp_queue->state != NDI_CM_INVALID )\r
- h_qp->p_irp_queue->state = NDI_CM_IDLE;\r
- __ndi_release_lock( &h_qp->p_irp_queue->csq, irql );\r
+ __ndi_acquire_lock( &p_csq->csq, &irql );\r
+ if( p_csq->state != NDI_CM_INVALID )\r
+ p_csq->state = NDI_CM_IDLE;\r
+ __ndi_release_lock( &p_csq->csq, irql );\r
switch( p_query_rec->status )\r
{\r
case IB_TIMEOUT:\r
status = STATUS_HOST_UNREACHABLE;\r
break;\r
}\r
- __ndi_complete_irp( h_qp, p_irp, status );\r
+ __ndi_complete_irp( p_csq, p_irp, status );\r
goto exit;\r
}\r
\r
p_irp->Tail.Overlay.DriverContext[1] = p_path_rec;\r
\r
status = IoCsqInsertIrpEx(\r
- &h_qp->p_irp_queue->csq,\r
+ &p_csq->csq,\r
p_irp,\r
NULL,\r
(VOID*)(ULONG_PTR)NDI_CM_CONNECTING_REQ_SENT\r
);\r
- if( status != STATUS_SUCCESS )\r
+ if( !NT_SUCCESS( status ) )\r
{\r
p_irp->Tail.Overlay.DriverContext[1] = NULL;\r
- __ndi_complete_irp( h_qp, p_irp, status );\r
+ __ndi_complete_irp( p_csq, p_irp, status );\r
}\r
else\r
{\r
* Release the previous reference because IoCsqInsertIrpEx\r
* took a new one.\r
*/\r
- deref_al_obj( &h_qp->obj ); /* Release IRP reference. */\r
+ nd_csq_release( p_csq ); /* Release IRP reference. */\r
}\r
\r
exit:\r
if( p_query_rec->p_result_mad )\r
ib_put_mad( p_query_rec->p_result_mad );\r
\r
- deref_al_obj( &h_qp->obj ); /* release path query reference */\r
+ nd_csq_release( p_csq ); /* release path query reference */\r
AL_EXIT( AL_DBG_NDI );\r
}\r
\r
ib_api_status_t status;\r
ual_ndi_req_cm_ioctl_in_t *p_req = \r
(ual_ndi_req_cm_ioctl_in_t*)cl_ioctl_in_buf( p_irp );\r
- ib_qp_handle_t h_qp = (ib_qp_handle_t)p_irp->Tail.Overlay.DriverContext[0];\r
+ nd_csq_t* p_csq = (nd_csq_t*)p_irp->Tail.Overlay.DriverContext[0];\r
ib_gid_pair_t gids;\r
\r
AL_ENTER( AL_DBG_NDI );\r
\r
- if ( h_qp->p_irp_queue->state != NDI_CM_IDLE )\r
+ if ( p_csq->state != NDI_CM_IDLE )\r
{\r
AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, \r
- ("STATUS_CONNECTION_ACTIVE: h_qp %#I64x, uhdl %#I64x, ref_cnt %d\n",\r
- (uint64_t)(ULONG_PTR)h_qp, h_qp->obj.hdl, h_qp->obj.ref_cnt ) );\r
+ ("STATUS_CONNECTION_ACTIVE: CID=%d, uhdl %#I64x, ref_cnt %d\n",\r
+ p_csq->cid, p_csq->h_qp, p_csq->ref_cnt ) );\r
return STATUS_CONNECTION_ACTIVE;\r
}\r
\r
query_req.timeout_ms = g_sa_timeout;\r
query_req.retry_cnt = g_sa_retries;\r
query_req.flags = 0; /* IB_FLAGS_SYNC */\r
- query_req.query_context = h_qp;\r
+ query_req.query_context = p_csq;\r
query_req.pfn_query_cb = __ndi_pr_query_cb;\r
\r
AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,\r
("Query for path from %I64x to %I64x\n",\r
p_req->guid, ib_gid_get_guid( &p_req->path.dgid )) );\r
\r
- ref_al_obj( &h_qp->obj ); /* take path query reference */\r
- status = ib_query( qp_get_al( h_qp ), &query_req, &h_qp->p_irp_queue->h_query );\r
+ nd_csq_ref( p_csq ); /* take path query reference */\r
+ status = ib_query( p_csq->h_al, &query_req, &p_csq->h_query );\r
if( status != IB_SUCCESS )\r
{\r
- h_qp->p_irp_queue->state = NDI_CM_IDLE;\r
+ p_csq->state = NDI_CM_IDLE;\r
AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("ib_query failed (%d)\n", status) );\r
- deref_al_obj( &h_qp->obj ); /* release path query reference */\r
+ nd_csq_release( p_csq ); /* release path query reference */\r
return ib_to_ntstatus( status );\r
}\r
\r
AL_EXIT( AL_DBG_NDI );\r
- return STATUS_SUCCESS;\r
+ return STATUS_PENDING;\r
}\r
\r
\r
NTSTATUS\r
ndi_req_cm(\r
- IN ib_qp_handle_t const h_qp,\r
+ IN ib_al_handle_t h_al,\r
IN IRP *p_irp\r
)\r
{\r
NTSTATUS status;\r
+ nd_csq_t* p_csq;\r
ual_ndi_req_cm_ioctl_in_t *p_req = \r
(ual_ndi_req_cm_ioctl_in_t*)cl_ioctl_in_buf( p_irp );\r
\r
AL_ENTER( AL_DBG_NDI );\r
\r
- p_irp->Tail.Overlay.DriverContext[0] = (ib_qp_t*)h_qp;\r
+ p_csq = kal_cep_get_context( h_al, p_req->cid, nd_cm_handler, nd_csq_ref );\r
+ if( p_csq == NULL )\r
+ {\r
+ status = nd_csq_init( h_al, p_req->cid, p_req->h_qp, &p_csq );\r
+ if( status != STATUS_SUCCESS )\r
+ goto err;\r
+ }\r
+\r
+ p_irp->Tail.Overlay.DriverContext[0] = p_csq;\r
\r
if( p_req->path.dlid != 0 )\r
{\r
\r
p_irp->Tail.Overlay.DriverContext[1] = &p_req->path;\r
status = IoCsqInsertIrpEx(\r
- &h_qp->p_irp_queue->csq,\r
+ &p_csq->csq,\r
p_irp,\r
NULL,\r
(VOID*)(ULONG_PTR)NDI_CM_CONNECTING_REQ_SENT\r
else\r
{\r
status = IoCsqInsertIrpEx(\r
- &h_qp->p_irp_queue->csq,\r
+ &p_csq->csq,\r
p_irp,\r
NULL,\r
(VOID*)(ULONG_PTR)NDI_CM_CONNECTING_QPR_SENT\r
);\r
}\r
- if( status == STATUS_SUCCESS )\r
- status = STATUS_PENDING;\r
\r
+ nd_csq_release( p_csq );\r
+err:\r
AL_EXIT( AL_DBG_NDI );\r
return status;\r
}\r
IN PIRP p_irp )\r
{\r
ib_api_status_t status;\r
- ib_qp_handle_t h_qp = p_irp->Tail.Overlay.DriverContext[0];\r
+ nd_csq_t* p_csq = p_irp->Tail.Overlay.DriverContext[0];\r
KIRQL irql;\r
NTSTATUS nt_status;\r
\r
{\r
IoFreeWorkItem( p_irp->Tail.Overlay.DriverContext[1] );\r
p_irp->Tail.Overlay.DriverContext[1] = NULL;\r
- deref_al_obj( &h_qp->obj ); /* Release work item reference. */\r
+ nd_csq_release( p_csq ); /* Release work item reference. */\r
}\r
\r
- __ndi_acquire_lock( &h_qp->p_irp_queue->csq, &irql );\r
- if( h_qp->p_irp_queue->state != NDI_CM_CONNECTING_REP_RCVD )\r
+ __ndi_acquire_lock( &p_csq->csq, &irql );\r
+ if( p_csq->state != NDI_CM_CONNECTING_REP_RCVD )\r
{\r
+ __ndi_release_lock( &p_csq->csq, irql );\r
nt_status = STATUS_CONNECTION_ABORTED;\r
goto exit;\r
}\r
- __ndi_release_lock( &h_qp->p_irp_queue->csq, irql );\r
+ __ndi_release_lock( &p_csq->csq, irql );\r
\r
/* change the QP state to RTS */\r
- status = __ndi_qp2rts( h_qp, p_irp );\r
-\r
+ status = __ndi_qp2rts( p_csq, p_irp );\r
if ( status != IB_SUCCESS )\r
{\r
goto err;\r
}\r
\r
/* send RTU */\r
- status = al_cep_rtu( qp_get_al( h_qp ), ((al_conn_qp_t*)h_qp)->cid, NULL, 0 );\r
+ status = al_cep_rtu( p_csq->h_al, p_csq->cid, NULL, 0 );\r
if( status != IB_SUCCESS )\r
{\r
err:\r
- /* Reject and abort the connection. */\r
- al_cep_rej(\r
- qp_get_al( h_qp ), ((al_conn_qp_t*)h_qp)->cid, \r
- IB_REJ_INSUF_QP, NULL, 0, NULL, 0 );\r
-\r
- __cep_timewait_qp( h_qp );\r
+ /*\r
+ * Reject the connection. Note that we don't free the CEP since the\r
+ * usermode INDConnector object references it, and the CEP will be\r
+ * freed when that object is freed.\r
+ */\r
+ al_cep_rej( p_csq->h_al, p_csq->cid, IB_REJ_INSUF_QP, NULL, 0, NULL, 0 );\r
\r
- al_destroy_cep( qp_get_al( h_qp ), &((al_conn_qp_t*)h_qp)->cid, TRUE );\r
+ __cep_timewait_qp( p_csq );\r
\r
AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,\r
("al_cep_rtu returned %s.\n", ib_get_err_str( status )) );\r
\r
- __ndi_acquire_lock( &h_qp->p_irp_queue->csq, &irql );\r
- if( h_qp->p_irp_queue->state != NDI_CM_INVALID )\r
- h_qp->p_irp_queue->state = NDI_CM_IDLE;\r
- __ndi_release_lock( &h_qp->p_irp_queue->csq, irql );\r
+ __ndi_acquire_lock( &p_csq->csq, &irql );\r
+ if( p_csq->state != NDI_CM_INVALID )\r
+ p_csq->state = NDI_CM_IDLE;\r
+ __ndi_release_lock( &p_csq->csq, irql );\r
\r
nt_status = STATUS_CONNECTION_ABORTED;\r
goto exit;\r
}\r
\r
- __ndi_acquire_lock( &h_qp->p_irp_queue->csq, &irql );\r
- if( h_qp->p_irp_queue->state == NDI_CM_CONNECTING_REP_RCVD )\r
- h_qp->p_irp_queue->state = NDI_CM_CONNECTED;\r
- __ndi_release_lock( &h_qp->p_irp_queue->csq, irql );\r
+ __ndi_acquire_lock( &p_csq->csq, &irql );\r
+ if( p_csq->state == NDI_CM_CONNECTING_REP_RCVD )\r
+ p_csq->state = NDI_CM_CONNECTED;\r
+ __ndi_release_lock( &p_csq->csq, irql );\r
\r
nt_status = STATUS_SUCCESS;\r
\r
exit:\r
- __ndi_complete_irp( h_qp, p_irp, nt_status );\r
+ __ndi_complete_irp( p_csq, p_irp, nt_status );\r
AL_EXIT( AL_DBG_NDI );\r
}\r
\r
\r
cl_status_t\r
ndi_rtu_cm(\r
- IN ib_qp_handle_t const h_qp,\r
+ IN nd_csq_t *p_csq,\r
IN PIRP p_irp\r
)\r
{\r
\r
AL_ENTER( AL_DBG_NDI );\r
\r
- p_irp->Tail.Overlay.DriverContext[0] = h_qp;\r
+ p_irp->Tail.Overlay.DriverContext[0] = p_csq;\r
+ nd_csq_ref( p_csq ); /* Take IRP reference. */\r
p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
p_irp->Tail.Overlay.DriverContext[1] = IoAllocateWorkItem( p_io_stack->DeviceObject );\r
- ref_al_obj( &h_qp->obj ); /* Take IRP reference. */\r
\r
IoMarkIrpPending( p_irp );\r
if ( p_irp->Tail.Overlay.DriverContext[1] )\r
{ /* asyncronous performing */\r
/* take a ref to prevent QP destroy before calling work item */\r
- ref_al_obj( &h_qp->obj ); /* Take work item reference. */\r
+ nd_csq_ref( p_csq ); /* Take work item reference. */\r
IoQueueWorkItem( p_irp->Tail.Overlay.DriverContext[1],\r
__ndi_do_rtu, DelayedWorkQueue, p_irp );\r
}\r
IN DEVICE_OBJECT* p_dev_obj,\r
IN PIRP p_irp )\r
{\r
- ib_qp_handle_t h_qp = p_irp->Tail.Overlay.DriverContext[0];\r
+ nd_csq_t* p_csq = p_irp->Tail.Overlay.DriverContext[0];\r
ib_api_status_t status;\r
- ual_ndi_rep_cm_ioctl_in_t *p_rep;\r
KIRQL irql;\r
NTSTATUS nt_status;\r
\r
UNUSED_PARAM(p_dev_obj);\r
\r
- AL_ENTER( AL_DBG_NDI );\r
+ AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI, ("[ CID = %d\n", p_csq->cid) );\r
\r
/* free the work item if any */\r
CL_ASSERT( p_irp->Tail.Overlay.DriverContext[1] != NULL );\r
IoFreeWorkItem( p_irp->Tail.Overlay.DriverContext[1] );\r
p_irp->Tail.Overlay.DriverContext[1] = NULL;\r
- deref_al_obj( &h_qp->obj ); /* Release work item reference. */\r
-\r
- p_rep = (ual_ndi_rep_cm_ioctl_in_t*)cl_ioctl_in_buf( p_irp );\r
\r
/* change the QP state to RTS */\r
- status = __ndi_qp2rts( h_qp, p_irp );\r
+ status = __ndi_qp2rts( p_csq, p_irp );\r
if ( status != IB_SUCCESS )\r
{\r
goto err;\r
}\r
\r
/* send REP */\r
- status = al_cep_send_rep ( qp_get_al( h_qp ), p_rep->cid );\r
+ status = al_cep_send_rep ( p_csq->h_al, p_csq->cid );\r
if( status != IB_SUCCESS )\r
{\r
AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
("al_cep_send_rep returned %s\n", ib_get_err_str(status)) );\r
err:\r
- /* Reject and abort the connection. */\r
- al_cep_rej( qp_get_al( h_qp ), p_rep->cid, IB_REJ_INSUF_QP, NULL, 0, NULL, 0 );\r
+ /*\r
+ * Reject the connection. Note that we don't free the CEP since the\r
+ * usermode INDConnector object references it, and the CEP will be\r
+ * freed when that object is freed.\r
+ */\r
+ al_cep_rej( p_csq->h_al, p_csq->cid, IB_REJ_INSUF_QP, NULL, 0, NULL, 0 );\r
\r
/* transit QP to error state */\r
- __cep_timewait_qp( h_qp );\r
-\r
- al_destroy_cep( qp_get_al( h_qp ), &((al_conn_qp_t*)h_qp)->cid, TRUE );\r
+ __cep_timewait_qp( p_csq );\r
\r
AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
("al_cep_rtu returned %s.\n", ib_get_err_str( status )) );\r
- __ndi_acquire_lock( &h_qp->p_irp_queue->csq, &irql );\r
- if( h_qp->p_irp_queue->state != NDI_CM_INVALID )\r
- h_qp->p_irp_queue->state = NDI_CM_IDLE;\r
- __ndi_release_lock( &h_qp->p_irp_queue->csq, irql );\r
- if (status == IB_INVALID_STATE)\r
+ __ndi_acquire_lock( &p_csq->csq, &irql );\r
+ if( p_csq->state != NDI_CM_INVALID )\r
+ p_csq->state = NDI_CM_IDLE;\r
+ __ndi_release_lock( &p_csq->csq, irql );\r
+ if (status == IB_INVALID_STATE )\r
nt_status = STATUS_CONNECTION_ABORTED;\r
+ /* The HCA driver will return IB_INVALID_PARAMETER if the QP is in the wrong state. */\r
+ else if( status == IB_INVALID_HANDLE || status == IB_INVALID_PARAMETER )\r
+ nt_status = STATUS_CANCELLED;\r
else\r
- nt_status =STATUS_INSUFFICIENT_RESOURCES;\r
+ nt_status = STATUS_INSUFFICIENT_RESOURCES;\r
goto exit;\r
}\r
\r
- __ndi_acquire_lock( &h_qp->p_irp_queue->csq, &irql );\r
- if( h_qp->p_irp_queue->state == NDI_CM_CONNECTING_REP_SENT )\r
- h_qp->p_irp_queue->state = NDI_CM_CONNECTED;\r
- __ndi_release_lock( &h_qp->p_irp_queue->csq, irql );\r
+ __ndi_acquire_lock( &p_csq->csq, &irql );\r
+ if( p_csq->state == NDI_CM_CONNECTING_REP_SENT )\r
+ p_csq->state = NDI_CM_CONNECTED;\r
+ __ndi_release_lock( &p_csq->csq, irql );\r
nt_status = STATUS_SUCCESS;\r
\r
exit:\r
- __ndi_complete_irp( h_qp, p_irp, nt_status );\r
+ __ndi_complete_irp( p_csq, p_irp, nt_status );\r
+ nd_csq_release( p_csq ); /* Release work item reference. */\r
AL_EXIT( AL_DBG_NDI );\r
}\r
\r
static void\r
__ndi_fill_cm_rep(\r
- IN ib_qp_handle_t const h_qp,\r
+ IN net32_t qpn,\r
IN ual_ndi_rep_cm_ioctl_in_t *p_rep,\r
OUT iba_cm_rep *p_cm_rep)\r
{\r
p_cm_rep->p_pdata = p_rep->pdata;\r
p_cm_rep->pdata_len = sizeof(p_rep->pdata);\r
\r
- p_cm_rep->qpn = h_qp->num;\r
+ p_cm_rep->qpn = qpn;\r
\r
p_cm_rep->init_depth = p_rep->init_depth;\r
p_cm_rep->failover_accepted = IB_FAILOVER_ACCEPT_UNSUPPORTED;\r
\r
NTSTATUS\r
__ndi_send_rep(\r
- IN ib_qp_handle_t h_qp,\r
+ IN nd_csq_t *p_csq,\r
IN PIRP p_irp )\r
{\r
IO_STACK_LOCATION *p_io_stack;\r
+ ib_qp_handle_t h_qp;\r
iba_cm_rep cm_rep;\r
- ib_qp_mod_t qp_mod;\r
ib_api_status_t status;\r
ual_ndi_rep_cm_ioctl_in_t *p_rep = \r
(ual_ndi_rep_cm_ioctl_in_t*)cl_ioctl_in_buf( p_irp );\r
\r
- AL_ENTER( AL_DBG_NDI );\r
+ AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI,\r
+ ("[ CID = %d\n", p_csq->cid) );\r
\r
- if( h_qp->p_irp_queue->state != NDI_CM_IDLE )\r
+ switch( p_csq->state )\r
{\r
+ case NDI_CM_CONNECTING_REQ_RCVD:\r
+ break;\r
+\r
+ case NDI_CM_CONNECTED_DREQ_RCVD:\r
+ AL_EXIT( AL_DBG_NDI );\r
+ return STATUS_CONNECTION_ABORTED;\r
+\r
+ default:\r
AL_EXIT( AL_DBG_NDI );\r
return STATUS_CONNECTION_ACTIVE;\r
}\r
AL_EXIT( AL_DBG_NDI );\r
return STATUS_NO_MEMORY;\r
}\r
- ref_al_obj( &h_qp->obj ); /* Take work item reference. */\r
+ nd_csq_ref( p_csq ); /* Take work item reference. */\r
\r
- /* Format ib_cm_req_t structure */\r
- __ndi_fill_cm_rep( h_qp, p_rep, &cm_rep );\r
+ h_qp = CONTAINING_RECORD(\r
+ al_hdl_ref( p_csq->h_al, p_csq->h_qp, AL_OBJ_TYPE_H_QP ),\r
+ ib_qp_t,\r
+ obj );\r
+ if( !h_qp )\r
+ {\r
+ /* The QP was valid when the IOCTL first came in... */\r
+ AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
+ ("Invalid QP: %I64d\n", p_rep->h_qp) );\r
+ status = IB_INVALID_HANDLE;\r
+ goto err;\r
+ }\r
\r
- ref_al_obj( &h_qp->obj ); /* Take CEP reference. */\r
+ /* Format ib_cm_req_t structure */\r
+ __ndi_fill_cm_rep( h_qp->num, p_rep, &cm_rep );\r
+ deref_al_obj( &h_qp->obj );\r
\r
/* prepare Passive CEP for connection */\r
- status = kal_cep_config_pre_rep_copy_cid(\r
- qp_get_al( h_qp ), p_rep->cid, __ndi_cm_handler, &h_qp->obj, deref_al_obj,\r
- &cm_rep, QP_ATTRIB_RNR_NAK_TIMEOUT, &((al_conn_qp_t*)h_qp)->cid, &qp_mod);\r
+ status = kal_cep_pre_rep(\r
+ p_csq->h_al, p_csq->cid, &cm_rep, QP_ATTRIB_RNR_NAK_TIMEOUT, NULL );\r
if( status != IB_SUCCESS )\r
{\r
+ AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
+ ("kal_cep_pre_rep returned %s.\n", ib_get_err_str( status )) );\r
+err:\r
IoFreeWorkItem( p_irp->Tail.Overlay.DriverContext[1] );\r
p_irp->Tail.Overlay.DriverContext[1] = NULL;\r
- deref_al_obj( &h_qp->obj ); /* Release work item reference. */\r
- al_destroy_cep( qp_get_al( h_qp ), &p_rep->cid, FALSE );\r
- deref_al_obj( &h_qp->obj ); /* Release CEP reference. */\r
- AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
- ("kal_cep_config_pre_rep_copy_cid returned %s.\n", ib_get_err_str( status )) );\r
+ nd_csq_release( p_csq ); /* Release work item reference. */\r
switch (status)\r
{\r
case IB_INVALID_HANDLE:\r
\r
AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,\r
("Prepared Passive CEP with cid %d, h_al %p, context %p\n",\r
- p_rep->cid, qp_get_al( h_qp ), h_qp ) );\r
+ p_csq->cid, p_csq->h_al, h_qp ) );\r
\r
/*\r
* transfer work to a worker thread so that QP transitions can be done\r
__ndi_do_rep, DelayedWorkQueue, p_irp );\r
\r
AL_EXIT( AL_DBG_NDI );\r
- return STATUS_SUCCESS;\r
+ return STATUS_PENDING;\r
}\r
\r
\r
NTSTATUS\r
ndi_rep_cm(\r
- IN ib_qp_handle_t const h_qp,\r
+ IN ib_al_handle_t h_al,\r
IN PIRP p_irp\r
)\r
{\r
NTSTATUS status;\r
+ nd_csq_t* p_csq;\r
+ ual_ndi_rep_cm_ioctl_in_t *p_rep = \r
+ (ual_ndi_rep_cm_ioctl_in_t*)cl_ioctl_in_buf( p_irp );\r
KIRQL irql;\r
\r
AL_ENTER( AL_DBG_NDI );\r
\r
- p_irp->Tail.Overlay.DriverContext[0] = h_qp;\r
+ p_csq = kal_cep_get_context( h_al, p_rep->cid, nd_cm_handler, nd_csq_ref );\r
+ if( p_csq == NULL )\r
+ {\r
+ status = STATUS_CONNECTION_ABORTED;\r
+ goto err;\r
+ }\r
\r
- __ndi_acquire_lock( &h_qp->p_irp_queue->csq, &irql );\r
- status = __ndi_send_rep( h_qp, p_irp );\r
- if( status == STATUS_SUCCESS )\r
+ p_csq->h_qp = p_rep->h_qp;\r
+\r
+ p_irp->Tail.Overlay.DriverContext[0] = p_csq;\r
+\r
+ __ndi_acquire_lock( &p_csq->csq, &irql );\r
+ status = __ndi_send_rep( p_csq, p_irp );\r
+ if( status == STATUS_PENDING )\r
{\r
/*\r
* We're going to keep the IRP dangling for a bit - take a reference\r
* on the QP until it completes.\r
*/\r
- ref_al_obj( &h_qp->obj ); /* Take IRP reference. */\r
- h_qp->p_irp_queue->state = NDI_CM_CONNECTING_REP_SENT;\r
+ nd_csq_ref( p_csq ); /* Take IRP reference. */\r
+ p_csq->state = NDI_CM_CONNECTING_REP_SENT;\r
IoMarkIrpPending( p_irp );\r
- status = STATUS_PENDING;\r
}\r
- __ndi_release_lock( &h_qp->p_irp_queue->csq, irql );\r
+ __ndi_release_lock( &p_csq->csq, irql );\r
\r
- AL_EXIT( AL_DBG_NDI );\r
+ nd_csq_release( p_csq );\r
+err:\r
+ AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI, ("] returning %08x\n", status) );\r
return status;\r
}\r
\r
IN IRP* p_irp\r
)\r
{\r
- ib_qp_handle_t h_qp = (ib_qp_handle_t)p_irp->Tail.Overlay.DriverContext[0];\r
+ nd_csq_t *p_csq = (nd_csq_t*)p_irp->Tail.Overlay.DriverContext[0];\r
IO_STACK_LOCATION *p_io_stack;\r
ib_api_status_t status;\r
NTSTATUS nt_status;\r
\r
AL_ENTER( AL_DBG_NDI );\r
\r
- if ( h_qp->p_irp_queue->state != NDI_CM_CONNECTED &&\r
- h_qp->p_irp_queue->state != NDI_CM_CONNECTED_DREQ_RCVD )\r
+ if ( p_csq->state != NDI_CM_CONNECTED &&\r
+ p_csq->state != NDI_CM_CONNECTED_DREQ_RCVD )\r
{\r
AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, \r
- ("STATUS_CONNECTION_ACTIVE: h_qp %#I64x, uhdl %#I64x, ref_cnt %d\n",\r
- (uint64_t)(ULONG_PTR)h_qp, h_qp->obj.hdl, h_qp->obj.ref_cnt ) );\r
+ ("STATUS_CONNECTION_ACTIVE: CID = %d, uhdl %#I64x, ref_cnt %d\n",\r
+ p_csq->cid, p_csq->h_qp, p_csq->ref_cnt ) );\r
return STATUS_CONNECTION_INVALID;\r
}\r
\r
AL_EXIT( AL_DBG_NDI );\r
return STATUS_NO_MEMORY;\r
}\r
- ref_al_obj( &h_qp->obj ); /* Take work item reference. */\r
+ nd_csq_ref( p_csq ); /* Take work item reference. */\r
\r
- status = al_cep_dreq( qp_get_al( h_qp ), ((al_conn_qp_t*)h_qp)->cid, NULL, 0 );\r
+ status = al_cep_dreq( p_csq->h_al, p_csq->cid, NULL, 0 );\r
switch( status )\r
{\r
case IB_INVALID_STATE:\r
- /* We might have just received a DREQ, so try sending a DREP. */\r
- __ndi_queue_drep( p_irp );\r
- IoMarkIrpPending( p_irp );\r
/*\r
* We're going to keep the IRP dangling for a bit - take a reference\r
- * on the QP until it completes.\r
+ * on the CSQ until it completes.\r
*/\r
- ref_al_obj( &h_qp->obj ); /* Take IRP reference. */\r
+ nd_csq_ref( p_csq ); /* Take IRP reference. */\r
+ /* We might have just received a DREQ, so try sending a DREP. */\r
+ IoMarkIrpPending( p_irp );\r
+ __ndi_queue_drep( p_irp );\r
+ AL_EXIT( AL_DBG_NDI );\r
+ return STATUS_INVALID_DEVICE_STATE;\r
\r
case IB_SUCCESS:\r
AL_EXIT( AL_DBG_NDI );\r
- return( ib_to_ntstatus( status ) );\r
+ return STATUS_PENDING;\r
\r
case IB_INVALID_HANDLE:\r
nt_status = STATUS_CONNECTION_INVALID;\r
}\r
IoFreeWorkItem( p_irp->Tail.Overlay.DriverContext[1] );\r
p_irp->Tail.Overlay.DriverContext[1] = NULL;\r
- deref_al_obj( &h_qp->obj ); /* Release work item reference. */\r
+ nd_csq_release( p_csq ); /* Release work item reference. */\r
AL_EXIT( AL_DBG_NDI );\r
return nt_status;\r
}\r
\r
NTSTATUS\r
ndi_dreq_cm(\r
- IN ib_qp_handle_t const h_qp,\r
+ IN nd_csq_t* p_csq,\r
IN PIRP p_irp\r
)\r
{\r
\r
AL_ENTER( AL_DBG_NDI );\r
\r
- p_irp->Tail.Overlay.DriverContext[0] = h_qp;\r
+ p_irp->Tail.Overlay.DriverContext[0] = p_csq;\r
\r
status = IoCsqInsertIrpEx(\r
- &h_qp->p_irp_queue->csq,\r
+ &p_csq->csq,\r
p_irp,\r
NULL,\r
(VOID*)(ULONG_PTR)NDI_CM_DISCONNECTING\r
* The IRP should never be queued if the work item is queued, so \r
* we trap the special error code for INVALID_STATE.\r
*/\r
- if( status == STATUS_SUCCESS || status == STATUS_INVALID_DEVICE_STATE )\r
+ if( status == STATUS_INVALID_DEVICE_STATE )\r
status = STATUS_PENDING;\r
\r
AL_EXIT( AL_DBG_NDI );\r
return status;\r
}\r
\r
+\r
+NTSTATUS\r
+ndi_listen_cm(\r
+ IN ib_al_handle_t h_al,\r
+ IN ib_cep_listen_t *p_listen,\r
+ OUT net32_t *p_cid,\r
+ OUT size_t *p_ret_bytes\r
+ )\r
+{\r
+ NTSTATUS status;\r
+ net32_t cid;\r
+ ib_api_status_t ib_status;\r
+ nd_csq_t *p_csq;\r
+ KIRQL irql;\r
+\r
+ AL_ENTER( AL_DBG_NDI );\r
+\r
+ ib_status = al_create_cep( h_al, NULL, NULL, NULL, &cid );\r
+ if( ib_status != IB_SUCCESS )\r
+ {\r
+ AL_EXIT( AL_DBG_NDI );\r
+ return ib_to_ntstatus( ib_status );\r
+ }\r
+\r
+ status = nd_csq_init( h_al, cid, 0, &p_csq );\r
+ if( status != STATUS_SUCCESS )\r
+ {\r
+ kal_cep_destroy( h_al, cid, STATUS_SUCCESS );\r
+ AL_EXIT( AL_DBG_NDI );\r
+ return status;\r
+ }\r
+\r
+ __ndi_acquire_lock( &p_csq->csq, &irql );\r
+ p_csq->state = NDI_CM_LISTEN;\r
+ __ndi_release_lock( &p_csq->csq, irql );\r
+\r
+ if( (p_listen->svc_id & 0xFFFF) == 0 )\r
+ {\r
+ p_listen->svc_id |= (USHORT)cid | (USHORT)(cid >> 16);\r
+ }\r
+\r
+ ib_status = al_cep_listen( h_al, cid, p_listen );\r
+ if( ib_status == IB_SUCCESS )\r
+ {\r
+ *p_cid = cid;\r
+ *p_ret_bytes = sizeof(*p_cid);\r
+ }\r
+\r
+ nd_csq_release( p_csq );\r
+ status = ib_to_ntstatus( ib_status );\r
+ AL_EXIT( AL_DBG_NDI );\r
+ return status;\r
+}\r
+\r
+\r
+NTSTATUS\r
+__ndi_get_req(\r
+ IN nd_csq_t *p_csq,\r
+ IN IRP* p_irp\r
+ )\r
+{\r
+ AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI, ("[ CID = %d\n", p_csq->cid) );\r
+\r
+ if( p_csq->state != NDI_CM_LISTEN )\r
+ {\r
+ AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_NDI,\r
+ ("] Invalid state (%d).\n", p_csq->state) );\r
+ return STATUS_INVALID_DEVICE_REQUEST;\r
+ }\r
+\r
+ /* Check the MAD list. */\r
+ if( p_csq->p_mad_head != NULL )\r
+ {\r
+ ib_mad_element_t* p_mad = p_csq->p_mad_head;\r
+ net32_t cid = (net32_t)(ULONG_PTR)p_mad->send_context1;\r
+ p_csq->p_mad_head = p_mad->p_next;\r
+ p_mad->p_next = NULL;\r
+\r
+ *(net32_t*)cl_ioctl_out_buf( p_irp ) = cid;\r
+ p_irp->IoStatus.Information = sizeof(net32_t);\r
+ p_irp->IoStatus.Status = STATUS_SUCCESS;\r
+ IoMarkIrpPending( p_irp );\r
+ IoCompleteRequest( p_irp, IO_NETWORK_INCREMENT );\r
+ ib_put_mad( p_mad );\r
+ AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI, ("] Returned new CID = %d\n", cid) );\r
+ return STATUS_INVALID_DEVICE_STATE;\r
+ }\r
+\r
+ AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI, ("] Queueing IRP\n") );\r
+ return STATUS_PENDING;\r
+}\r
+\r
+\r
+NTSTATUS\r
+ndi_get_req_cm(\r
+ IN nd_csq_t *p_csq,\r
+ IN PIRP p_irp\r
+ )\r
+{\r
+ NTSTATUS status;\r
+\r
+ AL_ENTER( AL_DBG_NDI );\r
+\r
+ status = IoCsqInsertIrpEx(\r
+ &p_csq->csq,\r
+ p_irp,\r
+ NULL,\r
+ (VOID*)(ULONG_PTR)NDI_CM_LISTEN\r
+ );\r
+\r
+ /*\r
+ * __ndi_get_req will return STATUS_INVALID_DEVICE_STATE to prevent the IRP\r
+ * from being inserted into the CSQ because the IRP was immediately completed.\r
+ * In this case, we need to return STATUS_PENDING.\r
+ */\r
+ if( status == STATUS_INVALID_DEVICE_STATE )\r
+ {\r
+ status = STATUS_PENDING;\r
+ }\r
+\r
+ AL_EXIT( AL_DBG_NDI );\r
+ return status;\r
+}\r
+\r
+\r
+\r
typedef enum _ndi_cm_state \r
{\r
NDI_CM_IDLE,\r
+ NDI_CM_LISTEN,\r
NDI_CM_CONNECTING_QPR_SENT, // QPR = Query path record\r
NDI_CM_CONNECTING_REQ_SENT,\r
+ NDI_CM_CONNECTING_REQ_RCVD,\r
NDI_CM_CONNECTING_REP_SENT,\r
NDI_CM_CONNECTING_REP_RCVD,\r
NDI_CM_CONNECTED,\r
\r
typedef struct _ib_qp ib_qp_t;\r
\r
-typedef struct _ndi_qp_csq\r
+typedef struct _nd_csq\r
{\r
IO_CSQ csq;\r
LIST_ENTRY queue;\r
- ib_qp_t* h_qp;\r
- ib_query_handle_t h_query;\r
+ ib_al_handle_t h_al;\r
+ union {\r
+ uint64_t h_qp;\r
+ ib_mad_element_t *p_mad_head;\r
+ };\r
+ union {\r
+ ib_query_handle_t h_query;\r
+ ib_mad_element_t *p_mad_tail;\r
+ };\r
+ net32_t cid;\r
ndi_cm_state_t state;\r
PIO_WORKITEM p_workitem;\r
+ volatile LONG ref_cnt;\r
+ KSPIN_LOCK lock;\r
+\r
+} nd_csq_t;\r
\r
-} ndi_qp_csq_t;\r
\r
ib_api_status_t\r
ndi_modify_qp(\r
IN const uint32_t buf_size,\r
IN uint8_t* const p_outbuf);\r
\r
+void\r
+nd_csq_ref( nd_csq_t* p_csq );\r
+\r
+void\r
+nd_csq_release( nd_csq_t* p_csq );\r
+\r
+void\r
+nd_cm_handler(\r
+ IN const ib_al_handle_t h_al,\r
+ IN const net32_t cid );\r
+\r
NTSTATUS\r
ndi_req_cm(\r
- IN ib_qp_handle_t const h_qp,\r
- IN cl_ioctl_handle_t h_ioctl\r
+ IN ib_al_handle_t h_al,\r
+ IN PIRP p_irp\r
);\r
\r
NTSTATUS\r
ndi_rep_cm(\r
- IN ib_qp_handle_t const h_qp,\r
+ IN ib_al_handle_t h_al,\r
IN PIRP p_irp\r
);\r
\r
cl_status_t\r
ndi_rtu_cm(\r
- IN ib_qp_handle_t const h_qp,\r
+ IN nd_csq_t *p_csq,\r
IN PIRP p_irp\r
);\r
\r
NTSTATUS\r
ndi_dreq_cm(\r
- IN ib_qp_handle_t const h_qp,\r
+ IN nd_csq_t *p_csq,\r
IN PIRP p_irp\r
);\r
- \r
-NTSTATUS\r
-ndi_qp_init(\r
- IN ib_qp_handle_t h_qp );\r
\r
void\r
-ndi_qp_destroy(\r
- IN ib_qp_handle_t h_qp );\r
+ndi_cancel_cm_irps(\r
+ IN nd_csq_t *p_csq\r
+ );\r
\r
-void\r
-ndi_qp_free(\r
- IN ib_qp_handle_t h_qp );\r
+NTSTATUS\r
+ndi_listen_cm(\r
+ IN ib_al_handle_t h_al,\r
+ IN ib_cep_listen_t *p_listen,\r
+ OUT net32_t *p_cid,\r
+ OUT size_t *p_ret_bytes\r
+ );\r
+\r
+NTSTATUS\r
+ndi_get_req_cm(\r
+ IN nd_csq_t *p_csq,\r
+ IN PIRP p_irp\r
+ );\r
\r
#endif\r
\r
OUT size_t *p_ret_bytes )\r
{\r
al_dev_open_context_t *p_context;\r
- void* user_context;\r
ual_create_cep_ioctl_t *p_ioctl;\r
\r
AL_ENTER( AL_DBG_CM );\r
p_ioctl = (ual_create_cep_ioctl_t*)cl_ioctl_out_buf( h_ioctl );\r
\r
/* Validate user parameters. */\r
- if( cl_ioctl_in_size( h_ioctl ) != sizeof(uint64_t) ||\r
- cl_ioctl_out_size( h_ioctl ) != sizeof(ual_create_cep_ioctl_t) )\r
+ if( cl_ioctl_out_size( h_ioctl ) != sizeof(ual_create_cep_ioctl_t) )\r
{\r
AL_EXIT( AL_DBG_CM );\r
return CL_INVALID_PARAMETER;\r
}\r
-\r
- user_context = *(void**)cl_ioctl_in_buf( h_ioctl );\r
-\r
/* We use IRPs as notification mechanism so the callback is NULL. */\r
- p_ioctl->cid = AL_INVALID_CID;\r
- p_ioctl->status = al_create_cep( p_context->h_al, NULL,\r
- user_context, NULL, &p_ioctl->cid );\r
+ p_ioctl->status = kal_cep_alloc( p_context->h_al, &p_ioctl->cid );\r
\r
*p_ret_bytes = sizeof(ual_create_cep_ioctl_t);\r
\r
}\r
\r
\r
-static cl_status_t\r
-proxy_cep_get_req_cid(\r
- IN void *p_open_context,\r
- IN cl_ioctl_handle_t h_ioctl,\r
- OUT size_t *p_ret_bytes )\r
-{\r
- cl_status_t cl_status;\r
- al_dev_open_context_t *p_context;\r
- UNUSED_PARAM(p_ret_bytes);\r
- \r
- AL_ENTER( AL_DBG_CM );\r
-\r
- p_context = (al_dev_open_context_t*)p_open_context;\r
-\r
- /* Validate user parameters. */\r
- if( cl_ioctl_in_size( h_ioctl ) != sizeof(uint32_t) ||\r
- cl_ioctl_out_size( h_ioctl ) != sizeof(uint32_t) )\r
- {\r
- AL_EXIT( AL_DBG_CM );\r
- return CL_INVALID_PARAMETER;\r
- }\r
-\r
- /* get CID */\r
- cl_status = al_cep_get_cid( p_context->h_al, \r
- *(uint32_t*)cl_ioctl_in_buf( h_ioctl ), h_ioctl );\r
-\r
- AL_EXIT( AL_DBG_CM );\r
- return cl_status;\r
-}\r
-\r
-\r
\r
static cl_status_t\r
proxy_cep_get_pdata(\r
{\r
al_dev_open_context_t *p_context;\r
ual_cep_get_pdata_ioctl_t *p_ioctl;\r
- al_conn_qp_t *p_qp;\r
NTSTATUS status;\r
+ net32_t cid;\r
\r
AL_ENTER( AL_DBG_CM );\r
\r
return CL_INVALID_PARAMETER;\r
}\r
\r
- if ( p_ioctl->in.h_qp )\r
- {\r
- /* Get the kernel QP handle. */\r
- p_qp = (al_conn_qp_t*)al_hdl_ref(\r
- p_context->h_al, p_ioctl->in.h_qp, AL_OBJ_TYPE_H_QP );\r
- if( !p_qp )\r
- {\r
- AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, \r
- ("Invalid QP handle\n"));\r
- return CL_CONNECTION_INVALID;\r
- }\r
- p_ioctl->in.cid = p_qp->cid;\r
- deref_al_obj( &p_qp->qp.obj );\r
- }\r
-\r
+ cid = p_ioctl->in.cid;\r
p_ioctl->out.pdata_len = sizeof(p_ioctl->out.pdata);\r
- status = al_cep_get_pdata( p_context->h_al, p_ioctl->in.cid,\r
+ status = al_cep_get_pdata( p_context->h_al, cid,\r
&p_ioctl->out.init_depth, &p_ioctl->out.resp_res,\r
(uint8_t*)&p_ioctl->out.pdata_len, p_ioctl->out.pdata );\r
\r
return status;\r
}\r
\r
+\r
cl_status_t cep_ioctl(\r
IN cl_ioctl_handle_t h_ioctl,\r
OUT size_t *p_ret_bytes )\r
case UAL_CEP_POLL:\r
cl_status = proxy_cep_poll( p_context, h_ioctl, p_ret_bytes );\r
break;\r
- case UAL_CEP_GET_REQ_CID:\r
- cl_status = proxy_cep_get_req_cid( p_context, h_ioctl, p_ret_bytes );\r
- break;\r
case UAL_CEP_GET_PDATA:\r
cl_status = proxy_cep_get_pdata( p_context, h_ioctl, p_ret_bytes );\r
break;\r
#include "al_proxy_ndi.h"\r
#include "al_ndi_cm.h"\r
\r
+#if WINVER <= 0x501\r
+#include "csq.h"\r
+#endif\r
+\r
/*******************************************************************\r
*\r
* IOCTLS\r
p_context = (al_dev_open_context_t*)p_open_context;\r
\r
/* Validate user parameters. */\r
- if( cl_ioctl_in_size( h_ioctl ) < sizeof(ual_ndi_req_cm_ioctl_in_t))\r
+ if( cl_ioctl_in_size( h_ioctl ) < sizeof(ual_ndi_req_cm_ioctl_in_t) )\r
{\r
cl_status = CL_INVALID_PARAMETER;\r
goto exit;\r
}\r
\r
/* perform the ioctl */\r
- cl_status = ndi_req_cm( h_qp, h_ioctl );\r
+ cl_status = ndi_req_cm( p_context->h_al, h_ioctl );\r
\r
err:\r
deref_al_obj( &h_qp->obj );\r
cl_status_t cl_status;\r
ib_qp_handle_t h_qp = NULL;\r
al_dev_open_context_t *p_context;\r
- net32_t cid;\r
ual_ndi_rep_cm_ioctl_in_t *p_rep = \r
(ual_ndi_rep_cm_ioctl_in_t*)cl_ioctl_in_buf( h_ioctl );\r
UNUSED_PARAM(p_ret_bytes);\r
goto exit;\r
}\r
\r
+ AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI,\r
+ ("CID = %d\n", p_rep->cid) );\r
+\r
/* Get and validate QP handle */\r
h_qp = (ib_qp_handle_t)al_hdl_ref( p_context->h_al, p_rep->h_qp, AL_OBJ_TYPE_H_QP );\r
if( !h_qp )\r
cl_status = CL_INVALID_PARAMETER;\r
goto err;\r
}\r
- \r
- /* Get and validate CID */\r
- cid = p_rep->cid;\r
\r
/* perform the ioctls */\r
- cl_status = ndi_rep_cm( h_qp, h_ioctl );\r
+ cl_status = ndi_rep_cm( p_context->h_al, h_ioctl );\r
\r
err:\r
deref_al_obj( &h_qp->obj );\r
goto exit;\r
}\r
\r
- al_destroy_cep( p_context->h_al, &p_rej->cid, FALSE );\r
ntstatus = STATUS_SUCCESS;\r
\r
exit:\r
OUT size_t *p_ret_bytes )\r
{\r
cl_status_t cl_status;\r
- ib_qp_handle_t h_qp = NULL;\r
+ nd_csq_t* p_csq;\r
al_dev_open_context_t *p_context;\r
- ual_ndi_rtu_cm_ioctl_in_t *p_rtu = \r
- (ual_ndi_rtu_cm_ioctl_in_t*)cl_ioctl_in_buf( h_ioctl );\r
\r
UNUSED_PARAM(p_ret_bytes);\r
\r
p_context = (al_dev_open_context_t*)p_open_context;\r
\r
/* Validate user parameters. */\r
- if( cl_ioctl_in_size( h_ioctl ) < sizeof(ual_ndi_rtu_cm_ioctl_in_t))\r
+ if( cl_ioctl_in_size( h_ioctl ) < sizeof(net32_t) )\r
{\r
cl_status = CL_INVALID_PARAMETER;\r
goto exit;\r
}\r
\r
- /* Validate QP handle */\r
- h_qp = (ib_qp_handle_t)al_hdl_ref( p_context->h_al, p_rtu->h_qp, AL_OBJ_TYPE_H_QP );\r
- if( !h_qp )\r
+ p_csq = kal_cep_get_context(\r
+ p_context->h_al,\r
+ *(net32_t*)cl_ioctl_in_buf( h_ioctl ),\r
+ nd_cm_handler,\r
+ nd_csq_ref\r
+ );\r
+ if( p_csq == NULL )\r
{\r
cl_status = CL_INVALID_HANDLE;\r
goto exit;\r
}\r
\r
- /* Check QP type */\r
- if( h_qp->type != IB_QPT_RELIABLE_CONN )\r
- {\r
- cl_status = CL_INVALID_HANDLE;\r
- goto err;\r
- }\r
-\r
/* perform the ioctl */\r
- cl_status = ndi_rtu_cm( h_qp, h_ioctl );\r
+ cl_status = ndi_rtu_cm( p_csq, h_ioctl );\r
\r
-err:\r
- deref_al_obj( &h_qp->obj );\r
+ nd_csq_release( p_csq );\r
\r
exit:\r
AL_EXIT( AL_DBG_NDI );\r
OUT size_t *p_ret_bytes )\r
{\r
cl_status_t cl_status;\r
- ib_qp_handle_t h_qp = NULL;\r
+ nd_csq_t *p_csq;\r
al_dev_open_context_t *p_context;\r
\r
UNUSED_PARAM(p_ret_bytes);\r
p_context = (al_dev_open_context_t*)p_open_context;\r
\r
/* Validate user parameters. */\r
- if( cl_ioctl_in_size( h_ioctl ) < sizeof(uint64_t))\r
+ if( cl_ioctl_in_size( h_ioctl ) < sizeof(net32_t) )\r
{\r
cl_status = CL_INVALID_PARAMETER;\r
goto exit;\r
}\r
\r
- /* Validate QP handle */\r
- h_qp = (ib_qp_handle_t)al_hdl_ref( p_context->h_al, \r
- *(uint64_t*)cl_ioctl_in_buf( h_ioctl ), AL_OBJ_TYPE_H_QP );\r
- if( !h_qp )\r
+ /* Validate CID */\r
+ p_csq = (nd_csq_t*)kal_cep_get_context(\r
+ p_context->h_al,\r
+ *(net32_t*)cl_ioctl_in_buf( h_ioctl ),\r
+ nd_cm_handler,\r
+ nd_csq_ref\r
+ );\r
+\r
+ if( p_csq == NULL )\r
{\r
cl_status = CL_CONNECTION_INVALID;\r
goto exit;\r
}\r
\r
- /* Check QP type */\r
- if( h_qp->type != IB_QPT_RELIABLE_CONN )\r
+ /* perform the ioctl */\r
+ cl_status = ndi_dreq_cm( p_csq, h_ioctl );\r
+\r
+ nd_csq_release( p_csq );\r
+\r
+exit:\r
+ AL_EXIT( AL_DBG_NDI );\r
+ return cl_status;\r
+}\r
+\r
+static NTSTATUS\r
+__ndi_notify_dreq_cm(\r
+ IN void *p_open_context,\r
+ IN cl_ioctl_handle_t h_ioctl,\r
+ OUT size_t *p_ret_bytes )\r
+{\r
+ NTSTATUS status;\r
+ nd_csq_t *p_csq;\r
+ al_dev_open_context_t *p_context;\r
+\r
+ UNUSED_PARAM(p_ret_bytes);\r
+ \r
+ AL_ENTER( AL_DBG_NDI );\r
+\r
+ p_context = (al_dev_open_context_t*)p_open_context;\r
+\r
+ /* Validate user parameters. */\r
+ if( cl_ioctl_in_size( h_ioctl ) < sizeof(net32_t) )\r
{\r
- cl_status = CL_CONNECTION_INVALID;\r
- goto err;\r
+ status = STATUS_INVALID_PARAMETER;\r
+ goto exit;\r
+ }\r
+\r
+ /* Validate CID */\r
+ p_csq = (nd_csq_t*)kal_cep_get_context(\r
+ p_context->h_al,\r
+ *(net32_t*)cl_ioctl_in_buf( h_ioctl ),\r
+ nd_cm_handler,\r
+ nd_csq_ref\r
+ );\r
+\r
+ if( p_csq == NULL )\r
+ {\r
+ status = STATUS_CONNECTION_INVALID;\r
+ goto exit;\r
}\r
\r
/* perform the ioctl */\r
- cl_status = ndi_dreq_cm( h_qp, h_ioctl );\r
+ status = IoCsqInsertIrpEx(\r
+ &p_csq->csq,\r
+ h_ioctl,\r
+ NULL,\r
+ (VOID*)(ULONG_PTR)NDI_CM_CONNECTED_DREQ_RCVD\r
+ );\r
\r
-err:\r
- deref_al_obj( &h_qp->obj );\r
+ nd_csq_release( p_csq );\r
\r
exit:\r
AL_EXIT( AL_DBG_NDI );\r
- return cl_status;\r
+ return status;\r
+}\r
+\r
+static cl_status_t\r
+__ndi_cancel_cm_irps(\r
+ IN void *p_open_context,\r
+ IN cl_ioctl_handle_t h_ioctl,\r
+ OUT size_t *p_ret_bytes )\r
+{\r
+ nd_csq_t *p_csq;\r
+ al_dev_open_context_t *p_context;\r
+\r
+ UNUSED_PARAM(p_ret_bytes);\r
+ \r
+ AL_ENTER( AL_DBG_NDI );\r
+\r
+ p_context = (al_dev_open_context_t*)p_open_context;\r
+\r
+ /* Validate user parameters. */\r
+ if( cl_ioctl_in_size( h_ioctl ) < sizeof(net32_t) )\r
+ {\r
+ AL_EXIT( AL_DBG_NDI );\r
+ return STATUS_INVALID_PARAMETER;\r
+ }\r
+\r
+ /* Validate CID */\r
+ p_csq = (nd_csq_t*)kal_cep_get_context(\r
+ p_context->h_al,\r
+ *(net32_t*)cl_ioctl_in_buf( h_ioctl ),\r
+ nd_cm_handler,\r
+ nd_csq_ref\r
+ );\r
+\r
+ if( p_csq == NULL )\r
+ {\r
+ AL_EXIT( AL_DBG_NDI );\r
+ return STATUS_UNSUCCESSFUL;\r
+ }\r
+\r
+ /* perform the ioctl */\r
+ ndi_cancel_cm_irps( p_csq );\r
+ nd_csq_release( p_csq );\r
+\r
+ AL_EXIT( AL_DBG_NDI );\r
+ return STATUS_SUCCESS;\r
+}\r
+\r
+static cl_status_t\r
+__ndi_listen_cm(\r
+ IN void *p_open_context,\r
+ IN cl_ioctl_handle_t h_ioctl,\r
+ OUT size_t *p_ret_bytes )\r
+{\r
+ al_dev_open_context_t *p_context;\r
+ ual_cep_listen_ioctl_t *p_listen = \r
+ (ual_cep_listen_ioctl_t*)cl_ioctl_in_buf( h_ioctl );\r
+ net32_t* p_cid =\r
+ (net32_t*)cl_ioctl_out_buf( h_ioctl );\r
+\r
+ AL_ENTER( AL_DBG_NDI );\r
+\r
+ p_context = (al_dev_open_context_t*)p_open_context;\r
+\r
+ /* Validate user parameters. */\r
+ if( cl_ioctl_in_size( h_ioctl ) < sizeof(*p_listen) ||\r
+ cl_ioctl_out_size( h_ioctl ) != sizeof(*p_cid) )\r
+ {\r
+ AL_EXIT( AL_DBG_NDI );\r
+ return CL_INVALID_PARAMETER;\r
+ }\r
+\r
+ /* Set the private data compare buffer to our kernel copy. */\r
+ if( p_listen->cep_listen.p_cmp_buf )\r
+ p_listen->cep_listen.p_cmp_buf = p_listen->compare;\r
+\r
+ AL_EXIT( AL_DBG_NDI );\r
+ return ndi_listen_cm( p_context->h_al, &p_listen->cep_listen, p_cid, p_ret_bytes );\r
+}\r
+\r
+static cl_status_t\r
+__ndi_get_req_cm(\r
+ IN void *p_open_context,\r
+ IN cl_ioctl_handle_t h_ioctl,\r
+ OUT size_t *p_ret_bytes )\r
+{\r
+ al_dev_open_context_t *p_context;\r
+ nd_csq_t *p_csq;\r
+ NTSTATUS status;\r
+\r
+ AL_ENTER( AL_DBG_NDI );\r
+\r
+ UNREFERENCED_PARAMETER( p_ret_bytes );\r
+\r
+ p_context = (al_dev_open_context_t*)p_open_context;\r
+\r
+ /* Validate user parameters. */\r
+ if( cl_ioctl_in_size( h_ioctl ) != sizeof(net32_t) ||\r
+ cl_ioctl_out_size( h_ioctl ) != sizeof(net32_t) )\r
+ {\r
+ AL_EXIT( AL_DBG_NDI );\r
+ return CL_INVALID_PARAMETER;\r
+ }\r
+\r
+ /* Validate CID */\r
+ p_csq = (nd_csq_t*)kal_cep_get_context(\r
+ p_context->h_al,\r
+ *(net32_t*)cl_ioctl_in_buf( h_ioctl ),\r
+ nd_cm_handler,\r
+ nd_csq_ref\r
+ );\r
+\r
+ if( p_csq == NULL )\r
+ {\r
+ AL_EXIT( AL_DBG_NDI );\r
+ return STATUS_UNSUCCESSFUL;\r
+ }\r
+\r
+ status = ndi_get_req_cm( p_csq, h_ioctl );\r
+ nd_csq_release( p_csq );\r
+ AL_EXIT( AL_DBG_NDI );\r
+ return status;\r
}\r
\r
cl_status_t\r
h_ioctl->IoStatus.Status = CL_SUCCESS;\r
h_ioctl->IoStatus.Information = 0;\r
\r
+ AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI,\r
+ ("UAL_NDI_NOOP completed with %08x\n", h_ioctl->IoStatus.Status) );\r
IoCompleteRequest( h_ioctl, IO_NETWORK_INCREMENT );\r
cl_status = CL_PENDING;\r
break;\r
+ case UAL_NDI_NOTIFY_DREQ:\r
+ cl_status = __ndi_notify_dreq_cm( p_context, h_ioctl, p_ret_bytes );\r
+ break;\r
+ case UAL_NDI_CANCEL_CM_IRPS:\r
+ cl_status = __ndi_cancel_cm_irps( p_context, h_ioctl, p_ret_bytes );\r
+ break;\r
+ case UAL_NDI_LISTEN_CM:\r
+ cl_status = __ndi_listen_cm( p_context, h_ioctl, p_ret_bytes );\r
+ break;\r
+ case UAL_NDI_GET_REQ_CM:\r
+ cl_status = __ndi_get_req_cm( p_context, h_ioctl, p_ret_bytes );\r
+ break;\r
default:\r
cl_status = CL_INVALID_PARAMETER;\r
break;\r
/* Create a kernel CEP only if we don't already have a CID. */\r
if( cid == AL_INVALID_CID )\r
{\r
- uint64_t cep_context = (ULONG_PTR)context;\r
- if( !DeviceIoControl( g_al_device, UAL_CREATE_CEP, &cep_context,\r
- sizeof(cep_context), &ioctl, sizeof(ioctl), &bytes_ret, NULL ) ||\r
+ if( !DeviceIoControl( g_al_device, UAL_CREATE_CEP, NULL,\r
+ 0, &ioctl, sizeof(ioctl), &bytes_ret, NULL ) ||\r
bytes_ret != sizeof(ioctl) )\r
{\r
__destroy_ucep( p_cep );\r
\r
//TODO: Fail outstanding I/O operations.\r
\r
+ ib_status = ib_deregister_ca( p_ext->hca_ifc.Verbs.guid );\r
+ if( ib_status != IB_SUCCESS ) {\r
+ BUS_PRINT( BUS_DBG_ERROR, ("ib_deregister_ca returned %s.\n",\r
+ ib_get_err_str(ib_status)) );\r
+ }\r
+\r
if ( p_ext->p_port_mgr && p_bfi->p_port_mgr ) {\r
cl_obj_destroy( &p_ext->p_port_mgr->obj );\r
p_ext->p_port_mgr = NULL;\r
}\r
\r
if (p_ext->hca_ifc_taken) {\r
- ib_status = ib_deregister_ca( p_ext->hca_ifc.Verbs.guid );\r
- if( ib_status != IB_SUCCESS ) {\r
- BUS_PRINT( BUS_DBG_ERROR, ("ib_deregister_ca returned %s.\n",\r
- ib_get_err_str(ib_status)) );\r
- }\r
p_ext->hca_ifc.InterfaceHeader.InterfaceDereference(\r
p_ext->hca_ifc.InterfaceHeader.Context);\r
}\r
_INX=.\r
STAMP=stampinf -f $@ -a $(_BUILDARCH) -k $(KMDF_VERSION_MAJOR).$(KMDF_VERSION_MINOR)\r
\r
+!INCLUDE mod_ver.def\r
+\r
$(OBJ_PATH)\$(O)\$(INF_NAME).inf: $(_INX)\$(INF_NAME).inx \r
copy $(_INX)\$(@B).inx $@\r
- $(STAMP)\r
+ $(STAMP) -d * -v $(IB_MAJORVERSION).$(IB_MINORVERSION).$(IB_BUILDVERSION).$(OPENIB_REV)\r
_INX=.\r
!ENDIF\r
\r
-STAMP=stampinf -a $(_BUILDARCH)\r
+STAMP=stampinf -a $(_BUILDARCH) -k $(KMDF_VERSION_MAJOR).$(KMDF_VERSION_MINOR)\r
\r
!INCLUDE mod_ver.def\r
\r
\r
[SourceDisksFiles.x86]\r
mlx4_bus.sys = 1,,\r
-wdfcoinstaller01007.dll = 1,,\r
+wdfcoinstaller$KMDFCOINSTALLERVERSION$.dll = 1,,\r
\r
[SourceDisksFiles.amd64]\r
mlx4_bus.sys = 1,,\r
-wdfcoinstaller01007.dll = 1,,\r
+wdfcoinstaller$KMDFCOINSTALLERVERSION$.dll = 1,,\r
\r
[SourceDisksFiles.ia64]\r
mlx4_bus.sys = 1,,\r
-wdfcoinstaller01007.dll = 1,,\r
+wdfcoinstaller$KMDFCOINSTALLERVERSION$.dll = 1,,\r
\r
;*****************************************\r
; Mlx4Bus Install Section\r
CopyFiles=Wdf_CoInstaller_CopyFiles\r
\r
[Wdf_CoInstaller_AddReg]\r
-HKR,,CoInstallers32,0x00010000, "wdfcoinstaller01007.dll,WdfCoInstaller"\r
+HKR,,CoInstallers32,0x00010000, "wdfcoinstaller$KMDFCOINSTALLERVERSION$.dll,WdfCoInstaller"\r
\r
[Wdf_CoInstaller_CopyFiles]\r
-wdfcoinstaller01007.dll\r
+wdfcoinstaller$KMDFCOINSTALLERVERSION$.dll\r
\r
[MLX4BUS.DDInstall.ntx86.Wdf]\r
KmdfService = mlx4_bus, mlx4_bus_wdfsect\r
KmdfService = mlx4_bus, mlx4_bus_wdfsect\r
\r
[mlx4_bus_wdfsect]\r
-KmdfLibraryVersion = 1.7\r
+KmdfLibraryVersion = $KMDFVERSION$\r
\r
\r
;*****************************************\r
TARGETPATH=..\..\..\..\..\bin\kernel\obj$(BUILD_ALT_DIR)\r
TARGETTYPE=DRIVER\r
\r
-!if $(_NT_TOOLS_VERSION) != 0x700\r
# WDK build only - transform .inx --> .inf adding date & version stamp.\r
# see .\makefile.inc\r
INF_NAME=$(TARGETNAME)\r
INF_TARGET=..\..\..\..\..\bin\kernel\$(O)\$(INF_NAME).inf\r
NTTARGETFILES=$(INF_TARGET)\r
-!endif\r
\r
!if $(FREEBUILD)\r
ENABLE_EVENT_TRACING=1\r
\r
NTTARGETFILE0=mofcomp\r
\r
-KMDF_VERSION=1\r
-\r
-KMDF_MINOR_VERSION=7\r
+KMDF_VERSION_MAJOR=1\r
\r
C_DEFINES=$(C_DEFINES) -DDRIVER -DDEPRECATE_DDK_FUNCTIONS -D__LITTLE_ENDIAN -DUSE_WDM_INTERRUPTS\r
\r
{
struct ib_device *ibdev;
struct mlx4_dev *dev;
- int err = 0;
unsigned long flags;
spin_lock_irqsave(&ibdev->event_handler_lock, &flags);
+
// set device to RESET_PENDING mode
if (!(dev->flags & (MLX4_FLAG_RESET_CLIENT | MLX4_FLAG_RESET_DRIVER))) {
PIO_WORKITEM reset_work;
if (!reset_work) {
spin_unlock_irqrestore(&ibdev->event_handler_lock, flags);
mlx4_err(dev, "mlx4_reset_request IoAllocateWorkItem failed, reset will not be propagated\n");
- err = -EFAULT;
- goto err_workitem;
+ return -EFAULT;
}
event_handler->rsrv_ptr = reset_work;
IoQueueWorkItem( reset_work, card_reset_wi, DelayedWorkQueue, event_handler );
}
-err_workitem:
spin_unlock_irqrestore(&ibdev->event_handler_lock, flags);
- return err;
+
+
+ return 0;
}
int mlx4_reset_cb_register( struct ib_event_handler *event_handler )
TARGETPATH=..\..\..\..\bin\kernel\obj$(BUILD_ALT_DIR)\r
TARGETTYPE=DRIVER\r
\r
-!if $(_NT_TOOLS_VERSION) != 0x700\r
# WDK build only - transform .inx --> .inf adding date & version stamp.\r
# see .\makefile.inc\r
INF_NAME=$(TARGETNAME)\r
INF_TARGET=..\..\..\..\bin\kernel\$(O)\$(INF_NAME).inf\r
NTTARGETFILES=$(INF_TARGET)\r
-!endif\r
\r
!if $(FREEBUILD)\r
ENABLE_EVENT_TRACING=1\r
\r
NTTARGETFILE0=mofcomp\r
\r
-KMDF_VERSION=1\r
+KMDF_VERSION_MAJOR=1\r
\r
C_DEFINES=$(C_DEFINES) -DDRIVER -DDEPRECATE_DDK_FUNCTIONS -D__LITTLE_ENDIAN \r
#-DUSE_WDM_FRAMEWORK \r
&GUID_RDMA_INTERFACE_VERBS ) )\r
{\r
status = __query_ci_ifc( p_dev_obj, p_io_stack );\r
- *p_action = IrpComplete;\r
+ if( !NT_SUCCESS( status ) )\r
+ {\r
+ *p_action = IrpComplete;\r
+ }\r
+ else\r
+ {\r
+ *p_action = IrpSkip;\r
+ }\r
}\r
else\r
{\r
_INX=.\r
!ENDIF\r
\r
-STAMP=stampinf -a $(_BUILDARCH)\r
+STAMP=stampinf -a $(_BUILDARCH) -k $(KMDF_VERSION_MAJOR).$(KMDF_VERSION_MINOR)\r
\r
!INCLUDE mod_ver.def\r
\r
mlx4_hca.sys = 1,,\r
mlx4u.dll = 1,,\r
mlx4ud.dll = 1,,\r
-WdfCoInstaller01007.dll = 1,,\r
+WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll = 1,,\r
ibal.dll=1,,\r
ibald.dll=1,,\r
complib.dll=1,,\r
mlx4ud.dll = 1,,\r
mlx4u32.dll = 1,,\r
mlx4u32d.dll = 1,,\r
-WdfCoInstaller01007.dll = 1,,\r
+WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll = 1,,\r
ibal.dll=1,,\r
ibald.dll=1,,\r
complib.dll=1,,\r
mlx4ud.dll = 1,,\r
mlx4u32.dll = 1,,\r
mlx4u32d.dll = 1,,\r
-WdfCoInstaller01007.dll = 1,,\r
+WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll = 1,,\r
ibal.dll=1,,\r
ibald.dll=1,,\r
complib.dll=1,,\r
CopyFiles=Wdf_CoInstaller_CopyFiles\r
\r
[Wdf_CoInstaller_AddReg]\r
-HKR,,CoInstallers32,0x00010000, "WdfCoInstaller01007.dll,WdfCoInstaller"\r
+HKR,,CoInstallers32,0x00010000, "WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll,WdfCoInstaller"\r
\r
[Wdf_CoInstaller_CopyFiles]\r
-WdfCoInstaller01007.dll\r
+WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll\r
\r
[MLX4HCA.DDInstall.ntx86.Wdf]\r
KmdfService = mlx4_hca,WvWdfSect\r
KmdfService = WinMad,WvWdfSect\r
\r
[WvWdfSect]\r
-KmdfLibraryVersion = 1.7\r
+KmdfLibraryVersion = $KMDFVERSION$\r
\r
\r
;*****************************************\r
TARGETPATH=$(TRUNK)\bin\kernel\obj$(BUILD_ALT_DIR)\r
TARGETTYPE=DRIVER\r
\r
-!if $(_NT_TOOLS_VERSION) != 0x700\r
+KMDF_VERSION_MAJOR=1\r
+\r
# WDK build only - transform .inx --> .inf adding date & version stamp.\r
# see .\makefile.inc\r
INF_NAME=$(TARGETNAME)\r
INF_TARGET=$(TRUNK)\bin\kernel\$(O)\$(INF_NAME).inf\r
NTTARGETFILES=$(INF_TARGET)\r
-!endif\r
\r
!if $(FREEBUILD)\r
ENABLE_EVENT_TRACING=1\r
&GUID_RDMA_INTERFACE_VERBS ) )\r
{\r
status = __query_ci_ifc( p_dev_obj, p_io_stack );\r
- *p_action = IrpComplete;\r
+ if( !NT_SUCCESS( status ) )\r
+ {\r
+ *p_action = IrpComplete;\r
+ }\r
+ else\r
+ {\r
+ *p_action = IrpSkip;\r
+ }\r
}\r
else\r
{\r
_INX=.\r
!ENDIF\r
\r
-STAMP=stampinf -a $(_BUILDARCH)\r
+STAMP=stampinf -a $(_BUILDARCH) -k $(KMDF_VERSION_MAJOR).$(KMDF_VERSION_MINOR)\r
\r
!INCLUDE mod_ver.def\r
\r
winmad.sys = 1,,\r
winmad.dll = 1,,\r
winmadd.dll = 1,,\r
-WdfCoInstaller01007.dll = 1,,\r
+WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll = 1,,\r
\r
\r
[SourceDisksFiles.amd64]\r
winmad.sys = 1,,\r
winmad.dll = 1,,\r
winmadd.dll = 1,,\r
-WdfCoInstaller01007.dll = 1,,\r
+WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll = 1,,\r
\r
[SourceDisksFiles.ia64]\r
mthca.sys=1,,\r
winmad.sys = 1,,\r
winmad.dll = 1,,\r
winmadd.dll = 1,,\r
-WdfCoInstaller01007.dll = 1,,\r
+WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll = 1,,\r
\r
[Manufacturer]\r
%MTL% = HCA.DeviceSection,ntx86,ntamd64,ntia64\r
CopyFiles = Wdf_CoInstaller_CopyFiles\r
\r
[Wdf_CoInstaller_AddReg]\r
-HKR,, CoInstallers32,0x00010000, "WdfCoInstaller01007.dll,WdfCoInstaller"\r
+HKR,, CoInstallers32,0x00010000, "WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll,WdfCoInstaller"\r
\r
[Wdf_CoInstaller_CopyFiles]\r
-WdfCoInstaller01007.dll\r
+WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll\r
\r
[MTHCA.DDInstall.ntx86.Wdf]\r
KmdfService = WinVerbs, WvWdfSect\r
KmdfService = WinMad, WvWdfSect\r
\r
[WvWdfSect]\r
-KmdfLibraryVersion = 1.7\r
+KmdfLibraryVersion = $KMDFVERSION$\r
\r
\r
; ============= Uninstall Section =============\r
{\r
struct _ual_cep_get_pdata_ioctl_in\r
{\r
- uint64_t h_qp;\r
net32_t cid;\r
\r
} in;\r
} ual_cep_get_pdata_ioctl_t;\r
/*\r
* FIELDS\r
-* h_qp\r
-* A handle to the QP to modify.\r
-*\r
* in.cid\r
* The CID for the target CEP.\r
*\r
ib_path_rec_t path;\r
uint64_t h_qp;\r
net64_t guid;\r
+ net32_t cid;\r
uint16_t dst_port;\r
uint8_t resp_res;\r
uint8_t init_depth;\r
} ual_ndi_req_cm_ioctl_in_t;\r
/*\r
* NOTES\r
-* The output parameter is the new QP state (RTS).\r
+* There is no output parameter.\r
*\r
* FIELDS\r
* h_qp\r
* guid\r
* Local port GUID to which to bind to.\r
*\r
+* cid\r
+* CID of the CEP to use for the connection request.\r
+*\r
* dst_port\r
* Destination port number.\r
*\r
*\r
*****/\r
\r
-\r
-/****s* User-mode Access Layer/ual_ndi_rtu_cm_ioctl_in_t\r
-* NAME\r
-* ual_ndi_rtu_cm_ioctl_in_t\r
-*\r
-* DESCRIPTION\r
-* IOCTL structure containing the input parameters \r
-* sending CM RTU response .\r
-*\r
-* SYNOPSIS\r
-*/\r
-typedef struct _ual_ndi_rtu_cm_ioctl_in\r
-{\r
- uint64_t h_qp;\r
-\r
-} ual_ndi_rtu_cm_ioctl_in_t;\r
-/*\r
-* NOTES\r
-* The output parameter is the new QP state (RTS).\r
-*\r
-* FIELDS\r
-* h_qp\r
-* A handle to the QP to modify.\r
-*\r
-* init_depth\r
-* The maximum number of outstanding RDMA read/atomic operations.\r
-*\r
-* resp_res\r
-* The maximum number of RDMA read/atomic operations from the recipient.\r
-*\r
-*****/\r
-\r
/****s* User-mode Access Layer/ual_ndi_modify_qp_ioctl_in_t\r
* NAME\r
* ual_ndi_modify_qp_ioctl_in_t\r
!ENDIF\r
\r
!IF !DEFINED(IB_MINORVERSION)\r
-IB_MINORVERSION=0\r
+IB_MINORVERSION=1\r
!ENDIF\r
\r
# unused build version field\r
rem server RR 1024 2 client RR 2048 2 \r
rem client SR 1024 3 -f server SR 256 3 -f\r
\r
+if "%T%" == "bench" (\r
+ echo %T%: Threads[1] Endpoints[1] transactions[RW, RR, SR], 64K iterations\r
+ set STIME=!DATE! !TIME!\r
+ %DT% -T T -P -t 1 -w 1 -i 65536 -s %S% -D %D% client RW 4096 4 server RW 2048 4 server RR 4096 2 client RR 4096 2 client SR 1024 2 -f server SR 1024 2 -f\r
+ set ETIME=!DATE! !TIME!\r
+ goto xit\r
+)\r
+\r
if "%T%" == "conn" (\r
rem Connectivity test - client sends one buffer with one 4KB segments, one time.\r
rem add '-d' for debug output.\r
echo Simple Connectivity test\r
+ set STIME=!DATE! !TIME!\r
%DT% -T T -s %S% -D %D% -i 1 -t 1 -w 1 client SR 4096 server SR 4096\r
+ set ETIME=!DATE! !TIME!\r
goto xit\r
)\r
\r
if "%T%" == "trans" (\r
echo %T%: Transaction test - 8192 iterations, 1 thread, SR 4KB buffers\r
+ set STIME=!DATE! !TIME!\r
%DT% -T T -s %S% -D %D% -i 8192 -t 1 -w 1 client SR 4096 server SR 4096\r
- echo Finished %T%: Transaction test - 8192 iterations, 1 thread, SR 4KB buffers\r
+ set ETIME=!DATE! !TIME!\r
goto xit\r
)\r
\r
if "%T%" == "transm" (\r
echo %T%: Multiple RW, RR, SR transactions, 4096 iterations\r
+ set STIME=!DATE! !TIME!\r
%DT% -T T -P -t 1 -w 1 -i 4096 -s %S% -D %D% client RW 4096 1 server RW 2048 4 server RR 1024 2 client RR 2048 2 client SR 1024 3 -f server SR 256 3 -f\r
- echo Finished %T%: Multiple RW, RR, SR transactions, 4096 iterations\r
+ set ETIME=!DATE! !TIME!\r
goto xit\r
)\r
\r
if "%T%" == "transt" (\r
echo %T%: Threads[4] Transaction test - 4096 iterations, 1 thread, SR 4KB buffers\r
+ set STIME=!DATE! !TIME!\r
%DT% -T T -s %S% -D %D% -i 4096 -t 4 -w 1 client SR 8192 3 server SR 8192 3\r
- echo Finished %T%: Threads[4] Transaction test - 4096 iterations, 1 thread, SR 4KB buffers\r
+ set ETIME=!DATE! !TIME!\r
goto xit\r
)\r
\r
if "%T%" == "transme" (\r
echo %T%: 1 Thread Endpoints[4] transactions [RW, RR, SR], 4096 iterations\r
+ set STIME=!DATE! !TIME!\r
%DT% -T T -P -t 1 -w 4 -i 4096 -s %S% -D %D% client RW 4096 1 server RW 2048 4 server RR 1024 2 client RR 2048 2 client SR 1024 3 -f server SR 256 3 -f\r
- echo Finished %T%: 1 Thread Endpoints[4] transactions [RW, RR, SR], 4096 iterations\r
+ set ETIME=!DATE! !TIME!\r
goto xit\r
)\r
\r
if "%T%" == "transmet" (\r
echo %T%: Threads[2] Endpoints[4] transactions[RW, RR, SR], 4096 iterations\r
+ set STIME=!DATE! !TIME!\r
%DT% -T T -P -t 2 -w 4 -i 4096 -s %S% -D %D% client RW 4096 1 server RW 2048 4 server RR 1024 2 client RR 2048 2 client SR 1024 3 -f server SR 256 3 -f\r
- echo Finished %T%: Threads[2] Endpoints[4] transactions[RW, RR, SR], 4096 iterations\r
+ set ETIME=!DATE! !TIME!\r
goto xit\r
)\r
\r
if "%T%" == "transmete" (\r
echo %T%: Threads[4] Endpoints[4] transactions[RW, RR, SR], 8192 iterations\r
+ set STIME=!DATE! !TIME!\r
%DT% -T T -P -t 2 -w 4 -i 8192 -s %S% -D %D% client RW 4096 1 server RW 2048 4 server RR 1024 2 client RR 2048 2 client SR 1024 3 -f server SR 256 3 -f\r
- echo Finished %T%: Threads[4] Endpoints[4] transactions[RW, RR, SR], 8192 iterations\r
+ set ETIME=!DATE! !TIME!\r
goto xit\r
)\r
\r
if "%T%" == "EPA" (\r
+ set STIME=!DATE! !TIME!\r
FOR /L %%j IN (2,1,5) DO (\r
FOR /L %%i IN (1,1,5) DO (\r
echo %T%: Multi: Threads[%%j] Endpoints[%%i] Send/Recv test - 4096 iterations, 3 8K segs\r
timeout /T 3\r
)\r
)\r
+ set ETIME=!DATE! !TIME!\r
goto xit\r
)\r
\r
set TH=4\r
set EP=3\r
echo %T%: Multi: Threads[!TH!] endpoints[!EP!] Send/Recv test - 4096 iterations, 3 8K segs\r
+ set STIME=!DATE! !TIME!\r
%DT% -T T -s %S% -D %D% -i 4096 -t !TH! -w !EP! client SR 8192 3 server SR 8192 3\r
- echo %T%: Multi: Threads[!TH!] endpoints[!EP!] Send/Recv test - 4096 iterations, 3 8K segs\r
+ set ETIME=!DATE! !TIME!\r
goto xit\r
)\r
\r
if "%T%" == "threads" (\r
echo %T%: Multi Threaded[6] Send/Recv test - 4096 iterations, 3 8K segs\r
+ set STIME=!DATE! !TIME!\r
%DT% -T T -s %S% -D %D% -i 4096 -t 6 -w 1 client SR 8192 3 server SR 8192 3\r
- echo Finished %T%: Multi Threaded[6] Send/Recv test - 4096 iterations, 3 8K segs\r
+ set ETIME=!DATE! !TIME!\r
goto xit\r
)\r
\r
set TH=5\r
set EP=3\r
echo %T%: Multi: Threads[!TH!] endpoints[!EP!] Send/Recv test - 4096 iterations, 3 8K segs\r
+ set STIME=!DATE! !TIME!\r
%DT% -T T -s %S% -D %D% -i 4096 -t !TH! -w !EP! client SR 8192 3 server SR 8192 3\r
- echo Finished %T%: Multi: Threads[!TH!] endpoints[!EP!] Send/Recv test - 4096 iterations, 3 8K segs\r
+ set ETIME=!DATE! !TIME!\r
goto xit\r
)\r
\r
if "%T%" == "perf" (\r
rem echo Performance test\r
+ set STIME=!DATE! !TIME!\r
%DT% -T P %DBG% -s %S% -D %D% -i 2048 RW 4096 2\r
+ set ETIME=!DATE! !TIME!\r
goto xit\r
)\r
\r
if "%T%" == "rdma-read" (\r
echo %T% 4 32K segs\r
+ set STIME=!DATE! !TIME!\r
%DT% -T P -s %S% -D %D% -i 4096 RR 32768 4\r
- echo Finished %T% 4 32K segs\r
+ set ETIME=!DATE! !TIME!\r
goto xit\r
)\r
\r
if "%T%" == "rdma-write" (\r
echo %T% 4 32K segs\r
+ set STIME=!DATE! !TIME!\r
%DT% -T P -s %S% -D %D% -i 4096 RW 32768 4\r
- echo Finished %T% 4 32K segs\r
+ set ETIME=!DATE! !TIME!\r
goto xit\r
)\r
\r
if "%T%" == "bw" (\r
echo bandwidth 4096 iterations of 2 65K mesgs\r
+ set STIME=!DATE! !TIME!\r
%DT% -T P -s %S% -D %D% -i 4096 -p 16 -m p RW 65536 2 \r
- echo Finished bandwidth 4096 iterations of 2 65K mesgs\r
+ set ETIME=!DATE! !TIME!\r
goto xit\r
)\r
\r
if "%T%" == "latb" (\r
echo latency test - block for completion events\r
+ set STIME=!DATE! !TIME!\r
%DT% -T P -s %S% -D %D% -i 8192 -p 1 -m b RW 4 1\r
+ set ETIME=!DATE! !TIME!\r
goto xit\r
)\r
\r
if "%T%" == "latp" (\r
echo latency test - poll completion events\r
+ set STIME=!DATE! !TIME!\r
%DT% -T P -s %S% -D %D% -i 8192 -p 1 -m p RW 4 1\r
+ set ETIME=!DATE! !TIME!\r
goto xit\r
)\r
\r
if "%T%" == "lim" (\r
echo Resource limit tests\r
+ set STIME=!DATE! !TIME!\r
%DT% -T L -D %D% -w 8 -m 100 limit_ia\r
%DT% -T L -D %D% -w 8 -m 100 limit_pz\r
%DT% -T L -D %D% -w 8 -m 100 limit_evd\r
%DT% -T L -D %D% -w 8 -m 100 limit_psp\r
%DT% -T L -D %D% -w 8 -m 100 limit_lmr\r
%DT% -T L -D %D% -w 8 -m 15 limit_rpost\r
+ set ETIME=!DATE! !TIME!\r
goto xit\r
)\r
\r
echo %T% testing in !LPS! Loops\r
REM rdma-write, read, perf\r
set RT=trans perf threads threadsm transm transt transme transmet transmete rdma-write rdma-read bw EP\r
+ set STIME=!DATE! !TIME!\r
FOR /L %%i IN (1,1,!LPS!) DO (\r
for %%r in ( !RT! ) do (\r
echo loop %%i - start test %%r\r
echo Finished %T% loop %%i of !LPS!\r
if %%i LSS !LPS! timeout /T 8\r
)\r
+ set ETIME=!DATE! !TIME!\r
goto xit\r
)\r
\r
)\r
echo %T% testing in !LPS! Loops\r
REM test units from Nov-'07 OFA interop event\r
+ set STIME=!DATE! !TIME!\r
FOR /L %%i IN (1,1,!LPS!) DO (\r
echo %DT% -T T -s %S% -D %D% -i 4096 -t 1 -w 1 -R BE client SR 256 1 server SR 256 1\r
%DT% -T T -s %S% -D %D% -i 4096 -t 1 -w 1 -R BE client SR 256 1 server SR 256 1\r
echo %%i %T% loops of !LPS! completed.\r
if %%i LSS !LPS! timeout /T 8\r
)\r
+ set ETIME=!DATE! !TIME!\r
goto xit\r
)\r
\r
if "%T%" == "stop" (\r
+ set STIME=!DATE! !TIME!\r
%DT% -T Q -s %S% -D %D%\r
+ set ETIME=!DATE! !TIME!\r
goto xit\r
)\r
\r
echo interop {loopCnt,default=%LPS%} - 2007 OFA interoperability event tests.\r
\r
:xit\r
+if %ERRORLEVEL% EQU 0 (\r
+ echo +\r
+ echo %0 %*\r
+ echo Start %STIME% \r
+ echo End %ETIME%\r
+)\r
ENDLOCAL\r
exit /B %ERRORLEVEL%\r
-@echo off
-rem
-rem Sample DAPLtest server - usage: dt-svr [ -D [dbg-bit-mask] ]
-rem
-
-SETLOCAL
-
-rem set DAT_OVERRIDE=C:\DAT\dat.conf
-
-if EXIST "%ProgramFiles(x86)%" (
- set PF="%ProgramFiles(x86)%\WinOF"
-) else (
- set PF="%ProgramFiles%\WinOF"
-)
-
-rem Program name of dt-svr preferes dapl2test.exe, otherwise prefer dapltest.exe
-if "%0" == "dt-svr" (
- if EXIST %PF%\dapl2test.exe (
- set DT=dapl2test.exe
- set DEV=ibnic0v2
- goto OK
- )
-)
-
-if EXIST %PF%\dapltest.exe (
- set DT=dapltest.exe
- set DEV=ibnic0
- goto OK
-)
-echo Unable to find dapltest.exe or dapl2test.exe?
-exit /B
-
-:OK
-
-rem '-D' enables full debug output
-rem '-D hex-bit-mask' enables selective debug output - see manual.htm for details.
-if "%1" == "-D" (
- if "%2" == "" (
- set X=0xfffff
- ) else (
- set X=%2
- )
-) else ( set X= )
-
-if not "%X%" == "" (
- set DAT_OS_DBG_TYPE=%X%
- set DAT_DBG_LEVEL=%X%
- set DAT_DBG_TYPE=%X%
- set DAPL_DBG_TYPE=%X%
- set DAPL_DBG_LEVEL=%X%
-) else (
- set DAT_DBG_TYPE=1
-)
-
-rem start a dapltest server on the local node - server is waiting for
-rem dapltest 'client' to issue dapltest commands (dt-cli.bat).
-rem Client runs 'dt-cli IP-addr stop' to shutdown this dapltest server.
-
-echo %DT% -T S -d -D %DEV%
-
-%DT% -T S -D %DEV%
-
-echo %0 - %DT% server exit...
-
-ENDLOCAL
-
-@echo on
-exit /B
+@echo off\r
+rem\r
+rem Sample DAPLtest server - usage: dt-svr [ -D [dbg-bit-mask] ]\r
+rem\r
+SETLOCAL\r
+\r
+rem set DAT_OVERRIDE=C:\DAT\dat.conf\r
+\r
+if EXIST "%ProgramFiles(x86)%" (\r
+ set PF="%ProgramFiles(x86)%\WinOF"\r
+) else (\r
+ set PF="%ProgramFiles%\WinOF"\r
+)\r
+\r
+rem Program name of dt-svr preferes dapl2test.exe, otherwise prefer dapltest.exe\r
+if "%0" == "dt-svr" (\r
+ if EXIST %PF%\dapl2test.exe (\r
+ set DT=dapl2test.exe\r
+ set DEV=ibnic0v2\r
+ goto OK\r
+ )\r
+)\r
+\r
+if EXIST %PF%\dapltest.exe (\r
+ set DT=dapltest.exe\r
+ set DEV=ibnic0\r
+ goto OK\r
+)\r
+echo Unable to find dapltest.exe or dapl2test.exe?\r
+exit /B\r
+\r
+:OK\r
+\r
+rem '-D' enables full debug output\r
+rem '-D hex-bit-mask' enables selective debug output - see manual.htm for details.\r
+if "%1" == "-D" (\r
+ if "%2" == "" (\r
+ set X=0xfffff\r
+ ) else (\r
+ set X=%2\r
+ )\r
+) else ( set X= )\r
+\r
+if not "%X%" == "" (\r
+ set DAT_OS_DBG_TYPE=%X%\r
+ set DAT_DBG_LEVEL=%X%\r
+ set DAT_DBG_TYPE=%X%\r
+ set DAPL_DBG_TYPE=%X%\r
+ set DAPL_DBG_LEVEL=%X%\r
+) else (\r
+ set DAT_DBG_TYPE=1\r
+)\r
+\r
+rem start a dapltest server on the local node - server is waiting for\r
+rem dapltest 'client' to issue dapltest commands (dt-cli.bat).\r
+rem Client runs 'dt-cli IP-addr stop' to shutdown this dapltest server.\r
+\r
+echo %DT% -T S -d -D %DEV%\r
+\r
+%DT% -T S -D %DEV%\r
+\r
+echo %0 - %DT% server exit...\r
+\r
+ENDLOCAL\r
+exit /B %ERRORLEVEL%\r
--- /dev/null
+/*\r
+ * Copyright (c) 2008 Microsoft Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ * - Redistributions of source code must retain the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer.\r
+ *\r
+ * - Redistributions in binary form must reproduce the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer in the documentation and/or other materials\r
+ * provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id:$\r
+ */\r
+\r
+#include "NdCq.h"\r
+#include "NdAdapter.h"\r
+#include "NdMw.h"\r
+#include "NdEndpoint.h"\r
+#include "NdProv.h"\r
+#include "NdMr.h"\r
+#include "NdListen.h"\r
+#include "NdConnector.h"\r
+\r
+#include "al_dev.h"\r
+#pragma warning( push, 3 )\r
+#include "winternl.h"\r
+#pragma warning( pop )\r
+\r
+#include <assert.h>\r
+#include <limits.h>\r
+#include <strsafe.h>\r
+\r
+#if defined(EVENT_TRACING)\r
+#ifdef offsetof\r
+#undef offsetof\r
+#endif\r
+#include "NdAdapter.tmh"\r
+#endif\r
+\r
+\r
+namespace NetworkDirect\r
+{\r
+\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// HPC Pack 2008 Beta 2 SPI\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+\r
+CAdapter::CAdapter(void) :\r
+ m_nRef( 1 ),\r
+ m_hSync( INVALID_HANDLE_VALUE ),\r
+ m_hAsync( INVALID_HANDLE_VALUE ),\r
+ m_hCa( 0 ),\r
+ m_hPd( 0 ),\r
+ m_uCa( NULL ),\r
+ m_uPd( NULL ),\r
+ m_pParent( NULL )\r
+{\r
+ m_Ifc.h_uvp_lib = NULL;\r
+}\r
+\r
+CAdapter::~CAdapter(void)\r
+{\r
+ if( m_hPd )\r
+ DeallocPd();\r
+\r
+ if( m_hCa )\r
+ CloseCa();\r
+\r
+ if( m_hSync != INVALID_HANDLE_VALUE )\r
+ CloseHandle( m_hSync );\r
+\r
+ if( m_hAsync != INVALID_HANDLE_VALUE )\r
+ CloseHandle( m_hAsync );\r
+\r
+ if( m_pParent )\r
+ m_pParent->Release();\r
+}\r
+\r
+HRESULT CAdapter::Initialize(\r
+ CProvider* pParent,\r
+ const struct sockaddr* pAddr,\r
+ const IBAT_PORT_RECORD* pPortRecord )\r
+{\r
+ m_pParent = pParent;\r
+ m_pParent->AddRef();\r
+\r
+ HRESULT hr = OpenFiles();\r
+ if( FAILED( hr ) )\r
+ return hr;\r
+\r
+ hr = OpenCa( pPortRecord->CaGuid );\r
+ if( FAILED( hr ) )\r
+ return hr;\r
+\r
+ hr = AllocPd();\r
+ if( FAILED( hr ) )\r
+ return hr;\r
+\r
+ m_PortNum = pPortRecord->PortNum;\r
+ m_PortGuid = pPortRecord->PortGuid;\r
+\r
+ switch( pAddr->sa_family )\r
+ {\r
+ case AF_INET:\r
+ RtlCopyMemory( &m_Addr.v4, pAddr, sizeof(m_Addr.v4) );\r
+ ND_PRINT( TRACE_LEVEL_INFORMATION, ND_DBG_NDI,\r
+ ("Local address: IP %#x, port %#hx\n", \r
+ cl_hton32(m_Addr.v4.sin_addr.S_un.S_addr), cl_hton16(m_Addr.v4.sin_port) ) );\r
+ break;\r
+ case AF_INET6:\r
+ RtlCopyMemory( &m_Addr.v6, pAddr, sizeof(m_Addr.v6) );\r
+ break;\r
+ default:\r
+ return ND_INVALID_ADDRESS;\r
+ }\r
+ return S_OK;\r
+}\r
+\r
+HRESULT CAdapter::Create(\r
+ CProvider* pParent,\r
+ const struct sockaddr* pAddr,\r
+ const IBAT_PORT_RECORD* pPortRecord,\r
+ __out INDAdapter** ppAdapter\r
+ )\r
+{\r
+ CAdapter* pAdapter = new CAdapter();\r
+ if( pAdapter == NULL )\r
+ return ND_NO_MEMORY;\r
+\r
+ HRESULT hr = pAdapter->Initialize( pParent, pAddr, pPortRecord );\r
+ if( FAILED( hr ) )\r
+ {\r
+ delete pAdapter;\r
+ return hr;\r
+ }\r
+\r
+ *ppAdapter = pAdapter;\r
+ return ND_SUCCESS;\r
+}\r
+\r
+// IUnknown overrides.\r
+HRESULT CAdapter::QueryInterface(\r
+ const IID &riid,\r
+ LPVOID FAR *ppvObj )\r
+{\r
+ if( IsEqualIID( riid, IID_IUnknown ) )\r
+ {\r
+ *ppvObj = this;\r
+ return S_OK;\r
+ }\r
+\r
+ if( IsEqualIID( riid, IID_INDAdapter ) )\r
+ {\r
+ *ppvObj = this;\r
+ return S_OK;\r
+ }\r
+\r
+ return E_NOINTERFACE;\r
+}\r
+\r
+ULONG CAdapter::AddRef(void)\r
+{\r
+ return InterlockedIncrement( &m_nRef );\r
+}\r
+\r
+ULONG CAdapter::Release(void)\r
+{\r
+ ULONG ref = InterlockedDecrement( &m_nRef );\r
+ if( ref == 0 )\r
+ delete this;\r
+\r
+ return ref;\r
+}\r
+\r
+// *** INDOverlapped methods ***\r
+HRESULT CAdapter::CancelOverlappedRequests(void)\r
+{\r
+ // Memory registration IOCTLs can't be cancelled.\r
+ return S_OK;\r
+}\r
+\r
+HRESULT CAdapter::GetOverlappedResult(\r
+ __inout OVERLAPPED *pOverlapped,\r
+ __out SIZE_T *pNumberOfBytesTransferred,\r
+ __in BOOL bWait\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ *pNumberOfBytesTransferred = 0;\r
+ ::GetOverlappedResult(\r
+ m_hAsync,\r
+ pOverlapped,\r
+ (DWORD*)pNumberOfBytesTransferred,\r
+ bWait );\r
+ return (HRESULT)pOverlapped->Internal;\r
+}\r
+\r
+// INDAdapter overrides.\r
+HANDLE CAdapter::GetFileHandle(void)\r
+{\r
+ return m_hAsync;\r
+}\r
+\r
+HRESULT CAdapter::Query(\r
+ __in DWORD VersionRequested,\r
+ __out_bcount_part_opt(*pBufferSize, *pBufferSize) ND_ADAPTER_INFO* pInfo,\r
+ __inout_opt SIZE_T* pBufferSize\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ if( VersionRequested != 1 )\r
+ return ND_NOT_SUPPORTED;\r
+\r
+ if( *pBufferSize < sizeof(ND_ADAPTER_INFO1) )\r
+ {\r
+ *pBufferSize = sizeof(ND_ADAPTER_INFO1);\r
+ return ND_BUFFER_OVERFLOW;\r
+ }\r
+\r
+ ib_ca_attr_t* pAttr = NULL;\r
+ DWORD size = 0;\r
+ HRESULT hr = QueryCa( pAttr, &size );\r
+ if( hr != ND_BUFFER_OVERFLOW )\r
+ return hr;\r
+\r
+ pAttr = (ib_ca_attr_t*)HeapAlloc( GetProcessHeap(), 0, size );\r
+ if( !pAttr )\r
+ return ND_UNSUCCESSFUL;\r
+\r
+ hr = QueryCa( pAttr, &size );\r
+ if( FAILED( hr ) )\r
+ {\r
+ HeapFree( GetProcessHeap(), 0, pAttr );\r
+ return hr;\r
+ }\r
+\r
+ pInfo->MaxInboundSge = pAttr->max_sges;\r
+ pInfo->MaxInboundRequests = pAttr->max_wrs;\r
+ pInfo->MaxInboundLength = INT_MAX;\r
+ pInfo->MaxOutboundSge = pAttr->max_sges;\r
+ pInfo->MaxOutboundRequests = pAttr->max_wrs;\r
+ pInfo->MaxOutboundLength = INT_MAX;\r
+ pInfo->MaxInboundReadLimit = pAttr->max_qp_resp_res;\r
+ pInfo->MaxOutboundReadLimit = pAttr->max_qp_init_depth;\r
+ pInfo->MaxCqEntries = pAttr->max_cqes;\r
+#ifndef SIZE_MAX\r
+#ifdef _WIN64\r
+#define SIZE_MAX _UI64_MAX\r
+#else\r
+#define SIZE_MAX UINT_MAX\r
+#endif\r
+#endif\r
+ if( pAttr->init_region_size > SIZE_MAX )\r
+ pInfo->MaxRegistrationSize = SIZE_MAX;\r
+ else\r
+ pInfo->MaxRegistrationSize = (SIZE_T)pAttr->init_region_size;\r
+ pInfo->MaxWindowSize = pInfo->MaxRegistrationSize;\r
+ pInfo->LargeRequestThreshold = 16 * 1024;\r
+ pInfo->MaxCallerData = 56;\r
+ pInfo->MaxCalleeData = 148;\r
+ *pBufferSize = sizeof(ND_ADAPTER_INFO1);\r
+ return S_OK;\r
+}\r
+\r
+HRESULT CAdapter::Control(\r
+ __in DWORD IoControlCode,\r
+ __in_bcount_opt(InBufferSize) const void* pInBuffer,\r
+ __in SIZE_T InBufferSize,\r
+ __out_bcount_opt(OutBufferSize) void* pOutBuffer,\r
+ __in SIZE_T OutBufferSize,\r
+ __out SIZE_T* pBytesReturned,\r
+ __inout OVERLAPPED* pOverlapped\r
+ )\r
+{\r
+ UNREFERENCED_PARAMETER( IoControlCode );\r
+ UNREFERENCED_PARAMETER( pInBuffer );\r
+ UNREFERENCED_PARAMETER( InBufferSize );\r
+ UNREFERENCED_PARAMETER( pOutBuffer );\r
+ UNREFERENCED_PARAMETER( OutBufferSize );\r
+ UNREFERENCED_PARAMETER( pBytesReturned );\r
+ UNREFERENCED_PARAMETER( pOverlapped );\r
+ \r
+ return ND_NOT_SUPPORTED;\r
+}\r
+\r
+HRESULT CAdapter::CreateCompletionQueue(\r
+ __in SIZE_T nEntries,\r
+ __deref_out INDCompletionQueue** ppCq\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ CCq* pCq = new CCq();\r
+ if( pCq == NULL )\r
+ return ND_NO_MEMORY;\r
+\r
+ HRESULT hr = pCq->Initialize( this, nEntries );\r
+ if( FAILED(hr) )\r
+ {\r
+ delete pCq;\r
+ return hr;\r
+ }\r
+\r
+ *ppCq = pCq;\r
+ return S_OK;\r
+}\r
+\r
+\r
+HRESULT CAdapter::RegisterMemory(\r
+ __in_bcount(BufferSize) const void* pBuffer,\r
+ __in SIZE_T BufferSize,\r
+ __inout OVERLAPPED* pOverlapped,\r
+ __deref_out ND_MR_HANDLE* phMr\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ /* Get a MR tracking structure. */\r
+ CMr* pMr = new CMr();\r
+ if( pMr == NULL )\r
+ return ND_NO_MEMORY;\r
+\r
+ pMr->pBase = (const char*)pBuffer;\r
+\r
+ if( BufferSize > ULONG_MAX )\r
+ return ND_INVALID_PARAMETER_2;\r
+ pMr->Length = (uint32_t)BufferSize;\r
+\r
+ /* Clear the mr_ioctl */\r
+ pMr->mr_ioctl.in.h_pd = m_hPd;\r
+ pMr->mr_ioctl.in.mem_create.vaddr_padding = (ULONG_PTR)pBuffer;\r
+ pMr->mr_ioctl.in.mem_create.length = BufferSize;\r
+ // No support for MWs yet, so simulate it.\r
+ pMr->mr_ioctl.in.mem_create.access_ctrl =\r
+ IB_AC_RDMA_READ | IB_AC_RDMA_WRITE | IB_AC_LOCAL_WRITE;\r
+\r
+ *phMr = (ND_MR_HANDLE)pMr;\r
+ //\r
+ // We must issue the IOCTL on the synchronous file handle.\r
+ // If the user bound the async file handle to an I/O completion port\r
+ // DeviceIoControl could succeed, but not return data, so the MR\r
+ // wouldn't be updated.\r
+ //\r
+ // We use a second IOCTL to complet the user's overlapped.\r
+ //\r
+ DWORD bytes_ret = 0;\r
+ BOOL ret = DeviceIoControl( m_hSync, UAL_REG_MR,\r
+ &pMr->mr_ioctl.in, sizeof(pMr->mr_ioctl.in),\r
+ &pMr->mr_ioctl.out, sizeof(pMr->mr_ioctl.out),\r
+ &bytes_ret, NULL );\r
+ if( !ret )\r
+ {\r
+ CL_ASSERT( GetLastError() != ERROR_IO_PENDING );\r
+\r
+ delete pMr;\r
+ return ND_UNSUCCESSFUL;\r
+ }\r
+ if( bytes_ret != sizeof(pMr->mr_ioctl.out) || \r
+ pMr->mr_ioctl.out.status != IB_SUCCESS )\r
+ {\r
+ delete pMr;\r
+ return ND_UNSUCCESSFUL;\r
+ }\r
+\r
+ //\r
+ // The registration succeeded. Now issue the user's IOCTL.\r
+ //\r
+ pOverlapped->Internal = ND_PENDING;\r
+ HRESULT hr = NtDeviceIoControlFile(\r
+ m_hAsync,\r
+ pOverlapped->hEvent,\r
+ NULL,\r
+ (ULONG_PTR)pOverlapped->hEvent & 1 ? NULL : pOverlapped,\r
+ (IO_STATUS_BLOCK*)&pOverlapped->Internal,\r
+ UAL_NDI_NOOP,\r
+ NULL,\r
+ 0,\r
+ NULL,\r
+ 0 );\r
+\r
+ if( hr != ND_PENDING && hr != ND_SUCCESS )\r
+ {\r
+ delete pMr;\r
+ return hr;\r
+ }\r
+\r
+ AddRef();\r
+ return ND_SUCCESS;\r
+}\r
+\r
+HRESULT CAdapter::DeregisterMemory(\r
+ __in ND_MR_HANDLE hMr,\r
+ __inout OVERLAPPED* pOverlapped\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ CMr* pMr = (CMr*)hMr;\r
+\r
+ //\r
+ // We must issue the IOCTL on the synchronous file handle.\r
+ // If the user bound the async file handle to an I/O completion port\r
+ // DeviceIoControl could succeed, but not return data, so the MR\r
+ // wouldn't be updated.\r
+ //\r
+ // We use a second IOCTL to complet the user's overlapped.\r
+ //\r
+ DWORD bytes_ret = 0;\r
+ BOOL ret = DeviceIoControl( m_hSync, UAL_DEREG_MR,\r
+ &pMr->mr_ioctl.out.h_mr, sizeof(pMr->mr_ioctl.out.h_mr),\r
+ &pMr->mr_ioctl.out.status, sizeof(pMr->mr_ioctl.out.status),\r
+ &bytes_ret, NULL );\r
+ if( !ret )\r
+ {\r
+ CL_ASSERT( GetLastError() != ERROR_IO_PENDING );\r
+ pMr->mr_ioctl.out.status = IB_ERROR;\r
+ }\r
+ if( bytes_ret != sizeof(pMr->mr_ioctl.out.status) )\r
+ return ND_UNSUCCESSFUL;\r
+\r
+ switch( pMr->mr_ioctl.out.status )\r
+ {\r
+ case IB_SUCCESS:\r
+ {\r
+ delete pMr;\r
+ Release();\r
+\r
+ //\r
+ // The deregistration succeeded. Now issue the user's IOCTL.\r
+ //\r
+ pOverlapped->Internal = ND_PENDING;\r
+ HRESULT hr = NtDeviceIoControlFile(\r
+ m_hAsync,\r
+ pOverlapped->hEvent,\r
+ NULL,\r
+ (ULONG_PTR)pOverlapped->hEvent & 1 ? NULL : pOverlapped,\r
+ (IO_STATUS_BLOCK*)&pOverlapped->Internal,\r
+ UAL_NDI_NOOP,\r
+ NULL,\r
+ 0,\r
+ NULL,\r
+ 0 );\r
+ CL_ASSERT( SUCCEEDED( hr ) );\r
+ return hr;\r
+ }\r
+ case IB_RESOURCE_BUSY:\r
+ return ND_DEVICE_BUSY;\r
+\r
+ default:\r
+ return ND_UNSUCCESSFUL;\r
+ }\r
+}\r
+\r
+HRESULT CAdapter::CreateMemoryWindow(\r
+ __out ND_RESULT* pInvalidateResult,\r
+ __deref_out INDMemoryWindow** ppMw\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ CMw* pMw = new CMw();\r
+ if( pMw == NULL )\r
+ return ND_NO_MEMORY;\r
+\r
+ HRESULT hr = pMw->Initialize( this, pInvalidateResult );\r
+ if( FAILED(hr) )\r
+ {\r
+ delete pMw;\r
+ return hr;\r
+ }\r
+\r
+ *ppMw = pMw;\r
+ return S_OK;\r
+}\r
+\r
+HRESULT CAdapter::CreateConnector(\r
+ __deref_out INDConnector** ppConnector\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ return CConnector::Create( this, ppConnector );\r
+}\r
+\r
+HRESULT CAdapter::Listen(\r
+ __in SIZE_T Backlog,\r
+ __in INT Protocol,\r
+ __in USHORT Port,\r
+ __out_opt USHORT* pAssignedPort,\r
+ __deref_out INDListen** ppListen\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ return CListen::Create(\r
+ this,\r
+ Backlog,\r
+ Protocol,\r
+ Port,\r
+ pAssignedPort,\r
+ ppListen\r
+ );\r
+}\r
+\r
+HRESULT CAdapter::GetLocalAddress(\r
+ __out_bcount_part(*pAddressLength, *pAddressLength) struct sockaddr *pAddr,\r
+ __inout SIZE_T *pAddressLength )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ switch( m_Addr.v4.sin_family )\r
+ {\r
+ case AF_INET:\r
+ if( *pAddressLength < sizeof(struct sockaddr_in) )\r
+ {\r
+ *pAddressLength = sizeof(struct sockaddr_in);\r
+ return ND_BUFFER_OVERFLOW;\r
+ }\r
+ *(struct sockaddr_in*)pAddr = m_Addr.v4;\r
+ ND_PRINT( TRACE_LEVEL_INFORMATION, ND_DBG_NDI,\r
+ ("Local address: IP %#x, port %#hx\n", \r
+ cl_hton32(m_Addr.v4.sin_addr.S_un.S_addr), cl_hton16(m_Addr.v4.sin_port) ) );\r
+ return S_OK;\r
+\r
+ case AF_INET6:\r
+ if( *pAddressLength < sizeof(struct sockaddr_in6) )\r
+ {\r
+ *pAddressLength = sizeof(struct sockaddr_in6);\r
+ return ND_BUFFER_OVERFLOW;\r
+ }\r
+ *(struct sockaddr_in6*)pAddr = m_Addr.v6;\r
+ return S_OK;\r
+\r
+ default:\r
+ return ND_INVALID_ADDRESS;\r
+ }\r
+}\r
+\r
+HRESULT CAdapter::OpenFiles(void)\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ /* First open the kernel device. */\r
+ CL_ASSERT( m_hSync == INVALID_HANDLE_VALUE );\r
+ m_hSync = CreateFile(\r
+ "\\\\.\\ibal",\r
+ GENERIC_READ | GENERIC_WRITE,\r
+ FILE_SHARE_READ | FILE_SHARE_WRITE,\r
+ NULL,\r
+ OPEN_EXISTING,\r
+ 0,\r
+ NULL\r
+ );\r
+ if( m_hSync == INVALID_HANDLE_VALUE )\r
+ return ND_UNSUCCESSFUL;\r
+\r
+ // Now issue the BIND IOCTL which associates us as a client.\r
+ ULONG ver = AL_IOCTL_VERSION;\r
+ DWORD BytesRet;\r
+ BOOL fSuccess = DeviceIoControl(\r
+ m_hSync,\r
+ UAL_BIND,\r
+ &ver,\r
+ sizeof(ver),\r
+ NULL,\r
+ 0,\r
+ &BytesRet,\r
+ NULL\r
+ );\r
+ if( fSuccess != TRUE )\r
+ return ND_UNSUCCESSFUL;\r
+\r
+ // Now create the async file.\r
+ m_hAsync = CreateFile(\r
+ "\\\\.\\ibal",\r
+ GENERIC_READ | GENERIC_WRITE,\r
+ FILE_SHARE_READ | FILE_SHARE_WRITE,\r
+ NULL,\r
+ OPEN_EXISTING,\r
+ FILE_FLAG_OVERLAPPED,\r
+ NULL\r
+ );\r
+ if( m_hAsync == INVALID_HANDLE_VALUE )\r
+ return ND_UNSUCCESSFUL;\r
+\r
+ /*\r
+ * Send an IOCTL down on the main file handle to bind this file\r
+ * handle with our proxy context.\r
+ */\r
+ UINT64 hFile = (ULONG_PTR)m_hAsync;\r
+ fSuccess = DeviceIoControl(\r
+ m_hSync,\r
+ UAL_BIND_ND,\r
+ &hFile,\r
+ sizeof(hFile),\r
+ NULL,\r
+ 0,\r
+ &BytesRet,\r
+ NULL\r
+ );\r
+ if( fSuccess != TRUE )\r
+ return ND_UNSUCCESSFUL;\r
+\r
+ return S_OK;\r
+}\r
+\r
+HRESULT CAdapter::OpenCa(\r
+ __in UINT64 CaGuid )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ ual_get_uvp_name_ioctl_t al_ioctl;\r
+\r
+ /* Initialize assuming no user-mode support */\r
+ cl_memclr( &al_ioctl, sizeof(al_ioctl) );\r
+ cl_memclr( &m_Ifc, sizeof(m_Ifc) );\r
+\r
+ /* init with the guid */\r
+ m_Ifc.guid = CaGuid;\r
+\r
+ DWORD BytesRet;\r
+ BOOL fSuccess = DeviceIoControl(\r
+ m_hSync,\r
+ UAL_GET_VENDOR_LIBCFG,\r
+ &CaGuid, sizeof(CaGuid),\r
+ &al_ioctl.out, sizeof(al_ioctl.out),\r
+ &BytesRet,\r
+ NULL\r
+ );\r
+\r
+ if( fSuccess != TRUE || BytesRet != sizeof(al_ioctl.out) )\r
+ return ND_INSUFFICIENT_RESOURCES;\r
+\r
+ if( !strlen( al_ioctl.out.uvp_lib_name ) )\r
+ {\r
+ /* Vendor does not implement user-mode library */\r
+ return ND_NOT_SUPPORTED;\r
+ }\r
+\r
+ /*\r
+ * The vendor supports a user-mode library\r
+ * open the library and get the interfaces supported\r
+ */\r
+#if DBG\r
+ HRESULT hr = StringCbCatA( al_ioctl.out.uvp_lib_name, 32, "d.dll" );\r
+#else\r
+ HRESULT hr = StringCbCatA( al_ioctl.out.uvp_lib_name, 32, ".dll" );\r
+#endif\r
+ if( FAILED( hr ) )\r
+ return ND_NOT_SUPPORTED;\r
+\r
+ m_Ifc.h_uvp_lib = LoadLibrary( al_ioctl.out.uvp_lib_name );\r
+ if( m_Ifc.h_uvp_lib == NULL )\r
+ return ND_NOT_SUPPORTED;\r
+\r
+ uvp_get_interface_t pfn_uvp_ifc = (uvp_get_interface_t)GetProcAddress(\r
+ m_Ifc.h_uvp_lib,\r
+ "uvp_get_interface"\r
+ );\r
+\r
+ if( pfn_uvp_ifc == NULL )\r
+ return ND_NOT_SUPPORTED;\r
+\r
+ /* Query the vendor-supported user-mode functions */\r
+ pfn_uvp_ifc( IID_UVP, &m_Ifc.user_verbs );\r
+\r
+ ual_open_ca_ioctl_t ca_ioctl;\r
+ cl_memclr( &ca_ioctl, sizeof(ca_ioctl) );\r
+\r
+ /* Pre call to the UVP library */\r
+ ib_api_status_t status = IB_ERROR;\r
+ if( m_Ifc.user_verbs.pre_open_ca )\r
+ {\r
+ status = m_Ifc.user_verbs.pre_open_ca(\r
+ CaGuid,\r
+ &ca_ioctl.in.umv_buf,\r
+ (ib_ca_handle_t*)(ULONG_PTR)&m_uCa\r
+ );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ CL_ASSERT( status != IB_VERBS_PROCESSING_DONE );\r
+ return ND_INSUFFICIENT_RESOURCES;\r
+ }\r
+ }\r
+\r
+ ca_ioctl.in.guid = CaGuid;\r
+ ca_ioctl.in.context = (ULONG_PTR)this;\r
+\r
+ fSuccess = DeviceIoControl(\r
+ m_hSync,\r
+ UAL_OPEN_CA,\r
+ &ca_ioctl.in,\r
+ sizeof(ca_ioctl.in),\r
+ &ca_ioctl.out,\r
+ sizeof(ca_ioctl.out),\r
+ &BytesRet,\r
+ NULL\r
+ );\r
+\r
+ if( fSuccess != TRUE || BytesRet != sizeof(ca_ioctl.out) )\r
+ {\r
+ status = IB_ERROR;\r
+ }\r
+ else\r
+ {\r
+ status = ca_ioctl.out.status;\r
+ m_hCa = ca_ioctl.out.h_ca;\r
+ }\r
+\r
+ /* Post uvp call */\r
+ if( m_Ifc.user_verbs.post_open_ca )\r
+ {\r
+ status = m_Ifc.user_verbs.post_open_ca(\r
+ CaGuid,\r
+ status,\r
+ (ib_ca_handle_t*)(ULONG_PTR)&m_uCa,\r
+ &ca_ioctl.out.umv_buf );\r
+ }\r
+\r
+ // TODO: Does the UVP need a query call to succeed?\r
+ // IBAL always does this internally.\r
+\r
+ return (status == IB_SUCCESS? S_OK : ND_INSUFFICIENT_RESOURCES );\r
+}\r
+\r
+HRESULT CAdapter::QueryCa(\r
+ __out_bcount(*pSize) ib_ca_attr_t* pAttr,\r
+ __inout DWORD* pSize )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ ual_query_ca_ioctl_t ca_ioctl;\r
+\r
+ cl_memclr( &ca_ioctl, sizeof(ca_ioctl) );\r
+\r
+ ca_ioctl.in.h_ca = m_hCa;\r
+ ca_ioctl.in.p_ca_attr = (ULONG_PTR)pAttr;\r
+ ca_ioctl.in.byte_cnt = *pSize;\r
+\r
+ /* Call the uvp pre call if the vendor library provided a valid ca handle */\r
+ ib_api_status_t status;\r
+ if( m_uCa && m_Ifc.user_verbs.pre_query_ca )\r
+ {\r
+ /* Pre call to the UVP library */\r
+ status = m_Ifc.user_verbs.pre_query_ca(\r
+ m_uCa, pAttr, *pSize, &ca_ioctl.in.umv_buf );\r
+ if( status != IB_SUCCESS )\r
+ return ND_UNSUCCESSFUL;\r
+ }\r
+\r
+ DWORD BytesRet;\r
+ BOOL fSuccess = DeviceIoControl(\r
+ m_hSync,\r
+ UAL_QUERY_CA,\r
+ &ca_ioctl.in,\r
+ sizeof(ca_ioctl.in),\r
+ &ca_ioctl.out,\r
+ sizeof(ca_ioctl.out),\r
+ &BytesRet,\r
+ NULL\r
+ );\r
+ if( fSuccess != TRUE || BytesRet != sizeof(ca_ioctl.out) )\r
+ {\r
+ status = IB_ERROR;\r
+ }\r
+ else\r
+ {\r
+ *pSize = ca_ioctl.out.byte_cnt;\r
+ status = ca_ioctl.out.status;\r
+ }\r
+\r
+ /* The attributes, if any, will be directly copied by proxy */\r
+ /* Post uvp call */\r
+ if( m_uCa && m_Ifc.user_verbs.post_query_ca )\r
+ {\r
+ m_Ifc.user_verbs.post_query_ca( m_uCa,\r
+ status, pAttr, ca_ioctl.out.byte_cnt, &ca_ioctl.out.umv_buf );\r
+ }\r
+\r
+ switch( status )\r
+ {\r
+ case IB_SUCCESS:\r
+ return S_OK;\r
+ case IB_INSUFFICIENT_MEMORY:\r
+ return ND_BUFFER_OVERFLOW;\r
+ default:\r
+ return ND_INSUFFICIENT_RESOURCES;\r
+ }\r
+}\r
+\r
+void CAdapter::CloseCa(void)\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ ib_api_status_t status;\r
+\r
+ /* Call the uvp pre call if the vendor library provided a valid ca handle */\r
+ if( m_uCa && m_Ifc.user_verbs.pre_close_ca )\r
+ {\r
+ /* Pre call to the UVP library */\r
+ status = m_Ifc.user_verbs.pre_close_ca( m_uCa );\r
+ if( status != IB_SUCCESS )\r
+ return;\r
+ }\r
+\r
+ DWORD BytesRet;\r
+ BOOL fSuccess = DeviceIoControl(\r
+ m_hSync,\r
+ UAL_CLOSE_CA,\r
+ &m_hCa,\r
+ sizeof(m_hCa),\r
+ &status,\r
+ sizeof(status),\r
+ &BytesRet,\r
+ NULL\r
+ );\r
+\r
+ if( fSuccess != TRUE || BytesRet != sizeof(status) )\r
+ status = IB_ERROR;\r
+\r
+ if( m_uCa && m_Ifc.user_verbs.post_close_ca )\r
+ m_Ifc.user_verbs.post_close_ca( m_uCa, status );\r
+\r
+ if( m_Ifc.h_uvp_lib )\r
+ FreeLibrary( m_Ifc.h_uvp_lib );\r
+\r
+ m_hCa = 0;\r
+}\r
+\r
+HRESULT CAdapter::AllocPd(void)\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ /* Clear the pd_ioctl */\r
+ ual_alloc_pd_ioctl_t pd_ioctl;\r
+ cl_memclr( &pd_ioctl, sizeof(pd_ioctl) );\r
+\r
+ /* Pre call to the UVP library */\r
+ ib_api_status_t status;\r
+ if( m_uCa && m_Ifc.user_verbs.pre_allocate_pd )\r
+ {\r
+ status = m_Ifc.user_verbs.pre_allocate_pd(\r
+ m_uCa,\r
+ &pd_ioctl.in.umv_buf,\r
+ (ib_pd_handle_t*)(ULONG_PTR)&m_uPd\r
+ );\r
+ if( status != IB_SUCCESS )\r
+ return ND_INSUFFICIENT_RESOURCES;\r
+ }\r
+\r
+ pd_ioctl.in.h_ca = m_hCa;\r
+ pd_ioctl.in.type = IB_PDT_NORMAL;\r
+ pd_ioctl.in.context = (ULONG_PTR)this;\r
+\r
+ DWORD BytesRet;\r
+ BOOL fSuccess = DeviceIoControl(\r
+ m_hSync,\r
+ UAL_ALLOC_PD,\r
+ &pd_ioctl.in,\r
+ sizeof(pd_ioctl.in),\r
+ &pd_ioctl.out,\r
+ sizeof(pd_ioctl.out),\r
+ &BytesRet,\r
+ NULL\r
+ );\r
+\r
+ if( fSuccess != TRUE || BytesRet != sizeof(pd_ioctl.out) )\r
+ {\r
+ status = IB_ERROR;\r
+ }\r
+ else\r
+ {\r
+ status = pd_ioctl.out.status;\r
+ if( pd_ioctl.out.status == IB_SUCCESS )\r
+ m_hPd = pd_ioctl.out.h_pd;\r
+ }\r
+\r
+ /* Post uvp call */\r
+ if( m_uCa && m_Ifc.user_verbs.post_allocate_pd )\r
+ {\r
+ m_Ifc.user_verbs.post_allocate_pd(\r
+ m_uCa,\r
+ status,\r
+ (ib_pd_handle_t*)(ULONG_PTR)&m_uPd,\r
+ &pd_ioctl.out.umv_buf );\r
+ }\r
+\r
+ return (status == IB_SUCCESS? S_OK : ND_INSUFFICIENT_RESOURCES);\r
+}\r
+\r
+void CAdapter::DeallocPd(void)\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ ib_api_status_t status;\r
+\r
+ /* Call the uvp pre call if the vendor library provided a valid ca handle */\r
+ if( m_uPd && m_Ifc.user_verbs.pre_deallocate_pd )\r
+ {\r
+ /* Pre call to the UVP library */\r
+ status = m_Ifc.user_verbs.pre_deallocate_pd( m_uPd );\r
+ if( status != IB_SUCCESS )\r
+ return;\r
+ }\r
+\r
+ DWORD BytesRet;\r
+ BOOL fSuccess = DeviceIoControl(\r
+ m_hSync,\r
+ UAL_DEALLOC_PD,\r
+ &m_hPd,\r
+ sizeof(m_hPd),\r
+ &status,\r
+ sizeof(status),\r
+ &BytesRet,\r
+ NULL\r
+ );\r
+\r
+ if( fSuccess == FALSE || BytesRet != sizeof(status) )\r
+ status = IB_ERROR;\r
+\r
+ /* Call vendor's post_close ca */\r
+ if( m_uPd && m_Ifc.user_verbs.post_deallocate_pd )\r
+ m_Ifc.user_verbs.post_deallocate_pd( m_uPd, status );\r
+\r
+ m_hPd = 0;\r
+}\r
+\r
+} // namespace\r
--- /dev/null
+/*\r
+ * Copyright (c) 2008 Microsoft Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ * - Redistributions of source code must retain the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer.\r
+ *\r
+ * - Redistributions in binary form must reproduce the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer in the documentation and/or other materials\r
+ * provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id:$\r
+ */\r
+\r
+#pragma once\r
+\r
+#include "ndspi.h"\r
+#include "nddebug.h"\r
+#include <iba/ib_al.h>\r
+#include <iba/ib_at_ioctl.h>\r
+#include <ws2tcpip.h>\r
+#include "ual_ci_ca.h"\r
+\r
+#include "NdProv.h"\r
+\r
+\r
+namespace NetworkDirect\r
+{\r
+\r
+class CCq;\r
+class CAddr;\r
+class CProvider;\r
+\r
+class CAdapter :\r
+ public INDAdapter\r
+{\r
+ friend class CCq;\r
+ friend class CEndpoint;\r
+ friend class CConnector;\r
+ friend class CMw;\r
+ friend class CMr;\r
+ friend class CListen;\r
+\r
+private:\r
+ CAdapter(void);\r
+ ~CAdapter(void);\r
+\r
+ HRESULT Initialize(\r
+ CProvider* pParent,\r
+ const struct sockaddr* pAddr,\r
+ const IBAT_PORT_RECORD* pPortRecord\r
+ );\r
+\r
+public:\r
+ static HRESULT Create(\r
+ CProvider* pParent,\r
+ const struct sockaddr* pAddr,\r
+ const IBAT_PORT_RECORD* pPortRecord,\r
+ __out INDAdapter** ppAdapter\r
+ );\r
+\r
+ // *** IUnknown methods ***\r
+ HRESULT STDMETHODCALLTYPE QueryInterface(\r
+ REFIID riid,\r
+ LPVOID FAR* ppvObj\r
+ );\r
+\r
+ ULONG STDMETHODCALLTYPE AddRef(void);\r
+\r
+ ULONG STDMETHODCALLTYPE Release(void);\r
+\r
+ // *** INDOverlapped methods ***\r
+ HRESULT STDMETHODCALLTYPE CancelOverlappedRequests(void);\r
+\r
+ HRESULT STDMETHODCALLTYPE GetOverlappedResult(\r
+ __inout OVERLAPPED *pOverlapped,\r
+ __out SIZE_T *pNumberOfBytesTransferred,\r
+ __in BOOL bWait\r
+ );\r
+\r
+ // *** INDAdapter methods ***\r
+ HANDLE STDMETHODCALLTYPE GetFileHandle(void);\r
+\r
+ HRESULT STDMETHODCALLTYPE Query(\r
+ __in DWORD VersionRequested,\r
+ __out_bcount_part_opt(*pBufferSize, *pBufferSize) ND_ADAPTER_INFO* pInfo,\r
+ __inout_opt SIZE_T* pBufferSize\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE Control(\r
+ __in DWORD IoControlCode,\r
+ __in_bcount_opt(InBufferSize) const void* pInBuffer,\r
+ __in SIZE_T InBufferSize,\r
+ __out_bcount_opt(OutBufferSize) void* pOutBuffer,\r
+ __in SIZE_T OutBufferSize,\r
+ __out SIZE_T* pBytesReturned,\r
+ __inout OVERLAPPED* pOverlapped\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE CreateCompletionQueue(\r
+ __in SIZE_T nEntries,\r
+ __deref_out INDCompletionQueue** ppCq\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE RegisterMemory(\r
+ __in_bcount(BufferSize) const void* pBuffer,\r
+ __in SIZE_T BufferSize,\r
+ __inout OVERLAPPED* pOverlapped,\r
+ __deref_out ND_MR_HANDLE* phMr\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE CompleteRegisterMemory(\r
+ __in ND_MR_HANDLE hMr,\r
+ __in OVERLAPPED* pOverlapped\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE DeregisterMemory(\r
+ __in ND_MR_HANDLE hMr,\r
+ __inout OVERLAPPED* pOverlapped\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE CompleteDeregisterMemory(\r
+ __in ND_MR_HANDLE hMr,\r
+ __in OVERLAPPED* pOverlapped\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE CreateMemoryWindow(\r
+ __out ND_RESULT* pInvalidateResult,\r
+ __deref_out INDMemoryWindow** ppMw\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE CreateConnector(\r
+ __deref_out INDConnector** ppConnector\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE Listen(\r
+ __in SIZE_T Backlog,\r
+ __in INT Protocol,\r
+ __in USHORT Port,\r
+ __out_opt USHORT* pAssignedPort,\r
+ __deref_out INDListen** ppListen\r
+ );\r
+\r
+ HRESULT GetLocalAddress(\r
+ __out_bcount_part(*pAddressLength, *pAddressLength) struct sockaddr* pAddr,\r
+ __inout SIZE_T *pAddressLength );\r
+\r
+private:\r
+ HRESULT OpenFiles(void);\r
+\r
+ HRESULT OpenCa(\r
+ __in UINT64 CaGuid\r
+ );\r
+\r
+ HRESULT QueryCa(\r
+ __out_bcount(*pSize) ib_ca_attr_t* pAttr,\r
+ __inout DWORD* pSize\r
+ );\r
+\r
+ void CloseCa(void);\r
+\r
+ HRESULT AllocPd(void);\r
+\r
+ void DeallocPd(void);\r
+\r
+protected:\r
+ volatile LONG m_nRef;\r
+\r
+ CProvider* m_pParent;\r
+ UINT64 m_PortGuid;\r
+ UINT8 m_PortNum;\r
+\r
+ HANDLE m_hSync;\r
+ HANDLE m_hAsync;\r
+\r
+ ual_ci_interface_t m_Ifc;\r
+ // Kernel IBAL handles.\r
+ uint64_t m_hCa;\r
+ uint64_t m_hPd;\r
+ // UVP handles.\r
+ ib_ca_handle_t m_uCa;\r
+ ib_pd_handle_t m_uPd;\r
+\r
+ union _addr\r
+ {\r
+ struct sockaddr unspec;\r
+ struct sockaddr_in v4;\r
+ struct sockaddr_in6 v6;\r
+\r
+ } m_Addr;\r
+};\r
+\r
+} // namespace
\ No newline at end of file
--- /dev/null
+/*\r
+ * Copyright (c) 2008 Microsoft Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ * - Redistributions of source code must retain the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer.\r
+ *\r
+ * - Redistributions in binary form must reproduce the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer in the documentation and/or other materials\r
+ * provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id:$\r
+ */\r
+\r
+#include "NdCq.h"\r
+#include "NdAdapter.h"\r
+#include "NdMw.h"\r
+#include "NdEndpoint.h"\r
+#include "NdProv.h"\r
+#include "NdMr.h"\r
+#include "NdListen.h"\r
+#include "NdConnector.h"\r
+\r
+#include "al_dev.h"\r
+#pragma warning( push, 3 )\r
+#include "winternl.h"\r
+#pragma warning( pop )\r
+#include "iba/ibat.h"\r
+\r
+#include <assert.h>\r
+#include <limits.h>\r
+#include <strsafe.h>\r
+\r
+#if defined(EVENT_TRACING)\r
+#ifdef offsetof\r
+#undef offsetof\r
+#endif\r
+#include "NdConnector.tmh"\r
+#endif\r
+\r
+\r
+namespace NetworkDirect\r
+{\r
+\r
+CConnector::CConnector(void) :\r
+ m_nRef( 1 ),\r
+ m_pParent( NULL ),\r
+ m_pEndpoint( NULL ),\r
+ m_Protocol( 0 ),\r
+ m_LocalPort( 0 ),\r
+ m_cid( 0 ),\r
+ m_fActive( false )\r
+{\r
+}\r
+\r
+CConnector::~CConnector(void)\r
+{\r
+ FreeCid();\r
+\r
+ if( m_pEndpoint )\r
+ m_pEndpoint->Release();\r
+\r
+ if( m_pParent )\r
+ m_pParent->Release();\r
+}\r
+\r
+void CConnector::FreeCid(void)\r
+{\r
+ if( m_cid != 0 )\r
+ {\r
+ DWORD bytes_ret;\r
+ DeviceIoControl(\r
+ m_pParent->m_hSync,\r
+ UAL_DESTROY_CEP,\r
+ &m_cid,\r
+ sizeof(m_cid),\r
+ NULL,\r
+ 0,\r
+ &bytes_ret,\r
+ NULL );\r
+\r
+ m_cid = 0;\r
+ }\r
+}\r
+\r
+HRESULT CConnector::Create(\r
+ __in CAdapter* pParent,\r
+ __deref_out INDConnector** ppConnector\r
+ )\r
+{\r
+ CConnector* pConnector = new CConnector();\r
+ if( pConnector == NULL )\r
+ return ND_NO_MEMORY;\r
+\r
+ pConnector->m_pParent = pParent;\r
+ pParent->AddRef();\r
+\r
+ *ppConnector = pConnector;\r
+ return S_OK;\r
+}\r
+\r
+HRESULT CConnector::QueryInterface(\r
+ REFIID riid,\r
+ LPVOID FAR* ppvObj\r
+ )\r
+{\r
+ if( IsEqualIID( riid, IID_IUnknown ) )\r
+ {\r
+ *ppvObj = this;\r
+ return S_OK;\r
+ }\r
+\r
+ if( IsEqualIID( riid, IID_INDConnector ) )\r
+ {\r
+ *ppvObj = this;\r
+ return S_OK;\r
+ }\r
+\r
+ return E_NOINTERFACE;\r
+}\r
+\r
+ULONG CConnector::AddRef(void)\r
+{\r
+ return InterlockedIncrement( &m_nRef );\r
+}\r
+\r
+ULONG CConnector::Release(void)\r
+{\r
+ ULONG ref = InterlockedDecrement( &m_nRef );\r
+ if( ref == 0 )\r
+ delete this;\r
+\r
+ return ref;\r
+}\r
+\r
+// *** INDOverlapped methods ***\r
+HRESULT CConnector::CancelOverlappedRequests(void)\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ DWORD bytes_ret;\r
+ BOOL ret = DeviceIoControl(\r
+ m_pParent->m_hSync,\r
+ UAL_NDI_CANCEL_CM_IRPS,\r
+ &m_cid,\r
+ sizeof(m_cid),\r
+ NULL,\r
+ 0,\r
+ &bytes_ret,\r
+ NULL );\r
+\r
+ if( ret )\r
+ return S_OK;\r
+ else\r
+ return ND_UNSUCCESSFUL;\r
+}\r
+\r
+HRESULT CConnector::GetOverlappedResult(\r
+ __inout OVERLAPPED *pOverlapped,\r
+ __out SIZE_T *pNumberOfBytesTransferred,\r
+ __in BOOL bWait\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ *pNumberOfBytesTransferred = 0;\r
+ ::GetOverlappedResult(\r
+ m_pParent->GetFileHandle(),\r
+ pOverlapped,\r
+ (DWORD*)pNumberOfBytesTransferred,\r
+ bWait );\r
+ return (HRESULT)pOverlapped->Internal;\r
+}\r
+\r
+HRESULT CConnector::CreateEndpoint(\r
+ __in INDCompletionQueue* pInboundCq,\r
+ __in INDCompletionQueue* pOutboundCq,\r
+ __in SIZE_T nInboundEntries,\r
+ __in SIZE_T nOutboundEntries,\r
+ __in SIZE_T nInboundSge,\r
+ __in SIZE_T nOutboundSge,\r
+ __in SIZE_T InboundReadLimit,\r
+ __in SIZE_T OutboundReadLimit,\r
+ __out_opt SIZE_T* pMaxInlineData,\r
+ __deref_out INDEndpoint** ppEndpoint\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ //\r
+ // Check that the verb provider supports user-mode operations.\r
+ // If not, a different class should be created.\r
+ //\r
+ if( m_pParent->m_Ifc.user_verbs.pre_create_qp == NULL ||\r
+ m_pParent->m_Ifc.user_verbs.post_create_qp == NULL ||\r
+ m_pParent->m_Ifc.user_verbs.nd_modify_qp == NULL ||\r
+ m_pParent->m_Ifc.user_verbs.nd_get_qp_state == NULL ||\r
+ m_pParent->m_Ifc.user_verbs.pre_destroy_qp == NULL ||\r
+ m_pParent->m_Ifc.user_verbs.post_destroy_qp == NULL ||\r
+ m_pParent->m_Ifc.user_verbs.post_send == NULL ||\r
+ m_pParent->m_Ifc.user_verbs.post_recv == NULL /*||\r
+ m_pParent->m_Ifc.user_verbs.bind_mw == NULL*/ )\r
+ {\r
+ return ND_NOT_SUPPORTED;\r
+ }\r
+\r
+ if( m_pEndpoint != NULL )\r
+ return ND_NOT_SUPPORTED;\r
+\r
+ HRESULT hr = CEndpoint::Create(\r
+ m_pParent,\r
+ static_cast<CCq*>(pInboundCq),\r
+ static_cast<CCq*>(pOutboundCq),\r
+ nInboundEntries,\r
+ nOutboundEntries,\r
+ nInboundSge,\r
+ nOutboundSge,\r
+ InboundReadLimit,\r
+ OutboundReadLimit,\r
+ pMaxInlineData,\r
+ (INDEndpoint**)&m_pEndpoint\r
+ );\r
+\r
+ if( SUCCEEDED( hr ) )\r
+ {\r
+ m_pEndpoint->AddRef();\r
+ *ppEndpoint = m_pEndpoint;\r
+ }\r
+\r
+ return hr;\r
+}\r
+\r
+//\r
+// Connects an endpoint to the specified destinaton address.\r
+//\r
+// Only basic checks on input data are performed in user-mode,\r
+// and request is handed to the kernel, where:\r
+// 1. the destination address is resolved to a destination GID\r
+// 2. the destination GID is used to get a path record\r
+// 3. the path record is used to issue a CM REQ\r
+// 4. a CM REP is received (or REJ or timeout).\r
+// 5. the request is completed.\r
+//\r
+HRESULT CConnector::Connect(\r
+ __inout INDEndpoint* pEndpoint,\r
+ __in_bcount(AddressLength) const struct sockaddr* pAddress,\r
+ __in SIZE_T AddressLength,\r
+ __in INT Protocol,\r
+ __in_opt USHORT LocalPort,\r
+ __in_bcount_opt(PrivateDataLength) const void* pPrivateData,\r
+ __in SIZE_T PrivateDataLength,\r
+ __inout OVERLAPPED* pOverlapped\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ if( AddressLength < sizeof(struct sockaddr) )\r
+ return ND_INVALID_ADDRESS;\r
+\r
+ if( Protocol > UCHAR_MAX || Protocol < 0 )\r
+ return ND_INVALID_PARAMETER_4;\r
+\r
+ m_Protocol = (UINT8)Protocol;\r
+\r
+ //\r
+ // CM REQ supports 92 bytes of private data. We expect to use IP\r
+ // addressing annex, which eats up 36 bytes, leaving us with 56.\r
+ //\r
+ if( PrivateDataLength > 56 )\r
+ return ND_BUFFER_OVERFLOW;\r
+\r
+ //\r
+ // Only support connecting the endpoint we created.\r
+ //\r
+ if( pEndpoint != m_pEndpoint )\r
+ return ND_INVALID_PARAMETER_1;\r
+\r
+ //\r
+ // Format the private data to match the RDMA CM annex spec as we\r
+ // check the address validity.\r
+ //\r
+ ual_ndi_req_cm_ioctl_in_t ioctl;\r
+ ioctl.pdata.maj_min_ver = 0;\r
+ if( LocalPort == 0 )\r
+ {\r
+ m_LocalPort = (USHORT)_byteswap_ulong( m_pEndpoint->m_Qpn );\r
+ }\r
+ else\r
+ {\r
+ m_LocalPort = LocalPort;\r
+ }\r
+ ioctl.pdata.src_port = _byteswap_ushort( m_LocalPort );\r
+\r
+ // Resolve the GIDs.\r
+ HRESULT hr = IBAT::Resolve(\r
+ &m_pParent->m_Addr.unspec,\r
+ pAddress,\r
+ (IBAT_PATH_BLOB*)&ioctl.path\r
+ );\r
+ if( FAILED( hr ) )\r
+ {\r
+ if( hr == E_PENDING )\r
+ {\r
+ //\r
+ // Complete the request with a timeout status.\r
+ //\r
+ pOverlapped->Internal = ND_PENDING;\r
+ hr = NtDeviceIoControlFile(\r
+ m_pParent->GetFileHandle(),\r
+ pOverlapped->hEvent,\r
+ NULL,\r
+ (ULONG_PTR)pOverlapped->hEvent & 1 ? NULL : pOverlapped,\r
+ (IO_STATUS_BLOCK*)&pOverlapped->Internal,\r
+ UAL_NDI_NOOP,\r
+ &hr,\r
+ sizeof(hr),\r
+ NULL,\r
+ 0 );\r
+ }\r
+ return hr;\r
+ }\r
+\r
+ switch( ((struct sockaddr_in*)pAddress)->sin_family )\r
+ {\r
+ case AF_INET:\r
+ if( AddressLength != sizeof(struct sockaddr_in) )\r
+ return ND_INVALID_ADDRESS;\r
+\r
+ if( m_pParent->m_Addr.v4.sin_family != AF_INET )\r
+ return ND_INVALID_ADDRESS;\r
+\r
+ //\r
+ // Copy the destination address so we can satisfy a\r
+ // GetPeerAddress request.\r
+ //\r
+ m_PeerAddr.v4 = *(struct sockaddr_in*)pAddress;\r
+\r
+ ioctl.dst_port = m_PeerAddr.v4.sin_port;\r
+ ioctl.pdata.ipv = 0x40;\r
+\r
+ // Local address.\r
+ RtlZeroMemory( &ioctl.pdata.src_ip_addr, ATS_IPV4_OFFSET );\r
+ CopyMemory(\r
+ &ioctl.pdata.src_ip_addr[ATS_IPV4_OFFSET>>2],\r
+ (uint8_t*)&m_pParent->m_Addr.v4.sin_addr,\r
+ sizeof( m_pParent->m_Addr.v4.sin_addr )\r
+ );\r
+\r
+ // Destination address.\r
+ RtlZeroMemory( &ioctl.pdata.dst_ip_addr, ATS_IPV4_OFFSET );\r
+ CopyMemory(\r
+ &ioctl.pdata.dst_ip_addr[ATS_IPV4_OFFSET>>2],\r
+ (uint8_t*)&m_PeerAddr.v4.sin_addr,\r
+ sizeof( m_PeerAddr.v4.sin_addr )\r
+ );\r
+ ND_PRINT( TRACE_LEVEL_INFORMATION, ND_DBG_NDI,\r
+ ("local address: IP %#x, port %#hx, dest address: IP %#x, port %#hx\n", \r
+ cl_hton32(m_pParent->m_Addr.v4.sin_addr.S_un.S_addr), cl_hton16(m_pParent->m_Addr.v4.sin_port),\r
+ cl_hton32(m_PeerAddr.v4.sin_addr.S_un.S_addr), cl_hton16(m_PeerAddr.v4.sin_port) ) );\r
+ break;\r
+\r
+ case AF_INET6:\r
+ if( AddressLength != sizeof(struct sockaddr_in6) )\r
+ return ND_INVALID_ADDRESS;\r
+\r
+ //\r
+ // Copy the destination address so we can satisfy a\r
+ // GetPeerAddress request.\r
+ //\r
+ m_PeerAddr.v6 = *(struct sockaddr_in6*)pAddress;\r
+\r
+ ioctl.dst_port = m_PeerAddr.v6.sin6_port;\r
+ ioctl.pdata.ipv = 0x60;\r
+\r
+ // Local address.\r
+ CopyMemory(\r
+ ioctl.pdata.src_ip_addr,\r
+ m_pParent->m_Addr.v6.sin6_addr.u.Byte,\r
+ sizeof(ioctl.pdata.src_ip_addr)\r
+ );\r
+\r
+ // Destination address.\r
+ CopyMemory( ioctl.pdata.dst_ip_addr,\r
+ m_PeerAddr.v6.sin6_addr.u.Byte,\r
+ sizeof(ioctl.pdata.dst_ip_addr)\r
+ );\r
+ break;\r
+\r
+ default:\r
+ return ND_INVALID_ADDRESS;\r
+ }\r
+\r
+ // Copy the user's private data.\r
+ CopyMemory( ioctl.pdata.pdata, pPrivateData, PrivateDataLength );\r
+\r
+ //\r
+ // It's only valid to call Connect with a new or reused endpoint:\r
+ // the QP must be in the INIT state.\r
+ //\r
+ switch( m_pParent->m_Ifc.user_verbs.nd_get_qp_state( m_pEndpoint->m_uQp ) )\r
+ {\r
+ case IB_QPS_INIT:\r
+ break;\r
+\r
+ case IB_QPS_RTS:\r
+ return ND_CONNECTION_ACTIVE;\r
+\r
+ default:\r
+ return ND_UNSUCCESSFUL;\r
+ }\r
+\r
+ //\r
+ // Create the CEP. We do this so that we have a valid CID in user-mode\r
+ // in case the user calls CancelOverlappedRequests or releases the object.\r
+ //\r
+ UINT64 context = 0;\r
+ ual_create_cep_ioctl_t create;\r
+ DWORD bytes_ret;\r
+ BOOL fSuccess = DeviceIoControl(\r
+ m_pParent->m_hSync,\r
+ UAL_CREATE_CEP,\r
+ &context,\r
+ sizeof(context),\r
+ &create,\r
+ sizeof(create),\r
+ &bytes_ret,\r
+ NULL\r
+ );\r
+ if( !fSuccess ||\r
+ bytes_ret != sizeof(create) ||\r
+ create.status != IB_SUCCESS )\r
+ {\r
+ return ND_INSUFFICIENT_RESOURCES;\r
+ }\r
+\r
+ m_cid = create.cid;\r
+\r
+ //\r
+ // Fill in the rest of the input buffer and send the request down\r
+ // to the kernel and let everything else be done there.\r
+ //\r
+ ioctl.h_qp = m_pEndpoint->m_hQp;\r
+ ioctl.guid = m_pParent->m_PortGuid;\r
+ ioctl.cid = m_cid;\r
+ ioctl.prot = m_Protocol;\r
+ ioctl.pdata_size = sizeof(ioctl.pdata);\r
+ ioctl.init_depth = m_pEndpoint->m_Ord;\r
+ ioctl.resp_res = m_pEndpoint->m_Ird;\r
+\r
+ ND_PRINT( TRACE_LEVEL_INFORMATION, ND_DBG_NDI,\r
+ ("Connect QP %#I64x, QPn %#x, Guid %#I64x \n",\r
+ m_pEndpoint->m_hQp,\r
+ m_pEndpoint->m_Qpn,\r
+ m_pParent->m_PortGuid ) );\r
+\r
+ m_fActive = true;\r
+\r
+ pOverlapped->Internal = ND_PENDING;\r
+ hr = NtDeviceIoControlFile(\r
+ m_pParent->GetFileHandle(),\r
+ pOverlapped->hEvent,\r
+ NULL,\r
+ (ULONG_PTR)pOverlapped->hEvent & 1 ? NULL : pOverlapped,\r
+ (IO_STATUS_BLOCK*)&pOverlapped->Internal,\r
+ UAL_NDI_REQ_CM,\r
+ &ioctl,\r
+ sizeof(ioctl),\r
+ NULL,\r
+ 0 );\r
+\r
+ if( FAILED( hr ) )\r
+ {\r
+ FreeCid();\r
+ m_pEndpoint->Release();\r
+ m_pEndpoint = NULL;\r
+ }\r
+\r
+ return hr;\r
+}\r
+\r
+HRESULT CConnector::CompleteConnect(\r
+ __inout OVERLAPPED* pOverlapped\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ if( !m_fActive )\r
+ return ND_CONNECTION_INVALID;\r
+\r
+ if( m_pEndpoint == NULL )\r
+ return ND_CONNECTION_INVALID;\r
+\r
+ //\r
+ // Get the UVP's buffer for modify operations.\r
+ //\r
+ void* pOutbuf;\r
+ DWORD szOutbuf;\r
+\r
+ m_pParent->m_Ifc.user_verbs.nd_modify_qp(\r
+ (const ib_qp_handle_t)m_pEndpoint->m_uQp,\r
+ &pOutbuf,\r
+ &szOutbuf\r
+ );\r
+\r
+ ND_PRINT( TRACE_LEVEL_INFORMATION, ND_DBG_NDI,\r
+ ("CompleteConnect QP %#I64x, QPn %#x\n", m_pEndpoint->m_hQp, m_pEndpoint->m_Qpn ) );\r
+\r
+ pOverlapped->Internal = ND_PENDING;\r
+ return NtDeviceIoControlFile(\r
+ m_pParent->GetFileHandle(),\r
+ pOverlapped->hEvent,\r
+ NULL,\r
+ (ULONG_PTR)pOverlapped->hEvent & 1 ? NULL : pOverlapped,\r
+ (IO_STATUS_BLOCK*)&pOverlapped->Internal,\r
+ UAL_NDI_RTU_CM,\r
+ &m_cid,\r
+ sizeof(m_cid),\r
+ pOutbuf,\r
+ szOutbuf );\r
+}\r
+\r
+HRESULT CConnector::Accept(\r
+ __in INDEndpoint* pEndpoint,\r
+ __in_bcount_opt(PrivateDataLength) const void* pPrivateData,\r
+ __in SIZE_T PrivateDataLength,\r
+ __inout OVERLAPPED* pOverlapped\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ if( PrivateDataLength > IB_REJ_PDATA_SIZE )\r
+ return ND_BUFFER_OVERFLOW;\r
+\r
+ //\r
+ // Only support connecting the endpoint we created.\r
+ //\r
+ if( pEndpoint != m_pEndpoint )\r
+ return ND_INVALID_PARAMETER_1;\r
+\r
+ //\r
+ // Get the UVP's buffer for modify operations.\r
+ //\r
+ void* pOutbuf;\r
+ DWORD szOutbuf;\r
+\r
+ m_pParent->m_Ifc.user_verbs.nd_modify_qp(\r
+ static_cast<CEndpoint*>(pEndpoint)->m_uQp,\r
+ &pOutbuf,\r
+ &szOutbuf\r
+ );\r
+\r
+ ual_ndi_rep_cm_ioctl_in_t ioctl;\r
+ ioctl.h_qp = m_pEndpoint->m_hQp;\r
+ ioctl.cid = m_cid;\r
+ ioctl.init_depth = m_pEndpoint->m_Ord;\r
+ ioctl.resp_res = m_pEndpoint->m_Ird;\r
+ ioctl.pdata_size = (uint8_t)PrivateDataLength;\r
+ CopyMemory( &ioctl.pdata, pPrivateData, PrivateDataLength );\r
+\r
+ ND_PRINT( TRACE_LEVEL_INFORMATION, ND_DBG_NDI,\r
+ ("Accept QP %#I64x, cid %d \n", ioctl.h_qp, ioctl.cid ) );\r
+\r
+ pOverlapped->Internal = ND_PENDING;\r
+ HRESULT hr = NtDeviceIoControlFile(\r
+ m_pParent->GetFileHandle(),\r
+ pOverlapped->hEvent,\r
+ NULL,\r
+ (ULONG_PTR)pOverlapped->hEvent & 1 ? NULL : pOverlapped,\r
+ (IO_STATUS_BLOCK*)&pOverlapped->Internal,\r
+ UAL_NDI_REP_CM,\r
+ &ioctl,\r
+ sizeof(ioctl),\r
+ pOutbuf,\r
+ szOutbuf );\r
+\r
+ if( FAILED( hr ) )\r
+ {\r
+ m_pEndpoint->Release();\r
+ m_pEndpoint = NULL;\r
+ }\r
+ return hr;\r
+}\r
+\r
+HRESULT CConnector::Reject(\r
+ __in_bcount_opt(PrivateDataLength) const void* pPrivateData,\r
+ __in SIZE_T PrivateDataLength\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ if( PrivateDataLength > IB_REJ_PDATA_SIZE )\r
+ return ND_BUFFER_OVERFLOW;\r
+\r
+ ual_ndi_rej_cm_ioctl_in_t ioctl;\r
+ ioctl.cid = m_cid;\r
+ ioctl.pdata_size = (uint8_t)PrivateDataLength;\r
+ if( pPrivateData != NULL )\r
+ {\r
+ CopyMemory( &ioctl.pdata, pPrivateData, PrivateDataLength );\r
+ }\r
+\r
+ ND_PRINT( TRACE_LEVEL_INFORMATION, ND_DBG_NDI, \r
+ ("Connection rejected with pdata_size %d, cid %d\n", \r
+ (int)PrivateDataLength, ioctl.cid ));\r
+\r
+ IO_STATUS_BLOCK IoStatus;\r
+ return NtDeviceIoControlFile(\r
+ m_pParent->m_hSync,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ &IoStatus,\r
+ UAL_NDI_REJ_CM,\r
+ &ioctl,\r
+ sizeof(ioctl),\r
+ NULL,\r
+ 0 );\r
+}\r
+\r
+HRESULT CConnector::GetConnectionData(\r
+ __out_opt SIZE_T* pInboundReadLimit,\r
+ __out_opt SIZE_T* pOutboundReadLimit,\r
+ __out_bcount_part_opt(*pPrivateDataLength, *pPrivateDataLength) void* pPrivateData,\r
+ __inout SIZE_T* pPrivateDataLength\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ IO_STATUS_BLOCK IoStatus;\r
+ ual_cep_get_pdata_ioctl_t IoctlBuf;\r
+\r
+ IoctlBuf.in.cid = m_cid;\r
+ HRESULT hr = NtDeviceIoControlFile(\r
+ m_pParent->m_hSync,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ &IoStatus,\r
+ UAL_CEP_GET_PDATA,\r
+ &IoctlBuf,\r
+ sizeof(IoctlBuf.in),\r
+ &IoctlBuf,\r
+ sizeof(IoctlBuf.out) );\r
+\r
+ // UAL_CEP_GET_PDATA never returns pending.\r
+ if( FAILED( hr ) )\r
+ return hr;\r
+\r
+ // On the passive side, check that we got the REQ private data.\r
+ if( !m_fActive )\r
+ {\r
+ hr = GetPdataForPassive(\r
+ IoctlBuf.out.pdata,\r
+ IoctlBuf.out.pdata_len,\r
+ pPrivateData,\r
+ pPrivateDataLength\r
+ );\r
+ }\r
+ else\r
+ {\r
+ hr = GetPdataForActive(\r
+ IoctlBuf.out.pdata,\r
+ IoctlBuf.out.pdata_len,\r
+ pPrivateData,\r
+ pPrivateDataLength\r
+ );\r
+ }\r
+\r
+ if( FAILED( hr ) && hr != ND_BUFFER_OVERFLOW )\r
+ return hr;\r
+\r
+ if( pInboundReadLimit )\r
+ {\r
+ *pInboundReadLimit = IoctlBuf.out.resp_res;\r
+ }\r
+\r
+ if( pOutboundReadLimit )\r
+ {\r
+ *pOutboundReadLimit = IoctlBuf.out.init_depth;\r
+ }\r
+\r
+ return hr;\r
+}\r
+\r
+HRESULT CConnector::GetLocalAddress(\r
+ __out_bcount_part_opt(*pAddressLength, *pAddressLength) struct sockaddr* pAddress,\r
+ __inout SIZE_T* pAddressLength\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ if( m_pEndpoint == NULL )\r
+ return ND_CONNECTION_INVALID;\r
+\r
+ ib_qp_state_t state =\r
+ m_pParent->m_Ifc.user_verbs.nd_get_qp_state( m_pEndpoint->m_uQp );\r
+ if( state != IB_QPS_RTS )\r
+ return ND_CONNECTION_INVALID;\r
+\r
+ HRESULT hr = m_pParent->GetLocalAddress( pAddress, pAddressLength );\r
+ if( FAILED(hr) )\r
+ return hr;\r
+\r
+ // V4 and V6 addresses have the port number in the same place.\r
+ ((struct sockaddr_in*)pAddress)->sin_port = m_LocalPort;\r
+#if DBG || defined(EVENT_TRACING)\r
+ struct sockaddr_in*pAddrV4 = (struct sockaddr_in*)pAddress;\r
+#endif \r
+ ND_PRINT( TRACE_LEVEL_INFORMATION, ND_DBG_NDI,\r
+ ("Local address: IP %#x, port %#hx\n", \r
+ cl_hton32(pAddrV4->sin_addr.S_un.S_addr), cl_hton16(pAddrV4->sin_port) ) );\r
+\r
+ return S_OK;\r
+}\r
+\r
+HRESULT CConnector::GetAddressFromPdata(\r
+ __out_bcount_part(*pAddressLength, *pAddressLength) struct sockaddr* pAddress,\r
+ __inout SIZE_T* pAddressLength\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ IO_STATUS_BLOCK IoStatus;\r
+ ual_cep_get_pdata_ioctl_t IoctlBuf;\r
+\r
+ IoctlBuf.in.cid = m_cid;\r
+\r
+ HRESULT hr = NtDeviceIoControlFile(\r
+ m_pParent->m_hSync,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ &IoStatus,\r
+ UAL_CEP_GET_PDATA,\r
+ &IoctlBuf,\r
+ sizeof(IoctlBuf.in),\r
+ &IoctlBuf,\r
+ sizeof(IoctlBuf.out) );\r
+\r
+ // UAL_CEP_GET_PDATA never returns pending.\r
+ if( FAILED( hr ) )\r
+ {\r
+ CL_ASSERT( hr != ND_PENDING );\r
+ return hr;\r
+ }\r
+\r
+ if( IoctlBuf.out.pdata_len != IB_REQ_PDATA_SIZE )\r
+ return ND_CONNECTION_ABORTED;\r
+\r
+ ib_cm_rdma_req_t* pIpData = (ib_cm_rdma_req_t*)&IoctlBuf.out.pdata;\r
+ CL_ASSERT( pIpData->maj_min_ver == 0 );\r
+\r
+ SIZE_T len;\r
+ switch( pIpData->ipv )\r
+ {\r
+ case 0x40:\r
+ len = 4;\r
+ break;\r
+ case 0x60:\r
+ len = 16;\r
+ break;\r
+ default:\r
+ CL_ASSERT( pIpData->ipv == 0x40 || pIpData->ipv == 0x60 );\r
+ len = 0;\r
+ break;\r
+ }\r
+\r
+ if( len > *pAddressLength )\r
+ {\r
+ *pAddressLength = len;\r
+ return ND_BUFFER_OVERFLOW;\r
+ }\r
+\r
+ ((struct sockaddr_in*)pAddress)->sin_port =\r
+ _byteswap_ushort( pIpData->src_port );\r
+\r
+ switch( pIpData->ipv )\r
+ {\r
+ case 0x40:\r
+ ((struct sockaddr_in*)pAddress)->sin_family = AF_INET;\r
+ ((struct sockaddr_in*)pAddress)->sin_addr.s_addr = pIpData->src_ip_addr[3];\r
+ ZeroMemory( ((struct sockaddr_in*)pAddress)->sin_zero,\r
+ sizeof( ((struct sockaddr_in*)pAddress)->sin_zero ) );\r
+ break;\r
+\r
+ case 0x60:\r
+ ((struct sockaddr_in6*)pAddress)->sin6_family = AF_INET6;\r
+ ((struct sockaddr_in6*)pAddress)->sin6_flowinfo = 0;\r
+ RtlCopyMemory( (char*)((struct sockaddr_in6*)pAddress)->sin6_addr.s6_bytes,\r
+ (char *const)pIpData->src_ip_addr, sizeof(pIpData->src_ip_addr) );\r
+ ((struct sockaddr_in6*)pAddress)->sin6_scope_id = 0;\r
+ break;\r
+ }\r
+\r
+ *pAddressLength = len;\r
+ return hr;\r
+}\r
+\r
+HRESULT CConnector::GetPeerAddress(\r
+ __out_bcount_part_opt(*pAddressLength, *pAddressLength) struct sockaddr* pAddress,\r
+ __inout SIZE_T* pAddressLength\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ if( !m_fActive )\r
+ return GetAddressFromPdata( pAddress, pAddressLength );\r
+\r
+ if( m_pEndpoint == NULL )\r
+ return ND_CONNECTION_INVALID;\r
+\r
+ ib_qp_state_t state =\r
+ m_pParent->m_Ifc.user_verbs.nd_get_qp_state( m_pEndpoint->m_uQp );\r
+ if( state != IB_QPS_RTS )\r
+ return ND_CONNECTION_INVALID;\r
+\r
+ switch( m_PeerAddr.v4.sin_family )\r
+ {\r
+ case AF_INET:\r
+ if( *pAddressLength < sizeof(struct sockaddr_in) )\r
+ {\r
+ *pAddressLength = sizeof(struct sockaddr_in);\r
+ return ND_BUFFER_OVERFLOW;\r
+ }\r
+ *(struct sockaddr_in*)pAddress = m_PeerAddr.v4;\r
+ ND_PRINT( TRACE_LEVEL_INFORMATION, ND_DBG_NDI,\r
+ ("Peer address: IP %#x, port %#hx\n", \r
+ cl_hton32(m_PeerAddr.v4.sin_addr.S_un.S_addr), cl_hton16(m_PeerAddr.v4.sin_port) ) );\r
+ break;\r
+\r
+ case AF_INET6:\r
+ if( *pAddressLength < sizeof(struct sockaddr_in6) )\r
+ {\r
+ *pAddressLength = sizeof(struct sockaddr_in6);\r
+ return ND_BUFFER_OVERFLOW;\r
+ }\r
+ *(struct sockaddr_in6*)pAddress = m_PeerAddr.v6;\r
+ break;\r
+\r
+ default:\r
+ return ND_CONNECTION_INVALID;\r
+ }\r
+\r
+ return S_OK;\r
+}\r
+\r
+HRESULT CConnector::NotifyDisconnect(\r
+ __inout OVERLAPPED* pOverlapped\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ pOverlapped->Internal = ND_PENDING;\r
+ return NtDeviceIoControlFile(\r
+ m_pParent->GetFileHandle(),\r
+ pOverlapped->hEvent,\r
+ NULL,\r
+ (ULONG_PTR)pOverlapped->hEvent & 1 ? NULL : pOverlapped,\r
+ (IO_STATUS_BLOCK*)&pOverlapped->Internal,\r
+ UAL_NDI_NOTIFY_DREQ,\r
+ &m_cid,\r
+ sizeof(m_cid),\r
+ NULL,\r
+ 0 );\r
+}\r
+\r
+HRESULT CConnector::Disconnect(\r
+ __inout OVERLAPPED* pOverlapped\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ if( m_pEndpoint == NULL )\r
+ return ND_CONNECTION_INVALID;\r
+\r
+ ib_qp_state_t state =\r
+ m_pParent->m_Ifc.user_verbs.nd_get_qp_state( m_pEndpoint->m_uQp );\r
+ if( state != IB_QPS_RTS )\r
+ return ND_CONNECTION_INVALID;\r
+\r
+ //\r
+ // Get the UVP's buffer for modify operations.\r
+ //\r
+ void* pOutbuf;\r
+ DWORD szOutbuf;\r
+\r
+ m_pParent->m_Ifc.user_verbs.nd_modify_qp(\r
+ m_pEndpoint->m_uQp,\r
+ &pOutbuf,\r
+ &szOutbuf\r
+ );\r
+\r
+ ND_PRINT( TRACE_LEVEL_INFORMATION, ND_DBG_NDI,\r
+ ("Disconnect QP %#I64x, QPn %#x\n", m_pEndpoint->m_hQp, m_pEndpoint->m_Qpn ) );\r
+\r
+ pOverlapped->Internal = ND_PENDING;\r
+ HRESULT hr = NtDeviceIoControlFile(\r
+ m_pParent->GetFileHandle(),\r
+ pOverlapped->hEvent,\r
+ NULL,\r
+ (ULONG_PTR)pOverlapped->hEvent & 1 ? NULL : pOverlapped,\r
+ (IO_STATUS_BLOCK*)&pOverlapped->Internal,\r
+ UAL_NDI_DREQ_CM,\r
+ &m_cid,\r
+ sizeof(m_cid),\r
+ pOutbuf,\r
+ szOutbuf );\r
+\r
+ if( SUCCEEDED( hr ) )\r
+ {\r
+ m_pEndpoint->Release();\r
+ m_pEndpoint = NULL;\r
+ }\r
+\r
+ return hr;\r
+}\r
+\r
+} // namespace\r
--- /dev/null
+/*\r
+ * Copyright (c) 2008 Microsoft Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ * - Redistributions of source code must retain the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer.\r
+ *\r
+ * - Redistributions in binary form must reproduce the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer in the documentation and/or other materials\r
+ * provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id:$\r
+ */\r
+\r
+#pragma once\r
+\r
+#include "ndspi.h"\r
+#include "nddebug.h"\r
+#include <iba/ib_al.h>\r
+#include <iba/ib_at_ioctl.h>\r
+#include <ws2tcpip.h>\r
+#include "ual_ci_ca.h"\r
+\r
+\r
+namespace NetworkDirect\r
+{\r
+\r
+class CConnector :\r
+ public INDConnector\r
+{\r
+ friend class CListen;\r
+\r
+private:\r
+ CConnector(void);\r
+ ~CConnector(void);\r
+ void FreeCid(void);\r
+\r
+public:\r
+ static HRESULT Create(\r
+ __in CAdapter* pParent,\r
+ __deref_out INDConnector** ppConnector\r
+ );\r
+\r
+ // *** IUnknown methods ***\r
+ HRESULT STDMETHODCALLTYPE QueryInterface(\r
+ REFIID riid,\r
+ LPVOID FAR* ppvObj\r
+ );\r
+\r
+ ULONG STDMETHODCALLTYPE AddRef(void);\r
+\r
+ ULONG STDMETHODCALLTYPE Release(void);\r
+\r
+ // *** INDOverlapped methods ***\r
+ HRESULT STDMETHODCALLTYPE CancelOverlappedRequests(void);\r
+\r
+ HRESULT STDMETHODCALLTYPE GetOverlappedResult(\r
+ __inout OVERLAPPED *pOverlapped,\r
+ __out SIZE_T *pNumberOfBytesTransferred,\r
+ __in BOOL bWait\r
+ );\r
+\r
+ // *** INDConnector methods ***\r
+ HRESULT STDMETHODCALLTYPE CreateEndpoint(\r
+ __in INDCompletionQueue* pInboundCq,\r
+ __in INDCompletionQueue* pOutboundCq,\r
+ __in SIZE_T nInboundEntries,\r
+ __in SIZE_T nOutboundEntries,\r
+ __in SIZE_T nInboundSge,\r
+ __in SIZE_T nOutboundSge,\r
+ __in SIZE_T InboundReadLimit,\r
+ __in SIZE_T OutboundReadLimit,\r
+ __out_opt SIZE_T* pMaxInlineData,\r
+ __deref_out INDEndpoint** ppEndpoint\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE Connect(\r
+ __in INDEndpoint* pEndpoint,\r
+ __in_bcount(AddressLength) const struct sockaddr* pAddress,\r
+ __in SIZE_T AddressLength,\r
+ __in INT Protocol,\r
+ __in_opt USHORT LocalPort,\r
+ __in_bcount_opt(PrivateDataLength) const void* pPrivateData,\r
+ __in SIZE_T PrivateDataLength,\r
+ __inout OVERLAPPED* pOverlapped\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE CompleteConnect(\r
+ __inout OVERLAPPED* pOverlapped\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE Accept(\r
+ __in INDEndpoint* pEndpoint,\r
+ __in_bcount_opt(PrivateDataLength) const void* pPrivateData,\r
+ __in SIZE_T PrivateDataLength,\r
+ __inout OVERLAPPED* pOverlapped\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE Reject(\r
+ __in_bcount_opt(PrivateDataLength) const void* pPrivateData,\r
+ __in SIZE_T PrivateDataLength\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE GetConnectionData(\r
+ __out_opt SIZE_T* pInboundReadLimit,\r
+ __out_opt SIZE_T* pOutboundReadLimit,\r
+ __out_bcount_part_opt(*pPrivateDataLength, *pPrivateDataLength) void* pPrivateData,\r
+ __inout SIZE_T* pPrivateDataLength\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE GetLocalAddress(\r
+ __out_bcount_part_opt(*pAddressLength, *pAddressLength) struct sockaddr* pAddress,\r
+ __inout SIZE_T* pAddressLength\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE GetPeerAddress(\r
+ __out_bcount_part_opt(*pAddressLength, *pAddressLength) struct sockaddr* pAddress,\r
+ __inout SIZE_T* pAddressLength\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE NotifyDisconnect(\r
+ __inout_opt OVERLAPPED* pOverlapped\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE Disconnect(\r
+ __inout OVERLAPPED* pOverlapped\r
+ );\r
+\r
+private:\r
+ HRESULT GetAddressFromPdata(\r
+ __out_bcount_part(*pAddressLength, *pAddressLength) struct sockaddr* pAddress,\r
+ __inout SIZE_T* pAddressLength\r
+ );\r
+\r
+protected:\r
+ volatile LONG m_nRef;\r
+\r
+ CAdapter* m_pParent;\r
+\r
+ CEndpoint* m_pEndpoint;\r
+\r
+ UINT8 m_Protocol;\r
+ USHORT m_LocalPort;\r
+ net32_t m_cid;\r
+ bool m_fActive;\r
+\r
+ union _addr\r
+ {\r
+ struct sockaddr_in v4;\r
+ struct sockaddr_in6 v6;\r
+\r
+ } m_PeerAddr;\r
+};\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (c) 2008 Microsoft Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ * - Redistributions of source code must retain the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer.\r
+ *\r
+ * - Redistributions in binary form must reproduce the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer in the documentation and/or other materials\r
+ * provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id:$\r
+ */\r
+\r
+#include "NdCq.h"\r
+#include "NdAdapter.h"\r
+#include "al_cq.h"\r
+#include "al_dev.h"\r
+#include "al.h"\r
+#include "al_verbs.h"\r
+#pragma warning( push, 3 )\r
+#include "winternl.h"\r
+#pragma warning( pop )\r
+#include "limits.h"\r
+#include "nddebug.h"\r
+\r
+#if defined(EVENT_TRACING)\r
+#ifdef offsetof\r
+#undef offsetof\r
+#endif\r
+#include "NdCq.tmh"\r
+#endif\r
+\r
+\r
+namespace NetworkDirect\r
+{\r
+\r
+ CCq::CCq(void) :\r
+ m_nRef( 1 ),\r
+ m_pParent( NULL ),\r
+ m_hCq( 0 ),\r
+ m_uCq( NULL )\r
+ {\r
+ }\r
+\r
+ CCq::~CCq(void)\r
+ {\r
+ if( m_hCq )\r
+ CloseCq();\r
+\r
+ if( m_pParent )\r
+ m_pParent->Release();\r
+ }\r
+\r
+ HRESULT CCq::Initialize(\r
+ CAdapter* pParent,\r
+ SIZE_T nEntries )\r
+ {\r
+ if( nEntries > UINT_MAX )\r
+ return ND_INVALID_PARAMETER;\r
+\r
+ m_pParent = pParent;\r
+ pParent->AddRef();\r
+\r
+ return CreateCq( (UINT32)nEntries );\r
+ }\r
+\r
+ HRESULT CCq::QueryInterface(\r
+ REFIID riid,\r
+ LPVOID FAR* ppvObj\r
+ )\r
+ {\r
+ if( IsEqualIID( riid, IID_IUnknown ) )\r
+ {\r
+ *ppvObj = this;\r
+ return S_OK;\r
+ }\r
+\r
+ if( IsEqualIID( riid, IID_INDCompletionQueue ) )\r
+ {\r
+ *ppvObj = this;\r
+ return S_OK;\r
+ }\r
+\r
+ return E_NOINTERFACE;\r
+ }\r
+\r
+ ULONG CCq::AddRef(void)\r
+ {\r
+ return InterlockedIncrement( &m_nRef );\r
+ }\r
+\r
+ ULONG CCq::Release(void)\r
+ {\r
+ ULONG ref = InterlockedDecrement( &m_nRef );\r
+ if( ref == 0 )\r
+ delete this;\r
+\r
+ return ref;\r
+ }\r
+\r
+ // *** INDOverlapped methods ***\r
+ HRESULT CCq::CancelOverlappedRequests(void)\r
+ {\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ DWORD BytesRet;\r
+ DeviceIoControl(\r
+ m_pParent->m_hSync,\r
+ UAL_NDI_CANCEL_CQ,\r
+ &m_hCq,\r
+ sizeof(m_hCq),\r
+ NULL,\r
+ 0,\r
+ &BytesRet,\r
+ NULL\r
+ );\r
+\r
+ return S_OK;\r
+ }\r
+\r
+ HRESULT CCq::GetOverlappedResult(\r
+ __inout OVERLAPPED *pOverlapped,\r
+ __out SIZE_T *pNumberOfBytesTransferred,\r
+ __in BOOL bWait\r
+ )\r
+ {\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ *pNumberOfBytesTransferred = 0;\r
+ ::GetOverlappedResult(\r
+ m_pParent->GetFileHandle(),\r
+ pOverlapped,\r
+ (DWORD*)pNumberOfBytesTransferred,\r
+ bWait );\r
+ ND_PRINT( TRACE_LEVEL_VERBOSE, ND_DBG_NDI,\r
+ ("==> %s, result %#x, bytes %d\n", __FUNCTION__, (int)pOverlapped->Internal, (int)*pNumberOfBytesTransferred ));\r
+ return (HRESULT)pOverlapped->Internal;\r
+ }\r
+\r
+ // *** INDCompletionQueue methods ***\r
+ HRESULT CCq::Resize(\r
+ __in SIZE_T nEntries\r
+ )\r
+ {\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ if( nEntries > UINT_MAX )\r
+ return ND_INVALID_PARAMETER;\r
+\r
+ ib_api_status_t status;\r
+\r
+ /* Clear the IOCTL buffer */\r
+ ual_modify_cq_ioctl_t cq_ioctl;\r
+ cl_memclr( &cq_ioctl, sizeof(cq_ioctl) );\r
+\r
+ /* Call the uvp pre call if the vendor library provided a valid ca handle */\r
+ if( m_uCq && m_pParent->m_Ifc.user_verbs.pre_resize_cq )\r
+ {\r
+ /* Pre call to the UVP library */\r
+ status = m_pParent->m_Ifc.user_verbs.pre_resize_cq(\r
+ m_uCq, (uint32_t*)&nEntries, &cq_ioctl.in.umv_buf );\r
+ if( status != IB_SUCCESS )\r
+ goto exit;\r
+ }\r
+\r
+ cq_ioctl.in.h_cq = m_hCq;\r
+ cq_ioctl.in.size = (DWORD)nEntries;\r
+\r
+ DWORD BytesRet;\r
+ BOOL fSuccess = DeviceIoControl(\r
+ m_pParent->m_hSync,\r
+ UAL_MODIFY_CQ,\r
+ &cq_ioctl.in,\r
+ sizeof(cq_ioctl.in),\r
+ &cq_ioctl.out,\r
+ sizeof(cq_ioctl.out),\r
+ &BytesRet,\r
+ NULL\r
+ );\r
+\r
+ if( fSuccess != TRUE || BytesRet != sizeof(cq_ioctl.out) )\r
+ status = IB_ERROR;\r
+ else\r
+ status = cq_ioctl.out.status;\r
+\r
+ /* Post uvp call */\r
+ if( m_uCq && m_pParent->m_Ifc.user_verbs.post_resize_cq )\r
+ {\r
+ m_pParent->m_Ifc.user_verbs.post_resize_cq(\r
+ m_uCq, status, cq_ioctl.out.size, &cq_ioctl.out.umv_buf );\r
+ }\r
+\r
+exit:\r
+ switch( status )\r
+ {\r
+ case IB_INVALID_CQ_SIZE:\r
+ return ND_INVALID_PARAMETER;\r
+\r
+ case IB_SUCCESS:\r
+ return S_OK;\r
+\r
+ case IB_INSUFFICIENT_RESOURCES:\r
+ return ND_INSUFFICIENT_RESOURCES;\r
+\r
+ default:\r
+ return ND_UNSUCCESSFUL;\r
+ }\r
+ }\r
+\r
+ HRESULT CCq::Notify(\r
+ __in DWORD Type,\r
+ __inout OVERLAPPED* pOverlapped\r
+ )\r
+ {\r
+// ND_ENTER( ND_DBG_NDI );\r
+\r
+ ual_ndi_notify_cq_ioctl_in_t ioctl;\r
+ ioctl.h_cq = m_hCq;\r
+ ioctl.notify_comps = (boolean_t)Type;\r
+ pOverlapped->Internal = ND_PENDING;\r
+ HRESULT hr = NtDeviceIoControlFile(\r
+ m_pParent->GetFileHandle(),\r
+ pOverlapped->hEvent,\r
+ NULL,\r
+ (ULONG_PTR)pOverlapped->hEvent & 1 ? NULL : pOverlapped,\r
+ (IO_STATUS_BLOCK*)&pOverlapped->Internal,\r
+ UAL_NDI_NOTIFY_CQ,\r
+ &ioctl,\r
+ sizeof(ioctl),\r
+ NULL,\r
+ 0 );\r
+\r
+ if( hr == ND_PENDING && Type != ND_CQ_NOTIFY_ERRORS )\r
+ {\r
+ m_pParent->m_Ifc.user_verbs.rearm_cq(\r
+ m_uCq,\r
+ (Type == ND_CQ_NOTIFY_SOLICITED) ? TRUE : FALSE\r
+ );\r
+ ND_PRINT( TRACE_LEVEL_VERBOSE, ND_DBG_NDI,\r
+ ("==> %s, rearming with Type %d\n", __FUNCTION__, Type));\r
+ }\r
+ else\r
+ {\r
+ ND_PRINT( TRACE_LEVEL_ERROR, ND_DBG_NDI,\r
+ ("==> %s failed: hr %#x, notify_type %d \n", __FUNCTION__, hr, Type ));\r
+ }\r
+ return hr;\r
+ }\r
+\r
+ SIZE_T CCq::GetResults(\r
+ __out_ecount(nResults) ND_RESULT* pResults[],\r
+ __in SIZE_T nResults\r
+ )\r
+ {\r
+#if DBG \r
+ if (!(++g.c_cnt % 100000000)) // || !(rcv_pkts % 1000) || !(snd_pkts % 1000)\r
+ ND_PRINT( TRACE_LEVEL_VERBOSE, ND_DBG_NDI,\r
+ ("==> %s, cnt %I64d, rcv: %I64d:%I64d:%I64d, snd %I64d:%I64d:%I64d\n", \r
+ __FUNCTION__, g.c_cnt, \r
+ g.c_rcv_pkts, g.c_rcv_bytes, g.c_rcv_pkts_err,\r
+ g.c_snd_pkts, g.c_snd_bytes, g.c_snd_pkts_err));\r
+#endif \r
+ SIZE_T i = 0;\r
+\r
+ while( nResults-- )\r
+ {\r
+ ib_wc_t wc;\r
+ ib_wc_t* pWc = &wc;\r
+ ib_wc_t* pDoneWc;\r
+ wc.p_next = NULL;\r
+ ib_api_status_t status =\r
+ m_pParent->m_Ifc.user_verbs.poll_cq( m_uCq, &pWc, &pDoneWc );\r
+\r
+ if( status != IB_SUCCESS )\r
+ break;\r
+\r
+ pResults[i] = (ND_RESULT*)wc.wr_id;\r
+ if( wc.wc_type == IB_WC_RECV )\r
+ pResults[i]->BytesTransferred = wc.length;\r
+\r
+ if( wc.recv.conn.recv_opt & IB_RECV_OPT_IMMEDIATE )\r
+ {\r
+ // Emulated receive with invalidate - the immediate\r
+ // data holds the RKey that is supposed to be invalidated.\r
+\r
+ //TODO: We need the QP handle (or context) so we can force an\r
+ // error if we don't find a matching MW for the given RKEY.\r
+ // We also need to change the receive status in this case to\r
+ // ND_INVALIDATION_ERROR;\r
+ }\r
+\r
+ switch( wc.status )\r
+ {\r
+ case IB_WCS_SUCCESS:\r
+ pResults[i]->Status = ND_SUCCESS;\r
+ break;\r
+ case IB_WCS_LOCAL_LEN_ERR:\r
+ pResults[i]->Status = ND_LOCAL_LENGTH;\r
+ break;\r
+ case IB_WCS_LOCAL_OP_ERR:\r
+ case IB_WCS_LOCAL_ACCESS_ERR:\r
+ case IB_WCS_GENERAL_ERR:\r
+ default:\r
+ pResults[i]->Status = ND_INTERNAL_ERROR;\r
+ break;\r
+ case IB_WCS_LOCAL_PROTECTION_ERR:\r
+ case IB_WCS_MEM_WINDOW_BIND_ERR:\r
+ pResults[i]->Status = ND_ACCESS_VIOLATION;\r
+ break;\r
+ case IB_WCS_WR_FLUSHED_ERR:\r
+ pResults[i]->Status = ND_CANCELED;\r
+ break;\r
+ case IB_WCS_REM_INVALID_REQ_ERR:\r
+ pResults[i]->Status = ND_BUFFER_OVERFLOW;\r
+ break;\r
+ case IB_WCS_REM_ACCESS_ERR:\r
+ case IB_WCS_REM_OP_ERR:\r
+ case IB_WCS_BAD_RESP_ERR:\r
+ pResults[i]->Status = ND_REMOTE_ERROR;\r
+ break;\r
+ case IB_WCS_RNR_RETRY_ERR:\r
+ case IB_WCS_TIMEOUT_RETRY_ERR:\r
+ pResults[i]->Status = ND_TIMEOUT;\r
+ break;\r
+ }\r
+ i++;\r
+ // leo\r
+#if DBG\r
+ {\r
+ if (wc.wc_type == IB_WC_RECV)\r
+ { \r
+ if (!wc.status)\r
+ {\r
+ ++g.c_rcv_pkts;\r
+ g.c_rcv_bytes += wc.length;\r
+ }\r
+ else\r
+ ++g.c_rcv_pkts_err;\r
+ }\r
+ else\r
+ { \r
+ if (!wc.status)\r
+ {\r
+ ++g.c_snd_pkts;\r
+ g.c_snd_bytes += wc.length;\r
+ }\r
+ else\r
+ ++g.c_snd_pkts_err;\r
+ }\r
+ }\r
+#endif\r
+ continue;\r
+ }\r
+ return i;\r
+ }\r
+\r
+ HRESULT CCq::CreateCq(\r
+ __in UINT32 nEntries )\r
+ {\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ /* Clear the IOCTL buffer */\r
+ ual_create_cq_ioctl_t cq_ioctl;\r
+ cl_memclr( &cq_ioctl, sizeof(cq_ioctl) );\r
+\r
+ /* Pre call to the UVP library */\r
+ ib_api_status_t status;\r
+ if( m_pParent->m_uCa && m_pParent->m_Ifc.user_verbs.pre_create_cq )\r
+ {\r
+ status = m_pParent->m_Ifc.user_verbs.pre_create_cq(\r
+ m_pParent->m_uCa,\r
+ &nEntries,\r
+ &cq_ioctl.in.umv_buf,\r
+ (ib_cq_handle_t*)(ULONG_PTR)&m_uCq\r
+ );\r
+ if( status != IB_SUCCESS )\r
+ goto done;\r
+ }\r
+\r
+ cq_ioctl.in.h_ca = m_pParent->m_hCa;\r
+ cq_ioctl.in.size = nEntries;\r
+ cq_ioctl.in.h_wait_obj = NULL;\r
+ cq_ioctl.in.context = (ULONG_PTR)this;\r
+ cq_ioctl.in.ev_notify = FALSE;\r
+\r
+ DWORD BytesRet;\r
+ BOOL fSuccess = DeviceIoControl(\r
+ m_pParent->m_hSync,\r
+ UAL_NDI_CREATE_CQ,\r
+ &cq_ioctl.in,\r
+ sizeof(cq_ioctl.in),\r
+ &cq_ioctl.out,\r
+ sizeof(cq_ioctl.out),\r
+ &BytesRet,\r
+ NULL\r
+ );\r
+\r
+ if( fSuccess != TRUE || BytesRet != sizeof(cq_ioctl.out) )\r
+ status = IB_ERROR;\r
+ else\r
+ status = cq_ioctl.out.status;\r
+\r
+ m_hCq = cq_ioctl.out.h_cq;\r
+\r
+ /* Post uvp call */\r
+ if( m_pParent->m_uCa && m_pParent->m_Ifc.user_verbs.post_create_cq )\r
+ {\r
+ m_pParent->m_Ifc.user_verbs.post_create_cq(\r
+ m_pParent->m_uCa,\r
+ status,\r
+ cq_ioctl.out.size,\r
+ (ib_cq_handle_t*)(ULONG_PTR)&m_uCq,\r
+ &cq_ioctl.out.umv_buf );\r
+ }\r
+\r
+done:\r
+ switch( status )\r
+ {\r
+ case IB_INVALID_CQ_SIZE:\r
+ return ND_INVALID_PARAMETER;\r
+\r
+ case IB_INSUFFICIENT_RESOURCES:\r
+ return ND_INSUFFICIENT_RESOURCES;\r
+\r
+ case IB_INSUFFICIENT_MEMORY:\r
+ return ND_NO_MEMORY;\r
+\r
+ case IB_SUCCESS:\r
+ return S_OK;\r
+\r
+ default:\r
+ return ND_UNSUCCESSFUL;\r
+ }\r
+ }\r
+\r
+ void CCq::CloseCq(void)\r
+ {\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ ib_api_status_t status;\r
+\r
+ if( m_uCq && m_pParent->m_Ifc.user_verbs.pre_destroy_cq )\r
+ {\r
+ /* Pre call to the UVP library */\r
+ status = m_pParent->m_Ifc.user_verbs.pre_destroy_cq( m_uCq );\r
+ if( status != IB_SUCCESS )\r
+ return;\r
+ }\r
+\r
+ DWORD BytesRet;\r
+ BOOL fSuccess = DeviceIoControl(\r
+ m_pParent->m_hSync,\r
+ UAL_DESTROY_CQ,\r
+ &m_hCq,\r
+ sizeof(m_hCq),\r
+ &status,\r
+ sizeof(status),\r
+ &BytesRet,\r
+ NULL\r
+ );\r
+\r
+ if( fSuccess != TRUE || BytesRet != sizeof(status) )\r
+ status = IB_ERROR;\r
+\r
+ if( m_uCq && m_pParent->m_Ifc.user_verbs.post_destroy_cq )\r
+ m_pParent->m_Ifc.user_verbs.post_destroy_cq( m_uCq, status );\r
+ }\r
+\r
+} // namespace\r
--- /dev/null
+/*\r
+ * Copyright (c) 2008 Microsoft Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ * - Redistributions of source code must retain the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer.\r
+ *\r
+ * - Redistributions in binary form must reproduce the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer in the documentation and/or other materials\r
+ * provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id:$\r
+ */\r
+\r
+#pragma once\r
+#include "ndspi.h"\r
+#include <iba/ib_al.h>\r
+#include "al_cq.h"\r
+\r
+\r
+namespace NetworkDirect\r
+{\r
+ class CAdapter;\r
+\r
+ class CCq :\r
+ public INDCompletionQueue\r
+ {\r
+ friend class CEndpoint;\r
+ public:\r
+ CCq(void);\r
+ ~CCq(void);\r
+\r
+ HRESULT Initialize(\r
+ CAdapter* pParent,\r
+ SIZE_T nEntries );\r
+\r
+ // *** IUnknown methods ***\r
+ HRESULT STDMETHODCALLTYPE QueryInterface(\r
+ REFIID riid,\r
+ LPVOID FAR* ppvObj\r
+ );\r
+\r
+ ULONG STDMETHODCALLTYPE AddRef(void);\r
+\r
+ ULONG STDMETHODCALLTYPE Release(void);\r
+\r
+ // *** INDOverlapped methods ***\r
+ HRESULT STDMETHODCALLTYPE CancelOverlappedRequests(void);\r
+\r
+ HRESULT STDMETHODCALLTYPE GetOverlappedResult(\r
+ __inout_opt OVERLAPPED *pOverlapped,\r
+ __out SIZE_T *pNumberOfBytesTransferred,\r
+ __in BOOL bWait\r
+ );\r
+\r
+ // *** INDCompletionQueue methods ***\r
+ HANDLE STDMETHODCALLTYPE GetAdapterFileHandle(void);\r
+\r
+ HRESULT STDMETHODCALLTYPE Close(void);\r
+\r
+ HRESULT STDMETHODCALLTYPE Resize(\r
+ __in SIZE_T nEntries\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE Notify(\r
+ __in DWORD Type,\r
+ __inout_opt OVERLAPPED* pOverlapped\r
+ );\r
+\r
+ SIZE_T STDMETHODCALLTYPE GetResults(\r
+ __out_ecount(nResults) ND_RESULT* pResults[],\r
+ __in SIZE_T nResults\r
+ );\r
+\r
+ private:\r
+ HRESULT CreateCq(\r
+ __in UINT32 nEntries );\r
+\r
+ HRESULT Complete(\r
+ __in HRESULT Status );\r
+\r
+ HRESULT ModifyCq(\r
+ __in SIZE_T nEntries );\r
+\r
+ void CloseCq(void);\r
+\r
+ private:\r
+ volatile LONG m_nRef;\r
+\r
+ CAdapter* m_pParent;\r
+\r
+ UINT64 m_hCq;\r
+ ib_cq_handle_t m_uCq;\r
+ };\r
+\r
+} // namespace\r
--- /dev/null
+/*\r
+ * Copyright (c) 2008 Microsoft Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ * - Redistributions of source code must retain the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer.\r
+ *\r
+ * - Redistributions in binary form must reproduce the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer in the documentation and/or other materials\r
+ * provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id:$\r
+ */\r
+\r
+#include "NdEndpoint.h"\r
+#include "NdCq.h"\r
+#include "NdAdapter.h"\r
+#include "NdMr.h"\r
+#include "NdListen.h"\r
+#include "limits.h"\r
+#include "al_dev.h"\r
+#pragma warning( push, 3 )\r
+#include "winternl.h"\r
+#pragma warning( pop )\r
+#include "nddebug.h"\r
+\r
+#if defined(EVENT_TRACING)\r
+#ifdef offsetof\r
+#undef offsetof\r
+#endif\r
+#include "NdEndpoint.tmh"\r
+#endif\r
+\r
+#if DBG\r
+dbg_data g = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };\r
+#endif\r
+\r
+#ifndef SIZE_MAX\r
+#ifdef _WIN64\r
+#define SIZE_MAX _UI64_MAX\r
+#else\r
+#define SIZE_MAX UINT_MAX\r
+#endif\r
+#endif\r
+\r
+namespace NetworkDirect\r
+{\r
+\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// HPC Pack 2008 Beta 2 SPI\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+\r
+CEndpoint::CEndpoint(void) :\r
+ m_nRef( 1 ),\r
+ m_pParent( NULL ),\r
+ m_hQp( 0 )\r
+{\r
+}\r
+\r
+CEndpoint::~CEndpoint(void)\r
+{\r
+ if( m_hQp )\r
+ DestroyQp();\r
+\r
+ if( m_pParent )\r
+ m_pParent->Release();\r
+}\r
+\r
+HRESULT CEndpoint::Initialize(\r
+ __in CAdapter* pParent,\r
+ __in CCq* pInboundCq,\r
+ __in CCq* pOutboundCq,\r
+ __in SIZE_T nInboundEntries,\r
+ __in SIZE_T nOutboundEntries,\r
+ __in SIZE_T nInboundSge,\r
+ __in SIZE_T nOutboundSge,\r
+ __in SIZE_T InboundReadLimit,\r
+ __in SIZE_T OutboundReadLimit,\r
+ __out_opt SIZE_T* pMaxInlineData\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ if( InboundReadLimit > UCHAR_MAX )\r
+ return ND_INVALID_PARAMETER_8;\r
+\r
+ if( OutboundReadLimit > UCHAR_MAX )\r
+ return ND_INVALID_PARAMETER_9;\r
+\r
+ m_pParent = pParent;\r
+ m_pParent->AddRef();\r
+\r
+ CL_ASSERT(\r
+ m_pParent->m_Ifc.user_verbs.pre_create_qp != NULL ||\r
+ m_pParent->m_Ifc.user_verbs.post_create_qp != NULL ||\r
+ m_pParent->m_Ifc.user_verbs.nd_modify_qp != NULL ||\r
+ m_pParent->m_Ifc.user_verbs.nd_get_qp_state != NULL ||\r
+ m_pParent->m_Ifc.user_verbs.pre_destroy_qp != NULL ||\r
+ m_pParent->m_Ifc.user_verbs.post_destroy_qp != NULL ||\r
+ m_pParent->m_Ifc.user_verbs.post_send != NULL ||\r
+ m_pParent->m_Ifc.user_verbs.post_recv != NULL /*||\r
+ m_pParent->m_Ifc.user_verbs.bind_mw != NULL*/ );\r
+\r
+ HRESULT hr = CreateQp(\r
+ pInboundCq,\r
+ pOutboundCq,\r
+ nInboundEntries,\r
+ nOutboundEntries,\r
+ nInboundSge,\r
+ nOutboundSge,\r
+ InboundReadLimit,\r
+ OutboundReadLimit );\r
+\r
+ if( FAILED( hr ) )\r
+ return hr;\r
+\r
+ m_Ird = (UINT8)InboundReadLimit;\r
+ m_Ord = (UINT8)OutboundReadLimit;\r
+\r
+ // Move the QP to the INIT state so users can post receives.\r
+ hr = ModifyQp( IB_QPS_INIT );\r
+ if( FAILED( hr ) )\r
+ DestroyQp();\r
+\r
+ if( SUCCEEDED( hr ) && pMaxInlineData != NULL )\r
+ {\r
+ // Worst case.\r
+ *pMaxInlineData = nOutboundSge * 12;\r
+ }\r
+\r
+ return hr;\r
+}\r
+\r
+HRESULT CEndpoint::Create(\r
+ __in CAdapter* pParent,\r
+ __in CCq* pInboundCq,\r
+ __in CCq* pOutboundCq,\r
+ __in SIZE_T nInboundEntries,\r
+ __in SIZE_T nOutboundEntries,\r
+ __in SIZE_T nInboundSge,\r
+ __in SIZE_T nOutboundSge,\r
+ __in SIZE_T InboundReadLimit,\r
+ __in SIZE_T OutboundReadLimit,\r
+ __out_opt SIZE_T* pMaxInlineData,\r
+ __out INDEndpoint** ppEndpoint\r
+ )\r
+{\r
+ CEndpoint* pEp = new CEndpoint();\r
+ if( pEp == NULL )\r
+ return ND_NO_MEMORY;\r
+\r
+ HRESULT hr = pEp->Initialize(\r
+ pParent,\r
+ pInboundCq,\r
+ pOutboundCq,\r
+ nInboundEntries,\r
+ nOutboundEntries,\r
+ nInboundSge,\r
+ nOutboundSge,\r
+ InboundReadLimit,\r
+ OutboundReadLimit,\r
+ pMaxInlineData\r
+ );\r
+\r
+ if( FAILED( hr ) )\r
+ {\r
+ pEp->Release();\r
+ return hr;\r
+ }\r
+\r
+ *ppEndpoint = pEp;\r
+ return ND_SUCCESS;\r
+}\r
+\r
+HRESULT CEndpoint::QueryInterface(\r
+ REFIID riid,\r
+ LPVOID FAR* ppvObj\r
+ )\r
+{\r
+ if( IsEqualIID( riid, IID_IUnknown ) )\r
+ {\r
+ *ppvObj = this;\r
+ return S_OK;\r
+ }\r
+\r
+ if( IsEqualIID( riid, IID_INDEndpoint ) )\r
+ {\r
+ *ppvObj = this;\r
+ return S_OK;\r
+ }\r
+\r
+ return E_NOINTERFACE;\r
+}\r
+\r
+ULONG CEndpoint::AddRef(void)\r
+{\r
+ return InterlockedIncrement( &m_nRef );\r
+}\r
+\r
+ULONG CEndpoint::Release(void)\r
+{\r
+ ULONG ref = InterlockedDecrement( &m_nRef );\r
+ if( ref == 0 )\r
+ delete this;\r
+\r
+ return ref;\r
+}\r
+\r
+// *** INDEndpoint methods ***\r
+HRESULT CEndpoint::Flush(void)\r
+{\r
+ return ModifyQp( IB_QPS_ERROR );\r
+}\r
+\r
+void CEndpoint::StartRequestBatch(void)\r
+{\r
+ return;\r
+}\r
+\r
+void CEndpoint::SubmitRequestBatch(void)\r
+{\r
+ return;\r
+}\r
+\r
+HRESULT CEndpoint::Send(\r
+ __out ND_RESULT* pResult,\r
+ __in_ecount(nSge) const ND_SGE* pSgl,\r
+ __in SIZE_T nSge,\r
+ __in DWORD Flags\r
+ )\r
+{\r
+ ib_send_wr_t wr;\r
+ ib_local_ds_t* pDs;\r
+ ib_local_ds_t ds[4];\r
+\r
+ if( nSge > UINT_MAX )\r
+ return ND_DATA_OVERRUN;\r
+ else if( nSge <= 4 )\r
+ pDs = ds;\r
+ else\r
+ {\r
+ pDs = new ib_local_ds_t[nSge];\r
+ if( !pDs )\r
+ return ND_NO_MEMORY;\r
+ }\r
+\r
+ pResult->BytesTransferred = 0;\r
+ for( SIZE_T i = 0; i < nSge; i++ )\r
+ {\r
+ pDs[i].vaddr = (ULONG_PTR)pSgl[i].pAddr;\r
+ if( pSgl[i].Length > UINT_MAX )\r
+ {\r
+ if( nSge > 4 )\r
+ delete[] pDs;\r
+ return ND_BUFFER_OVERFLOW;\r
+ }\r
+ pDs[i].length = (uint32_t)pSgl[i].Length;\r
+ pDs[i].lkey = ((CMr*)pSgl[i].hMr)->mr_ioctl.out.lkey;\r
+\r
+ // Send completions don't include the length. It's going to\r
+ // be all or nothing, so store it now and we can reset if the\r
+ // request fails.\r
+ pResult->BytesTransferred += pSgl[i].Length;\r
+ }\r
+\r
+ wr.p_next = NULL;\r
+ wr.wr_id = (ULONG_PTR)pResult;\r
+ wr.wr_type = WR_SEND;\r
+ wr.send_opt = 0;\r
+ if( !(Flags & ND_OP_FLAG_SILENT_SUCCESS) )\r
+ wr.send_opt |= IB_SEND_OPT_SIGNALED;\r
+ if( Flags & ND_OP_FLAG_READ_FENCE )\r
+ wr.send_opt |= IB_SEND_OPT_FENCE;\r
+ if( Flags & ND_OP_FLAG_SEND_AND_SOLICIT_EVENT )\r
+ wr.send_opt |= IB_SEND_OPT_SOLICITED;\r
+ wr.num_ds = (uint32_t)nSge;\r
+ wr.ds_array = pDs;\r
+\r
+ ib_api_status_t status =\r
+ m_pParent->m_Ifc.user_verbs.post_send( m_uQp, &wr, NULL );\r
+ if( nSge > 4 )\r
+ delete[] pDs;\r
+\r
+ // leo\r
+ CL_ASSERT( nSge || pSgl == NULL );\r
+#if DBG\r
+ if (!status )\r
+ {\r
+ if (pSgl)\r
+ {\r
+ ++g.snd_pkts;\r
+ g.snd_bytes += pSgl[0].Length;\r
+ }\r
+ else\r
+ ++g.snd_pkts_zero;\r
+ }\r
+ else\r
+ ++g.snd_pkts_err;\r
+#endif\r
+\r
+ switch( status )\r
+ {\r
+ case IB_SUCCESS:\r
+ return S_OK;\r
+ case IB_INSUFFICIENT_RESOURCES:\r
+ return ND_NO_MORE_ENTRIES;\r
+ case IB_INVALID_MAX_SGE:\r
+ return ND_DATA_OVERRUN;\r
+ case IB_INVALID_QP_STATE:\r
+ return ND_CONNECTION_INVALID;\r
+ default:\r
+ return ND_UNSUCCESSFUL;\r
+ }\r
+}\r
+\r
+HRESULT CEndpoint::SendAndInvalidate(\r
+ __out ND_RESULT* pResult,\r
+ __in_ecount(nSge) const ND_SGE* pSgl,\r
+ __in SIZE_T nSge,\r
+ __in const ND_MW_DESCRIPTOR* pRemoteMwDescriptor,\r
+ __in DWORD Flags\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ ib_send_wr_t wr;\r
+ ib_local_ds_t* pDs;\r
+\r
+ if( nSge > UINT_MAX )\r
+ return ND_DATA_OVERRUN;\r
+\r
+ pDs = new ib_local_ds_t[nSge];\r
+ if( !pDs )\r
+ return ND_NO_MEMORY;\r
+\r
+ pResult->BytesTransferred = 0;\r
+ for( SIZE_T i = 0; i < nSge; i++ )\r
+ {\r
+ pDs[i].vaddr = (ULONG_PTR)pSgl[i].pAddr;\r
+ if( pSgl[i].Length > UINT_MAX )\r
+ {\r
+ delete[] pDs;\r
+ return ND_BUFFER_OVERFLOW;\r
+ }\r
+ pDs[i].length = (uint32_t)pSgl[i].Length;\r
+ pDs[i].lkey = ((CMr*)pSgl[i].hMr)->mr_ioctl.out.lkey;\r
+\r
+ // Send completions don't include the length. It's going to\r
+ // be all or nothing, so store it now and we can reset if the\r
+ // request fails.\r
+ pResult->BytesTransferred += pSgl[i].Length;\r
+ }\r
+\r
+ wr.p_next = NULL;\r
+ wr.wr_id = (ULONG_PTR)pResult;\r
+ wr.wr_type = WR_SEND;\r
+ // We simulate invalidate operations (since we simulate MW use). We\r
+ // put the RKey in the immediate data, the recipient will do the\r
+ // lookup of the MW based on that (as they would with a regular\r
+ // invalidate request).\r
+ wr.send_opt = IB_SEND_OPT_IMMEDIATE;\r
+ if( !(Flags & ND_OP_FLAG_SILENT_SUCCESS) )\r
+ wr.send_opt |= IB_SEND_OPT_SIGNALED;\r
+ if( Flags & ND_OP_FLAG_READ_FENCE )\r
+ wr.send_opt |= IB_SEND_OPT_FENCE;\r
+ if( Flags & ND_OP_FLAG_SEND_AND_SOLICIT_EVENT )\r
+ wr.send_opt |= IB_SEND_OPT_SOLICITED;\r
+ wr.num_ds = (uint32_t)nSge;\r
+ wr.ds_array = pDs;\r
+ // Put the RKey in the immeditate data.\r
+ wr.immediate_data = pRemoteMwDescriptor->Token;\r
+\r
+ ib_api_status_t status =\r
+ m_pParent->m_Ifc.user_verbs.post_send( m_uQp, &wr, NULL );\r
+ delete[] pDs;\r
+\r
+ switch( status )\r
+ {\r
+ case IB_SUCCESS:\r
+ return S_OK;\r
+ case IB_INSUFFICIENT_RESOURCES:\r
+ return ND_NO_MORE_ENTRIES;\r
+ case IB_INVALID_MAX_SGE:\r
+ return ND_DATA_OVERRUN;\r
+ case IB_INVALID_QP_STATE:\r
+ return ND_CONNECTION_INVALID;\r
+ default:\r
+ return ND_UNSUCCESSFUL;\r
+ }\r
+}\r
+\r
+HRESULT CEndpoint::Receive(\r
+ __out ND_RESULT* pResult,\r
+ __in_ecount(nSge) const ND_SGE* pSgl,\r
+ __in SIZE_T nSge\r
+ )\r
+{\r
+#if DBG \r
+ if (!(++g.rcv_cnt % 1000))\r
+ ND_PRINT( TRACE_LEVEL_VERBOSE, ND_DBG_NDI,\r
+ ("==> %s, cnt %I64d, rcv %I64d:%I64d:%I64d:%I64d\n",\r
+ __FUNCTION__, g.rcv_cnt, g.rcv_pkts, g.rcv_bytes, g.rcv_pkts_err, g.rcv_pkts_zero ));\r
+#endif\r
+ ib_recv_wr_t wr;\r
+ ib_local_ds_t* pDs;\r
+ ib_local_ds_t ds[4];\r
+\r
+ if( nSge > UINT_MAX )\r
+ return ND_DATA_OVERRUN;\r
+ else if( nSge <= 4 )\r
+ pDs = ds;\r
+ else\r
+ {\r
+ pDs = new ib_local_ds_t[nSge];\r
+ if( !pDs )\r
+ return ND_NO_MEMORY;\r
+ }\r
+\r
+ for( SIZE_T i = 0; i < nSge; i++ )\r
+ {\r
+ pDs[i].vaddr = (ULONG_PTR)pSgl[i].pAddr;\r
+ if( pSgl[i].Length > UINT_MAX )\r
+ {\r
+ if( nSge > 4 )\r
+ delete[] pDs;\r
+ return ND_BUFFER_OVERFLOW;\r
+ }\r
+ pDs[i].length = (uint32_t)pSgl[i].Length;\r
+ pDs[i].lkey = ((CMr*)pSgl[i].hMr)->mr_ioctl.out.lkey;\r
+ }\r
+\r
+ wr.p_next = NULL;\r
+ wr.wr_id = (ULONG_PTR)pResult;\r
+ wr.num_ds = (uint32_t)nSge;\r
+ wr.ds_array = pDs;\r
+\r
+ ib_api_status_t status =\r
+ m_pParent->m_Ifc.user_verbs.post_recv( m_uQp, &wr, NULL );\r
+\r
+ if( nSge > 4 )\r
+ delete[] pDs;\r
+\r
+ // leo\r
+ CL_ASSERT( nSge || pSgl == NULL );\r
+#if DBG\r
+ if (!status)\r
+ {\r
+ if (pSgl)\r
+ {\r
+ ++g.rcv_pkts;\r
+ g.rcv_bytes += pSgl[0].Length;\r
+ }\r
+ else\r
+ ++g.rcv_pkts_zero;\r
+ }\r
+ else\r
+ ++g.rcv_pkts_err;\r
+#endif\r
+\r
+ switch( status )\r
+ {\r
+ case IB_SUCCESS:\r
+ return S_OK;\r
+ case IB_INSUFFICIENT_RESOURCES:\r
+ return ND_NO_MORE_ENTRIES;\r
+ case IB_INVALID_MAX_SGE:\r
+ return ND_DATA_OVERRUN;\r
+ case IB_INVALID_QP_STATE:\r
+ return ND_CONNECTION_INVALID;\r
+ default:\r
+ return ND_UNSUCCESSFUL;\r
+ }\r
+}\r
+\r
+HRESULT CEndpoint::Bind(\r
+ __out ND_RESULT* pResult,\r
+ __in ND_MR_HANDLE hMr,\r
+ __in INDMemoryWindow* pMw,\r
+ __in_bcount(BufferSize) const void* pBuffer,\r
+ __in SIZE_T BufferSize,\r
+ __in DWORD Flags,\r
+ __out ND_MW_DESCRIPTOR* pMwDescriptor\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ UNREFERENCED_PARAMETER( pMw );\r
+ UNREFERENCED_PARAMETER( Flags );\r
+\r
+ CMr* pMr = ((CMr*)hMr);\r
+\r
+ if( pBuffer < pMr->pBase ||\r
+ pBuffer > pMr->pBase + pMr->Length )\r
+ {\r
+ return ND_INVALID_PARAMETER_4;\r
+ }\r
+\r
+ if( ((const char*)pBuffer + BufferSize) > (pMr->pBase + pMr->Length) )\r
+ {\r
+ return ND_INVALID_PARAMETER_5;\r
+ }\r
+\r
+ // Ok, this here is a workaround since the Mellanox HCA driver doesn't\r
+ // support MWs. This should be pushed into the HCA driver.\r
+ pMwDescriptor->Base = _byteswap_uint64( (UINT64)(ULONG_PTR)pBuffer );\r
+ pMwDescriptor->Length = _byteswap_uint64( BufferSize );\r
+ pMwDescriptor->Token = pMr->mr_ioctl.out.rkey;\r
+\r
+ // Zero-byte RDMA write. Could also be a no-op on the send queue\r
+ // which would be better, but requires changing the HCA driver.\r
+ ib_send_wr_t wr;\r
+ wr.p_next = NULL;\r
+ wr.wr_id = (ULONG_PTR)pResult;\r
+ wr.wr_type = WR_RDMA_WRITE;\r
+ wr.send_opt = IB_SEND_OPT_SIGNALED;\r
+ wr.num_ds = 0;\r
+ wr.ds_array = NULL;\r
+\r
+ wr.remote_ops.vaddr = 0;\r
+ wr.remote_ops.rkey = 0;\r
+\r
+ pResult->BytesTransferred = 0;\r
+\r
+ // TODO: Track the MW by rkey, so we can unbind it.\r
+\r
+ ib_api_status_t status =\r
+ m_pParent->m_Ifc.user_verbs.post_send( m_uQp, &wr, NULL );\r
+\r
+ switch( status )\r
+ {\r
+ case IB_SUCCESS:\r
+ return S_OK;\r
+ case IB_INSUFFICIENT_RESOURCES:\r
+ return ND_NO_MORE_ENTRIES;\r
+ case IB_INVALID_QP_STATE:\r
+ return ND_CONNECTION_INVALID;\r
+ default:\r
+ return ND_UNSUCCESSFUL;\r
+ }\r
+}\r
+\r
+HRESULT CEndpoint::Invalidate(\r
+ __out ND_RESULT* pResult,\r
+ __in INDMemoryWindow* pMw,\r
+ __in DWORD Flags\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ UNREFERENCED_PARAMETER( pMw );\r
+ UNREFERENCED_PARAMETER( Flags );\r
+\r
+ // Zero-byte RDMA write. Could also be a no-op on the send queue\r
+ // which would be better, but requires changing the HCA driver.\r
+ ib_send_wr_t wr;\r
+ wr.p_next = NULL;\r
+ wr.wr_id = (ULONG_PTR)pResult;\r
+ wr.wr_type = WR_RDMA_WRITE;\r
+ wr.send_opt = IB_SEND_OPT_SIGNALED;\r
+ wr.num_ds = 0;\r
+ wr.ds_array = NULL;\r
+\r
+ wr.remote_ops.vaddr = 0;\r
+ wr.remote_ops.rkey = 0;\r
+\r
+ pResult->BytesTransferred = 0;\r
+\r
+ ib_api_status_t status =\r
+ m_pParent->m_Ifc.user_verbs.post_send( m_uQp, &wr, NULL );\r
+\r
+ switch( status )\r
+ {\r
+ case IB_SUCCESS:\r
+ // TODO: Stop trackign MW\r
+ return S_OK;\r
+ case IB_INSUFFICIENT_RESOURCES:\r
+ return ND_NO_MORE_ENTRIES;\r
+ case IB_INVALID_QP_STATE:\r
+ return ND_CONNECTION_INVALID;\r
+ default:\r
+ return ND_UNSUCCESSFUL;\r
+ }\r
+}\r
+\r
+HRESULT CEndpoint::Rdma(\r
+ __out ND_RESULT* pResult,\r
+ __in ib_wr_type_t Type,\r
+ __in_ecount(nSge) const ND_SGE* pSgl,\r
+ __in SIZE_T nSge,\r
+ __in const ND_MW_DESCRIPTOR* pRemoteMwDescriptor,\r
+ __in ULONGLONG Offset,\r
+ __in DWORD Flags\r
+ )\r
+{\r
+// ND_ENTER( ND_DBG_NDI );\r
+\r
+ ib_send_wr_t wr;\r
+ ib_local_ds_t* pDs;\r
+ ib_local_ds_t ds[4];\r
+\r
+ if( nSge > UINT_MAX )\r
+ return ND_DATA_OVERRUN;\r
+ else if( nSge <= 4 )\r
+ pDs = ds;\r
+ else\r
+ {\r
+ pDs = new ib_local_ds_t[nSge];\r
+ if( !pDs )\r
+ return ND_NO_MEMORY;\r
+ }\r
+\r
+ pResult->BytesTransferred = 0;\r
+ for( SIZE_T i = 0; i < nSge; i++ )\r
+ {\r
+ pDs[i].vaddr = (ULONG_PTR)pSgl[i].pAddr;\r
+ if( pSgl[i].Length > UINT_MAX )\r
+ {\r
+ if( nSge > 4 )\r
+ delete[] pDs;\r
+ return ND_BUFFER_OVERFLOW;\r
+ }\r
+ pDs[i].length = (uint32_t)pSgl[i].Length;\r
+ pDs[i].lkey = ((CMr*)pSgl[i].hMr)->mr_ioctl.out.lkey;\r
+\r
+ //TODO: temporary - a workaround of test bug\r
+ //leo\r
+ if( (int)pSgl[i].Length < 0 )\r
+ {\r
+ pDs[i].length = 0 - (int)pSgl[i].Length;\r
+#if DBG \r
+ ND_PRINT( TRACE_LEVEL_VERBOSE, ND_DBG_NDI,\r
+ ("nSge %d, i %d, Length %#x\n", nSge, i, pSgl[i].Length ));\r
+ if( nSge > 4 )\r
+ delete[] pDs;\r
+ return ND_BUFFER_OVERFLOW;\r
+#endif \r
+ }\r
+\r
+ // Send completions don't include the length. It's going to\r
+ // be all or nothing, so store it now and we can reset if the\r
+ // request fails.\r
+ pResult->BytesTransferred += pSgl[i].Length;\r
+ }\r
+\r
+ wr.p_next = NULL;\r
+ wr.wr_id = (ULONG_PTR)pResult;\r
+ wr.wr_type = Type;\r
+ wr.send_opt = 0;\r
+ if( !(Flags & ND_OP_FLAG_SILENT_SUCCESS) )\r
+ wr.send_opt |= IB_SEND_OPT_SIGNALED;\r
+ if( Flags & ND_OP_FLAG_READ_FENCE )\r
+ wr.send_opt |= IB_SEND_OPT_FENCE;\r
+ wr.num_ds = (uint32_t)nSge;\r
+ wr.ds_array = pDs;\r
+\r
+ UINT64 vaddr = _byteswap_uint64( pRemoteMwDescriptor->Base );\r
+ vaddr += Offset;\r
+ wr.remote_ops.vaddr = vaddr;\r
+ wr.remote_ops.rkey = pRemoteMwDescriptor->Token;\r
+\r
+ ib_api_status_t status =\r
+ m_pParent->m_Ifc.user_verbs.post_send( m_uQp, &wr, NULL );\r
+\r
+ if( nSge > 4 )\r
+ delete[] pDs;\r
+\r
+ switch( status )\r
+ {\r
+ case IB_SUCCESS:\r
+ return S_OK;\r
+ case IB_INSUFFICIENT_RESOURCES:\r
+ return ND_NO_MORE_ENTRIES;\r
+ case IB_INVALID_MAX_SGE:\r
+ return ND_DATA_OVERRUN;\r
+ case IB_INVALID_QP_STATE:\r
+ return ND_CONNECTION_INVALID;\r
+ default:\r
+ return ND_UNSUCCESSFUL;\r
+ }\r
+}\r
+\r
+HRESULT CEndpoint::Read(\r
+ __out ND_RESULT* pResult,\r
+ __in_ecount(nSge) const ND_SGE* pSgl,\r
+ __in SIZE_T nSge,\r
+ __in const ND_MW_DESCRIPTOR* pRemoteMwDescriptor,\r
+ __in ULONGLONG Offset,\r
+ __in DWORD Flags\r
+ )\r
+{\r
+// ND_ENTER( ND_DBG_NDI );\r
+\r
+ return Rdma( pResult, WR_RDMA_READ, pSgl, nSge,\r
+ pRemoteMwDescriptor, Offset, Flags );\r
+}\r
+\r
+HRESULT CEndpoint::Write(\r
+ __out ND_RESULT* pResult,\r
+ __in_ecount(nSge) const ND_SGE* pSgl,\r
+ __in SIZE_T nSge,\r
+ __in const ND_MW_DESCRIPTOR* pRemoteMwDescriptor,\r
+ __in ULONGLONG Offset,\r
+ __in DWORD Flags\r
+ )\r
+{\r
+// ND_ENTER( ND_DBG_NDI );\r
+\r
+ return Rdma( pResult, WR_RDMA_WRITE, pSgl, nSge,\r
+ pRemoteMwDescriptor, Offset, Flags );\r
+}\r
+\r
+HRESULT CEndpoint::CreateQp(\r
+ __in CCq* pInboundCq,\r
+ __in CCq* pOutboundCq,\r
+ __in SIZE_T nInboundEntries,\r
+ __in SIZE_T nOutboundEntries,\r
+ __in SIZE_T nInboundSge,\r
+ __in SIZE_T nOutboundSge,\r
+ __in SIZE_T InboundReadLimit,\r
+ __in SIZE_T OutboundReadLimit\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ if( nInboundEntries > UINT_MAX )\r
+ return ND_INVALID_PARAMETER_4;\r
+ if( nOutboundEntries > UINT_MAX )\r
+ return ND_INVALID_PARAMETER_5;\r
+ if( nInboundSge > UINT_MAX )\r
+ return ND_INVALID_PARAMETER_6;\r
+ if( nOutboundSge > UINT_MAX )\r
+ return ND_INVALID_PARAMETER_7;\r
+ if( InboundReadLimit > UCHAR_MAX )\r
+ return ND_INVALID_PARAMETER_9;\r
+ if( OutboundReadLimit > UCHAR_MAX )\r
+ return ND_INVALID_PARAMETER_10;\r
+\r
+ /* Setup the qp_ioctl */\r
+ ual_create_qp_ioctl_t qp_ioctl;\r
+ cl_memclr( &qp_ioctl, sizeof(qp_ioctl) );\r
+\r
+ qp_ioctl.in.qp_create.qp_type = IB_QPT_RELIABLE_CONN;\r
+ qp_ioctl.in.qp_create.sq_depth = (uint32_t)nOutboundEntries;\r
+ qp_ioctl.in.qp_create.rq_depth = (uint32_t)nInboundEntries;\r
+ qp_ioctl.in.qp_create.sq_sge = (uint32_t)nOutboundSge;\r
+ qp_ioctl.in.qp_create.rq_sge = (uint32_t)nInboundSge;\r
+ qp_ioctl.in.qp_create.h_srq = NULL;\r
+ qp_ioctl.in.qp_create.sq_signaled = FALSE;\r
+\r
+ /* Pre call to the UVP library */\r
+ CL_ASSERT( m_pParent->m_Ifc.user_verbs.pre_create_qp );\r
+ qp_ioctl.in.qp_create.h_sq_cq = pOutboundCq->m_uCq;\r
+ qp_ioctl.in.qp_create.h_rq_cq = pInboundCq->m_uCq;\r
+ ib_api_status_t status = m_pParent->m_Ifc.user_verbs.pre_create_qp(\r
+ m_pParent->m_uPd,\r
+ &qp_ioctl.in.qp_create,\r
+ &qp_ioctl.in.umv_buf,\r
+ (ib_qp_handle_t*)(ULONG_PTR)&m_uQp\r
+ );\r
+ if( status != IB_SUCCESS )\r
+ return ND_INSUFFICIENT_RESOURCES;\r
+\r
+ /*\r
+ * Convert the handles to KAL handles once again starting\r
+ * from the input qp attribute\r
+ */\r
+ qp_ioctl.in.h_pd = m_pParent->m_hPd;\r
+ qp_ioctl.in.qp_create.h_sq_cq = (ib_cq_handle_t)pOutboundCq->m_hCq;\r
+ qp_ioctl.in.qp_create.h_rq_cq = (ib_cq_handle_t)pInboundCq->m_hCq;\r
+ qp_ioctl.in.context = (ULONG_PTR)this;\r
+ qp_ioctl.in.ev_notify = FALSE;\r
+\r
+ DWORD bytes_ret;\r
+ BOOL fSuccess = DeviceIoControl(\r
+ m_pParent->m_hSync,\r
+ UAL_CREATE_QP,\r
+ &qp_ioctl.in,\r
+ sizeof(qp_ioctl.in),\r
+ &qp_ioctl.out,\r
+ sizeof(qp_ioctl.out),\r
+ &bytes_ret,\r
+ NULL );\r
+\r
+ if( fSuccess != TRUE || bytes_ret != sizeof(qp_ioctl.out) )\r
+ qp_ioctl.out.status = IB_ERROR;\r
+\r
+ /* Post uvp call */\r
+ CL_ASSERT( m_pParent->m_Ifc.user_verbs.post_create_qp );\r
+ m_pParent->m_Ifc.user_verbs.post_create_qp(\r
+ m_pParent->m_uPd,\r
+ qp_ioctl.out.status,\r
+ (ib_qp_handle_t*)(ULONG_PTR)&m_uQp,\r
+ &qp_ioctl.out.umv_buf\r
+ );\r
+\r
+\r
+ switch( qp_ioctl.out.status )\r
+ {\r
+ case IB_SUCCESS:\r
+ m_hQp = qp_ioctl.out.h_qp;\r
+ m_Qpn = qp_ioctl.out.attr.num;\r
+ ND_PRINT( TRACE_LEVEL_INFORMATION, ND_DBG_NDI,\r
+ ("Created QP %#I64x, QPn %#x, pd %#I64x, context %p \n", \r
+ m_hQp, m_Qpn, m_pParent->m_hPd, this ) );\r
+ return S_OK;\r
+\r
+ case IB_INVALID_MAX_WRS:\r
+ if( nInboundEntries > nOutboundEntries )\r
+ return ND_INVALID_PARAMETER_4;\r
+ else\r
+ return ND_INVALID_PARAMETER_5;\r
+\r
+ case IB_INVALID_MAX_SGE:\r
+ if( nInboundSge > nOutboundSge )\r
+ return ND_INVALID_PARAMETER_6;\r
+ else\r
+ return ND_INVALID_PARAMETER_7;\r
+\r
+ case IB_INSUFFICIENT_MEMORY:\r
+ return ND_NO_MEMORY;\r
+\r
+ default:\r
+ return ND_INSUFFICIENT_RESOURCES;\r
+ }\r
+}\r
+\r
+void CEndpoint::DestroyQp()\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ /* Call the uvp pre call if the vendor library provided a valid QP handle */\r
+ CL_ASSERT( m_pParent->m_Ifc.user_verbs.pre_destroy_qp );\r
+ m_pParent->m_Ifc.user_verbs.pre_destroy_qp( m_uQp );\r
+\r
+ ual_destroy_qp_ioctl_t qp_ioctl;\r
+ cl_memclr( &qp_ioctl, sizeof(qp_ioctl) );\r
+ qp_ioctl.in.h_qp = m_hQp;\r
+\r
+ ND_PRINT( TRACE_LEVEL_INFORMATION, ND_DBG_NDI,\r
+ ("Destroy QP %I64x\n", m_hQp) );\r
+\r
+ DWORD bytes_ret;\r
+ BOOL fSuccess = DeviceIoControl(\r
+ m_pParent->m_hSync,\r
+ UAL_DESTROY_QP,\r
+ &qp_ioctl.in,\r
+ sizeof(qp_ioctl.in),\r
+ &qp_ioctl.out,\r
+ sizeof(qp_ioctl.out),\r
+ &bytes_ret,\r
+ NULL\r
+ );\r
+\r
+ if( fSuccess != TRUE || bytes_ret != sizeof(qp_ioctl.out) )\r
+ qp_ioctl.out.status = IB_ERROR;\r
+\r
+ ND_PRINT( TRACE_LEVEL_INFORMATION, ND_DBG_NDI,\r
+ ("Destroyed QP %#I64x, QPn %#x, pd %#I64x, context %p \n", \r
+ m_hQp, m_Qpn, m_pParent->m_hPd, this ) );\r
+ \r
+ /* Call vendor's post_destroy_qp */\r
+ CL_ASSERT( m_pParent->m_Ifc.user_verbs.post_destroy_qp );\r
+ m_pParent->m_Ifc.user_verbs.post_destroy_qp(\r
+ m_uQp,\r
+ qp_ioctl.out.status\r
+ );\r
+ m_hQp = NULL;\r
+}\r
+\r
+HRESULT CEndpoint::ModifyQp(\r
+ __in ib_qp_state_t NewState )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ /* Setup the qp_ioctl */\r
+ ual_ndi_modify_qp_ioctl_in_t qp_ioctl;\r
+ cl_memclr( &qp_ioctl, sizeof(qp_ioctl) );\r
+\r
+ switch( NewState )\r
+ {\r
+ case IB_QPS_INIT:\r
+ qp_ioctl.qp_mod.state.init.primary_port = m_pParent->m_PortNum;\r
+ qp_ioctl.qp_mod.state.init.qkey = 0;\r
+ qp_ioctl.qp_mod.state.init.pkey_index = 0;\r
+ qp_ioctl.qp_mod.state.init.access_ctrl =\r
+ IB_AC_LOCAL_WRITE | IB_AC_RDMA_READ | IB_AC_RDMA_WRITE;\r
+\r
+ // Fall through.\r
+ case IB_QPS_RESET:\r
+ case IB_QPS_ERROR:\r
+ qp_ioctl.qp_mod.req_state = NewState;\r
+ }\r
+\r
+ /* Call the uvp ND modify verb */\r
+ CL_ASSERT( m_pParent->m_Ifc.user_verbs.nd_modify_qp );\r
+ void* pOutbuf;\r
+ DWORD szOutbuf;\r
+\r
+ m_pParent->m_Ifc.user_verbs.nd_modify_qp(\r
+ m_uQp,\r
+ &pOutbuf,\r
+ &szOutbuf\r
+ );\r
+\r
+ qp_ioctl.h_qp = m_hQp;\r
+\r
+ DWORD bytes_ret;\r
+ BOOL fSuccess = DeviceIoControl(\r
+ m_pParent->m_hSync,\r
+ UAL_NDI_MODIFY_QP,\r
+ &qp_ioctl,\r
+ sizeof(qp_ioctl),\r
+ pOutbuf,\r
+ szOutbuf,\r
+ &bytes_ret,\r
+ NULL );\r
+\r
+ if( fSuccess != TRUE )\r
+ return ND_UNSUCCESSFUL;\r
+\r
+ return S_OK;\r
+}\r
+\r
+} // namespace\r
--- /dev/null
+/*\r
+ * Copyright (c) 2008 Microsoft Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ * - Redistributions of source code must retain the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer.\r
+ *\r
+ * - Redistributions in binary form must reproduce the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer in the documentation and/or other materials\r
+ * provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id:$\r
+ */\r
+\r
+#pragma once\r
+#include "ndspi.h"\r
+#include <iba/ib_al.h>\r
+#include <ws2tcpip.h>\r
+\r
+\r
+namespace NetworkDirect\r
+{\r
+\r
+\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// HPC Pack 2008 Beta 2 SPI\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+class CAdapter;\r
+class CCq;\r
+\r
+class CEndpoint :\r
+ public INDEndpoint\r
+{\r
+ friend class CConnector;\r
+\r
+private:\r
+ CEndpoint(void);\r
+ ~CEndpoint(void);\r
+\r
+ HRESULT Initialize(\r
+ __in CAdapter* pParent,\r
+ __in CCq* pInboundCq,\r
+ __in CCq* pOutboundCq,\r
+ __in SIZE_T nInboundEntries,\r
+ __in SIZE_T nOutboundEntries,\r
+ __in SIZE_T nInboundSge,\r
+ __in SIZE_T nOutboundSge,\r
+ __in SIZE_T InboundReadLimit,\r
+ __in SIZE_T OutboundReadLimit,\r
+ __out_opt SIZE_T* pMaxInlineData\r
+ );\r
+\r
+public:\r
+ static HRESULT Create(\r
+ __in CAdapter* pParent,\r
+ __in CCq* pInboundCq,\r
+ __in CCq* pOutboundCq,\r
+ __in SIZE_T nInboundEntries,\r
+ __in SIZE_T nOutboundEntries,\r
+ __in SIZE_T nInboundSge,\r
+ __in SIZE_T nOutboundSge,\r
+ __in SIZE_T InboundReadLimit,\r
+ __in SIZE_T OutboundReadLimit,\r
+ __out_opt SIZE_T* pMaxInlineData,\r
+ __out INDEndpoint** ppEndpoint\r
+ );\r
+\r
+ // *** IUnknown methods ***\r
+ HRESULT STDMETHODCALLTYPE QueryInterface(\r
+ REFIID riid,\r
+ LPVOID FAR* ppvObj\r
+ );\r
+\r
+ ULONG STDMETHODCALLTYPE AddRef(void);\r
+\r
+ ULONG STDMETHODCALLTYPE Release(void);\r
+\r
+ // *** INDEndpoint methods ***\r
+ HRESULT STDMETHODCALLTYPE Flush(void);\r
+\r
+ void STDMETHODCALLTYPE StartRequestBatch(void);\r
+\r
+ void STDMETHODCALLTYPE SubmitRequestBatch(void);\r
+\r
+ HRESULT STDMETHODCALLTYPE Send(\r
+ __out ND_RESULT* pResult,\r
+ __in_ecount(nSge) const ND_SGE* pSgl,\r
+ __in SIZE_T nSge,\r
+ __in DWORD Flags\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE SendAndInvalidate(\r
+ __out ND_RESULT* pResult,\r
+ __in_ecount(nSge) const ND_SGE* pSgl,\r
+ __in SIZE_T nSge,\r
+ __in const ND_MW_DESCRIPTOR* pRemoteMwDescriptor,\r
+ __in DWORD Flags\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE Receive(\r
+ __out ND_RESULT* pResult,\r
+ __in_ecount(nSge) const ND_SGE* pSgl,\r
+ __in SIZE_T nSge\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE Bind(\r
+ __out ND_RESULT* pResult,\r
+ __in ND_MR_HANDLE hMr,\r
+ __in INDMemoryWindow* pMw,\r
+ __in_bcount(BufferSize) const void* pBuffer,\r
+ __in SIZE_T BufferSize,\r
+ __in DWORD Flags,\r
+ __out ND_MW_DESCRIPTOR* pMwDescriptor\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE Invalidate(\r
+ __out ND_RESULT* pResult,\r
+ __in INDMemoryWindow* pMw,\r
+ __in DWORD Flags\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE Read(\r
+ __out ND_RESULT* pResult,\r
+ __in_ecount(nSge) const ND_SGE* pSgl,\r
+ __in SIZE_T nSge,\r
+ __in const ND_MW_DESCRIPTOR* pRemoteMwDescriptor,\r
+ __in ULONGLONG Offset,\r
+ __in DWORD Flags\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE Write(\r
+ __out ND_RESULT* pResult,\r
+ __in_ecount(nSge) const ND_SGE* pSgl,\r
+ __in SIZE_T nSge,\r
+ __in const ND_MW_DESCRIPTOR* pRemoteMwDescriptor,\r
+ __in ULONGLONG Offset,\r
+ __in DWORD Flags\r
+ );\r
+\r
+private:\r
+ HRESULT Rdma(\r
+ __out ND_RESULT* pResult,\r
+ __in ib_wr_type_t Type,\r
+ __in_ecount(nSge) const ND_SGE* pSgl,\r
+ __in SIZE_T nSge,\r
+ __in const ND_MW_DESCRIPTOR* pRemoteMwDescriptor,\r
+ __in ULONGLONG Offset,\r
+ __in DWORD Flags\r
+ );\r
+\r
+ HRESULT CreateQp(\r
+ __in CCq* pInboundCq,\r
+ __in CCq* pOutboundCq,\r
+ __in SIZE_T nInboundEntries,\r
+ __in SIZE_T nOutboundEntries,\r
+ __in SIZE_T nInboundSge,\r
+ __in SIZE_T nOutboundSge,\r
+ __in SIZE_T InboundReadLimit,\r
+ __in SIZE_T OutboundReadLimit\r
+ );\r
+\r
+ void DestroyQp();\r
+\r
+ HRESULT ModifyQp(\r
+ __in ib_qp_state_t NewState\r
+ );\r
+\r
+protected:\r
+ volatile LONG m_nRef;\r
+\r
+ CAdapter* m_pParent;\r
+\r
+ uint64_t m_hQp;\r
+ ib_qp_handle_t m_uQp;\r
+\r
+ net32_t m_Qpn;\r
+\r
+ UINT8 m_Ird;\r
+ UINT8 m_Ord;\r
+};\r
+\r
+} // namespace\r
--- /dev/null
+/*\r
+ * Copyright (c) 2008 Microsoft Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ * - Redistributions of source code must retain the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer.\r
+ *\r
+ * - Redistributions in binary form must reproduce the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer in the documentation and/or other materials\r
+ * provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id:$\r
+ */\r
+\r
+#include "NdListen.h"\r
+#include "NdAdapter.h"\r
+#include "NdEndpoint.h"\r
+#include "NdConnector.h"\r
+#include "al_dev.h"\r
+#pragma warning( push, 3 )\r
+#include "winternl.h"\r
+#pragma warning( pop )\r
+#include <complib/cl_byteswap.h>\r
+#include <limits.h>\r
+#include "nddebug.h"\r
+\r
+#if defined(EVENT_TRACING)\r
+#ifdef offsetof\r
+#undef offsetof\r
+#endif\r
+#include "NdListen.tmh"\r
+#endif\r
+\r
+namespace NetworkDirect\r
+{\r
+\r
+HRESULT GetPdataForPassive(\r
+ __in UINT8* pSrc,\r
+ __in SIZE_T SrcLength,\r
+ __out_bcount_part_opt(*pPrivateDataLength, *pPrivateDataLength) void* pPrivateData,\r
+ __inout SIZE_T* pPrivateDataLength\r
+ )\r
+{\r
+ if( SrcLength != IB_REQ_PDATA_SIZE )\r
+ {\r
+ ND_PRINT( TRACE_LEVEL_ERROR, ND_DBG_NDI, \r
+ ("Connection aborted: incorrect pdata_len %d \n", (int)SrcLength ));\r
+ return ND_CONNECTION_ABORTED;\r
+ }\r
+\r
+ if( pPrivateDataLength == NULL )\r
+ return S_OK;\r
+\r
+ ib_cm_rdma_req_t* pIpData = (ib_cm_rdma_req_t*)pSrc;\r
+ CL_ASSERT( pIpData->maj_min_ver == 0 );\r
+ CL_ASSERT( pIpData->ipv == 0x40 || pIpData->ipv == 0x60 );\r
+\r
+ if( *pPrivateDataLength == 0 )\r
+ {\r
+ *pPrivateDataLength = sizeof(pIpData->pdata);\r
+ return ND_BUFFER_OVERFLOW;\r
+ }\r
+\r
+ CopyMemory(\r
+ pPrivateData,\r
+ pIpData->pdata,\r
+ min( *pPrivateDataLength, sizeof(pIpData->pdata) )\r
+ );\r
+\r
+ HRESULT hr;\r
+ if( *pPrivateDataLength < sizeof(pIpData->pdata) )\r
+ {\r
+ hr = ND_BUFFER_OVERFLOW;\r
+ }\r
+ else\r
+ {\r
+ hr = S_OK;\r
+ }\r
+\r
+ *pPrivateDataLength = sizeof(pIpData->pdata);\r
+ return hr;\r
+}\r
+\r
+HRESULT GetPdataForActive(\r
+ __in UINT8* pSrc,\r
+ __in SIZE_T SrcLength,\r
+ __out_bcount_part_opt(*pPrivateDataLength, *pPrivateDataLength) void* pPrivateData,\r
+ __inout SIZE_T* pPrivateDataLength\r
+ )\r
+{\r
+ if( pPrivateDataLength == NULL )\r
+ return S_OK;\r
+\r
+ if( *pPrivateDataLength == 0 )\r
+ {\r
+ *pPrivateDataLength = SrcLength;\r
+ return ND_BUFFER_OVERFLOW;\r
+ }\r
+\r
+ CopyMemory(\r
+ pPrivateData,\r
+ pSrc,\r
+ min( *pPrivateDataLength, SrcLength ) );\r
+\r
+ HRESULT hr;\r
+ if( *pPrivateDataLength < IB_REJ_PDATA_SIZE )\r
+ {\r
+ hr = ND_BUFFER_OVERFLOW;\r
+ }\r
+ else\r
+ {\r
+ hr = S_OK;\r
+ }\r
+\r
+ *pPrivateDataLength = SrcLength;\r
+ return hr;\r
+}\r
+\r
+ CListen::CListen(void) :\r
+ m_nRef( 1 ),\r
+ m_pParent( NULL ),\r
+ m_cid( 0 )\r
+ {\r
+ }\r
+\r
+ CListen::~CListen(void)\r
+ {\r
+ if( m_cid != 0 )\r
+ {\r
+ DWORD bytes_ret;\r
+ DeviceIoControl(\r
+ m_pParent->m_hSync,\r
+ UAL_DESTROY_CEP,\r
+ &m_cid,\r
+ sizeof(m_cid),\r
+ NULL,\r
+ 0,\r
+ &bytes_ret,\r
+ NULL );\r
+ }\r
+\r
+ if( m_pParent )\r
+ m_pParent->Release();\r
+ }\r
+\r
+ HRESULT CListen::Initialize(\r
+ __in CAdapter* pParent,\r
+ __in SIZE_T Backlog,\r
+ __in INT Protocol,\r
+ __in USHORT Port,\r
+ __out_opt USHORT* pAssignedPort\r
+ )\r
+ {\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ m_pParent = pParent;\r
+ m_pParent->AddRef();\r
+\r
+ UNREFERENCED_PARAMETER( Backlog );\r
+\r
+ if( Port == 0 && pAssignedPort == NULL )\r
+ return ND_INVALID_PARAMETER_MIX;\r
+\r
+ //\r
+ // IP Addressing Annex only supports a single byte for protocol.\r
+ //\r
+ if( Protocol > UCHAR_MAX || Protocol < 0 )\r
+ return ND_INVALID_PARAMETER_3;\r
+\r
+ ual_cep_listen_ioctl_t listen;\r
+ listen.cid = 0;\r
+\r
+ listen.cep_listen.svc_id = \r
+ 0x0000000001000000 | Protocol << 16 | Port;\r
+\r
+ listen.cep_listen.port_guid = m_pParent->m_PortGuid;\r
+\r
+ switch( m_pParent->m_Addr.v4.sin_family )\r
+ {\r
+ case AF_INET:\r
+ ZeroMemory( listen.compare, ATS_IPV4_OFFSET );\r
+ CopyMemory( &listen.compare[ATS_IPV4_OFFSET],\r
+ (uint8_t*)&m_pParent->m_Addr.v4.sin_addr,\r
+ sizeof(m_pParent->m_Addr.v4.sin_addr) );\r
+ ND_PRINT( TRACE_LEVEL_INFORMATION, ND_DBG_NDI,\r
+ ("Listen for: IP %#x, port %#hx\n", \r
+ cl_hton32(m_pParent->m_Addr.v4.sin_addr.S_un.S_addr), cl_hton16(m_pParent->m_Addr.v4.sin_port) ) );\r
+ break;\r
+ case AF_INET6:\r
+ CopyMemory( listen.compare,\r
+ (uint8_t*)&m_pParent->m_Addr.v6.sin6_addr,\r
+ sizeof(m_pParent->m_Addr.v6.sin6_addr) );\r
+ break;\r
+ }\r
+ listen.cep_listen.p_cmp_buf = listen.compare;\r
+ listen.cep_listen.cmp_len = 16;\r
+ listen.cep_listen.cmp_offset = FIELD_OFFSET( ib_cm_rdma_req_t, dst_ip_addr );\r
+\r
+ IO_STATUS_BLOCK IoStatus;\r
+ IoStatus.Status = NtDeviceIoControlFile(\r
+ m_pParent->m_hSync,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ &IoStatus,\r
+ UAL_NDI_LISTEN_CM,\r
+ &listen,\r
+ sizeof(listen),\r
+ &m_cid,\r
+ sizeof(m_cid) );\r
+\r
+ switch( IoStatus.Status )\r
+ {\r
+ case ND_SUCCESS:\r
+ ND_PRINT( TRACE_LEVEL_INFORMATION, ND_DBG_NDI,\r
+ ("Listen for: Guid %#I64x, sid %#I64x\n", \r
+ m_pParent->m_PortGuid, listen.cep_listen.svc_id ) );\r
+ break;\r
+\r
+ case IB_INVALID_SETTING:\r
+ return ND_ADDRESS_ALREADY_EXISTS;\r
+\r
+ default:\r
+ return IoStatus.Status;\r
+ }\r
+\r
+ ND_PRINT( TRACE_LEVEL_INFORMATION, ND_DBG_NDI,\r
+ ("Created listen CEP with cid %d \n", m_cid ) );\r
+\r
+ // TODO: Come up with something better for port number.\r
+ if( Port == 0 )\r
+ Port = (USHORT)m_cid | (USHORT)(m_cid >> 16);\r
+\r
+ if( pAssignedPort )\r
+ *pAssignedPort = Port;\r
+\r
+ m_Protocol = (UINT8)Protocol;\r
+ return S_OK;\r
+ }\r
+\r
+ HRESULT CListen::Create(\r
+ __in CAdapter* pParent,\r
+ __in SIZE_T Backlog,\r
+ __in INT Protocol,\r
+ __in USHORT Port,\r
+ __out_opt USHORT* pAssignedPort,\r
+ __deref_out INDListen** ppListen\r
+ )\r
+ {\r
+ CListen* pListen = new CListen();\r
+ if( pListen == NULL )\r
+ return ND_NO_MEMORY;\r
+\r
+ HRESULT hr = pListen->Initialize(\r
+ pParent,\r
+ Backlog,\r
+ Protocol,\r
+ Port,\r
+ pAssignedPort );\r
+ if( FAILED( hr ) )\r
+ {\r
+ delete pListen;\r
+ return hr;\r
+ }\r
+\r
+ *ppListen = pListen;\r
+ return S_OK;\r
+ }\r
+\r
+ // *** IUnknown methods ***\r
+ HRESULT CListen::QueryInterface(\r
+ REFIID riid,\r
+ LPVOID FAR* ppvObj\r
+ )\r
+ {\r
+ if( IsEqualIID( riid, IID_IUnknown ) )\r
+ {\r
+ *ppvObj = this;\r
+ return S_OK;\r
+ }\r
+\r
+ if( IsEqualIID( riid, IID_INDListen ) )\r
+ {\r
+ *ppvObj = this;\r
+ return S_OK;\r
+ }\r
+\r
+ return E_NOINTERFACE;\r
+ }\r
+\r
+ ULONG CListen::AddRef(void)\r
+ {\r
+ return InterlockedIncrement( &m_nRef );\r
+ }\r
+\r
+ ULONG CListen::Release(void)\r
+ {\r
+ ULONG ref = InterlockedDecrement( &m_nRef );\r
+ if( ref == 0 )\r
+ delete this;\r
+\r
+ return ref;\r
+ }\r
+\r
+ // *** INDOverlapped methods ***\r
+ HRESULT CListen::CancelOverlappedRequests(void)\r
+ {\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ DWORD bytes_ret;\r
+ BOOL ret = DeviceIoControl(\r
+ m_pParent->m_hSync,\r
+ UAL_NDI_CANCEL_CM_IRPS,\r
+ &m_cid,\r
+ sizeof(m_cid),\r
+ NULL,\r
+ 0,\r
+ &bytes_ret,\r
+ NULL );\r
+\r
+ if( ret )\r
+ return S_OK;\r
+ else\r
+ return ND_UNSUCCESSFUL;\r
+ }\r
+\r
+ HRESULT CListen::GetOverlappedResult(\r
+ __inout OVERLAPPED *pOverlapped,\r
+ __out SIZE_T *pNumberOfBytesTransferred,\r
+ __in BOOL bWait\r
+ )\r
+ {\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ *pNumberOfBytesTransferred = 0;\r
+ ::GetOverlappedResult(\r
+ m_pParent->GetFileHandle(),\r
+ pOverlapped,\r
+ (DWORD*)pNumberOfBytesTransferred,\r
+ bWait );\r
+ return (HRESULT)pOverlapped->Internal;\r
+ }\r
+\r
+ // *** INDListen methods ***\r
+ HRESULT CListen::GetConnectionRequest(\r
+ __inout INDConnector* pConnector,\r
+ __inout OVERLAPPED* pOverlapped\r
+ )\r
+ {\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ static_cast<CConnector*>(pConnector)->m_Protocol = m_Protocol;\r
+\r
+ pOverlapped->Internal = ND_PENDING;\r
+ return NtDeviceIoControlFile(\r
+ m_pParent->GetFileHandle(),\r
+ pOverlapped->hEvent,\r
+ NULL,\r
+ (ULONG_PTR)pOverlapped->hEvent & 1 ? NULL : pOverlapped,\r
+ (IO_STATUS_BLOCK*)&pOverlapped->Internal,\r
+ UAL_NDI_GET_REQ_CM,\r
+ &m_cid,\r
+ sizeof(m_cid),\r
+ &static_cast<CConnector*>(pConnector)->m_cid,\r
+ sizeof(static_cast<CConnector*>(pConnector)->m_cid) );\r
+ }\r
+\r
+} // namespace\r
--- /dev/null
+/*\r
+ * Copyright (c) 2008 Microsoft Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ * - Redistributions of source code must retain the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer.\r
+ *\r
+ * - Redistributions in binary form must reproduce the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer in the documentation and/or other materials\r
+ * provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id:$\r
+ */\r
+\r
+#pragma once\r
+#include "ndspi.h"\r
+#include <iba/ib_al.h>\r
+\r
+\r
+namespace NetworkDirect\r
+{\r
+\r
+HRESULT GetPdataForPassive(\r
+ __in UINT8* pSrc,\r
+ __in SIZE_T SrcLength,\r
+ __out_bcount_part_opt(*pPrivateDataLength, *pPrivateDataLength) void* pPrivateData,\r
+ __inout SIZE_T* pPrivateDataLength\r
+ );\r
+\r
+HRESULT GetPdataForActive(\r
+ __in UINT8* pSrc,\r
+ __in SIZE_T SrcLength,\r
+ __out_bcount_part_opt(*pPrivateDataLength, *pPrivateDataLength) void* pPrivateData,\r
+ __inout SIZE_T* pPrivateDataLength\r
+ );\r
+\r
+class CAdapter;\r
+\r
+class CListen :\r
+ public INDListen\r
+{\r
+private:\r
+ CListen(void);\r
+ ~CListen(void);\r
+\r
+ HRESULT Initialize(\r
+ __in CAdapter* pParent,\r
+ __in SIZE_T Backlog,\r
+ __in INT Protocol,\r
+ __in USHORT Port,\r
+ __out_opt USHORT* pAssignedPort\r
+ );\r
+\r
+public:\r
+ static HRESULT Create(\r
+ __in CAdapter* pParent,\r
+ __in SIZE_T Backlog,\r
+ __in INT Protocol,\r
+ __in USHORT Port,\r
+ __out_opt USHORT* pAssignedPort,\r
+ __deref_out INDListen** ppListen\r
+ );\r
+\r
+ // *** IUnknown methods ***\r
+ HRESULT STDMETHODCALLTYPE QueryInterface(\r
+ REFIID riid,\r
+ LPVOID FAR* ppvObj\r
+ );\r
+\r
+ ULONG STDMETHODCALLTYPE AddRef(void);\r
+\r
+ ULONG STDMETHODCALLTYPE Release(void);\r
+\r
+ // *** INDOverlapped methods ***\r
+ HRESULT STDMETHODCALLTYPE CancelOverlappedRequests(void);\r
+\r
+ HRESULT STDMETHODCALLTYPE GetOverlappedResult(\r
+ __inout OVERLAPPED *pOverlapped,\r
+ __out SIZE_T *pNumberOfBytesTransferred,\r
+ __in BOOL bWait\r
+ );\r
+\r
+ // *** INDListen methods ***\r
+ HRESULT STDMETHODCALLTYPE GetConnectionRequest(\r
+ __inout INDConnector* pConnector,\r
+ __inout OVERLAPPED* pOverlapped\r
+ );\r
+\r
+private:\r
+ volatile LONG m_nRef;\r
+\r
+ CAdapter* m_pParent;\r
+\r
+ UINT8 m_Protocol;\r
+ net32_t m_cid;\r
+};\r
+\r
+} // namespace\r
--- /dev/null
+/*\r
+ * Copyright (c) 2008 Microsoft Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ * - Redistributions of source code must retain the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer.\r
+ *\r
+ * - Redistributions in binary form must reproduce the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer in the documentation and/or other materials\r
+ * provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id:$\r
+ */\r
+\r
+#include <initguid.h>\r
+#include "ndspi.h"\r
+#include "NdMr.h"\r
+\r
+\r
+namespace NetworkDirect\r
+{\r
+\r
+ CMr::CMr(void)\r
+ {\r
+ }\r
+\r
+ CMr::~CMr(void)\r
+ {\r
+ }\r
+\r
+} // namespace\r
--- /dev/null
+/*\r
+ * Copyright (c) 2008 Microsoft Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ * - Redistributions of source code must retain the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer.\r
+ *\r
+ * - Redistributions in binary form must reproduce the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer in the documentation and/or other materials\r
+ * provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id:$\r
+ */\r
+\r
+#pragma once\r
+\r
+#include "iba/ib_al_ioctl.h"\r
+\r
+\r
+namespace NetworkDirect\r
+{\r
+\r
+ class CMr\r
+ {\r
+ friend class CAdapter;\r
+ friend class CEndpoint;\r
+\r
+ friend class CAdapter_Beta1;\r
+ friend class CEndpoint_Beta1;\r
+ public:\r
+ CMr(void);\r
+ ~CMr(void);\r
+\r
+ protected:\r
+ const char* pBase;\r
+ uint32_t Length;\r
+ ual_reg_mem_ioctl_t mr_ioctl;\r
+ };\r
+\r
+} // namespace\r
--- /dev/null
+/*\r
+ * Copyright (c) 2008 Microsoft Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ * - Redistributions of source code must retain the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer.\r
+ *\r
+ * - Redistributions in binary form must reproduce the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer in the documentation and/or other materials\r
+ * provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id:$\r
+ */\r
+\r
+#include "NdMw.h"\r
+#include "NdAdapter.h"\r
+\r
+#if defined(EVENT_TRACING)\r
+#ifdef offsetof\r
+#undef offsetof\r
+#endif\r
+#include "NdMw.tmh"\r
+#endif\r
+\r
+\r
+namespace NetworkDirect\r
+{\r
+\r
+ CMw::CMw(void) :\r
+ m_nRef( 1 ),\r
+ m_pParent( NULL )\r
+ {\r
+ }\r
+\r
+ CMw::~CMw(void)\r
+ {\r
+ if( m_pParent )\r
+ m_pParent->Release();\r
+ }\r
+\r
+ HRESULT CMw::Initialize(\r
+ CAdapter* pParent,\r
+ ND_RESULT* pInvalidateResult\r
+ )\r
+ {\r
+ m_pParent = pParent;\r
+ m_pParent->AddRef();\r
+\r
+ m_pInvalidateResult = pInvalidateResult;\r
+ return S_OK;\r
+ }\r
+\r
+ HRESULT CMw::QueryInterface(\r
+ REFIID riid,\r
+ LPVOID FAR* ppvObj\r
+ )\r
+ {\r
+ if( IsEqualIID( riid, IID_IUnknown ) )\r
+ {\r
+ *ppvObj = this;\r
+ return S_OK;\r
+ }\r
+\r
+ if( IsEqualIID( riid, IID_INDMemoryWindow ) )\r
+ {\r
+ *ppvObj = this;\r
+ return S_OK;\r
+ }\r
+\r
+ return E_NOINTERFACE;\r
+ }\r
+\r
+ ULONG CMw::AddRef(void)\r
+ {\r
+ return InterlockedIncrement( &m_nRef );\r
+ }\r
+\r
+ ULONG CMw::Release(void)\r
+ {\r
+ ULONG ref = InterlockedDecrement( &m_nRef );\r
+ if( ref == 0 )\r
+ delete this;\r
+\r
+ return ref;\r
+ }\r
+\r
+ HRESULT CMw::Close(void)\r
+ {\r
+ Release();\r
+ return S_OK;\r
+ }\r
+\r
+} // namespace\r
--- /dev/null
+/*\r
+ * Copyright (c) 2008 Microsoft Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ * - Redistributions of source code must retain the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer.\r
+ *\r
+ * - Redistributions in binary form must reproduce the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer in the documentation and/or other materials\r
+ * provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id:$\r
+ */\r
+\r
+#pragma once\r
+#include "ndspi.h"\r
+\r
+\r
+namespace NetworkDirect\r
+{\r
+\r
+ class CAdapter;\r
+\r
+ class CMw :\r
+ public INDMemoryWindow\r
+ {\r
+ public:\r
+ CMw(void);\r
+ ~CMw(void);\r
+\r
+ HRESULT Initialize(\r
+ CAdapter* pParent,\r
+ ND_RESULT* pInvalidateResult );\r
+\r
+ // *** IUnknown methods ***\r
+ HRESULT STDMETHODCALLTYPE QueryInterface(\r
+ REFIID riid,\r
+ LPVOID FAR* ppvObj\r
+ );\r
+\r
+ ULONG STDMETHODCALLTYPE AddRef(void);\r
+\r
+ ULONG STDMETHODCALLTYPE Release(void);\r
+\r
+ // *** INDMemoryWindow methods ***\r
+ HRESULT STDMETHODCALLTYPE Close(void);\r
+\r
+ //operator ND_RESULT*(){ return m_pInvalidateResult; };\r
+\r
+ private:\r
+ volatile LONG m_nRef;\r
+\r
+ CAdapter* m_pParent;\r
+\r
+ ND_RESULT* m_pInvalidateResult;\r
+ };\r
+\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// HPC Pack 2008 Beta 1 SPI\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+ class CAdapter_Beta1;\r
+\r
+ class CMw_Beta1 :\r
+ public INDMemoryWindow\r
+ {\r
+ public:\r
+ CMw_Beta1(void);\r
+ ~CMw_Beta1(void);\r
+\r
+ HRESULT Initialize(\r
+ CAdapter_Beta1* pParent,\r
+ ND_RESULT* pInvalidateResult );\r
+\r
+ // *** IUnknown methods ***\r
+ HRESULT STDMETHODCALLTYPE QueryInterface(\r
+ REFIID riid,\r
+ LPVOID FAR* ppvObj\r
+ );\r
+\r
+ ULONG STDMETHODCALLTYPE AddRef(void);\r
+\r
+ ULONG STDMETHODCALLTYPE Release(void);\r
+\r
+ // *** INDMemoryWindow methods ***\r
+ HRESULT STDMETHODCALLTYPE Close(void);\r
+\r
+ //operator ND_RESULT*(){ return m_pInvalidateResult; };\r
+\r
+ private:\r
+ volatile LONG m_nRef;\r
+\r
+ CAdapter_Beta1* m_pParent;\r
+\r
+ ND_RESULT* m_pInvalidateResult;\r
+ };\r
+\r
+} // namespace
\ No newline at end of file
--- /dev/null
+/*\r
+ * Copyright (c) 2008 Microsoft Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ * - Redistributions of source code must retain the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer.\r
+ *\r
+ * - Redistributions in binary form must reproduce the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer in the documentation and/or other materials\r
+ * provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id:$\r
+ */\r
+\r
+#include <tchar.h>\r
+#include <ndspi.h>\r
+#include <iba/ib_at_ioctl.h>\r
+#include <complib/cl_types.h>\r
+#include <complib/cl_ioctl.h>\r
+#pragma warning( push, 3 )\r
+#include <unknwn.h>\r
+#include <assert.h>\r
+#include <ws2tcpip.h>\r
+#include <winioctl.h>\r
+#include <limits.h>\r
+#include <ws2spi.h>\r
+#pragma warning( pop )\r
+#include "ndprov.h"\r
+#include "ndadapter.h"\r
+\r
+#if defined(EVENT_TRACING)\r
+#ifdef offsetof\r
+#undef offsetof\r
+#endif\r
+#include "NdProv.tmh"\r
+#endif\r
+\r
+#include "nddebug.h"\r
+\r
+uint32_t g_nd_dbg_level = TRACE_LEVEL_ERROR;\r
+/* WPP doesn't want here literals! */\r
+uint32_t g_nd_dbg_flags = 0x80000001; /* ND_DBG_ERROR | ND_DBG_NDI; */\r
+\r
+namespace NetworkDirect\r
+{\r
+\r
+ static LONG gnRef = 0;\r
+\r
+ CProvider::CProvider() :\r
+ m_nRef( 1 )\r
+ {\r
+ InterlockedIncrement( &gnRef );\r
+ }\r
+\r
+ CProvider::~CProvider()\r
+ {\r
+ InterlockedDecrement( &gnRef );\r
+ }\r
+\r
+ HRESULT CProvider::QueryInterface(\r
+ const IID &riid,\r
+ void **ppObject )\r
+ {\r
+ if( IsEqualIID( riid, IID_IUnknown ) )\r
+ {\r
+ *ppObject = this;\r
+ return S_OK;\r
+ }\r
+\r
+ if( IsEqualIID( riid, IID_INDProvider ) )\r
+ {\r
+ *ppObject = this;\r
+ return S_OK;\r
+ }\r
+\r
+ return E_NOINTERFACE;\r
+ }\r
+\r
+ ULONG CProvider::AddRef()\r
+ {\r
+ return InterlockedIncrement( &m_nRef );\r
+ }\r
+\r
+ ULONG CProvider::Release()\r
+ {\r
+ ULONG ref = InterlockedDecrement( &m_nRef );\r
+ if( ref == 0 )\r
+ delete this;\r
+\r
+ return ref;\r
+ }\r
+\r
+ HRESULT CProvider::QueryAddressList(\r
+ __out_bcount_part_opt(*pBufferSize, *pBufferSize) SOCKET_ADDRESS_LIST* pAddressList,\r
+ __inout SIZE_T* pBufferSize )\r
+ {\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ HANDLE hIbatDev = CreateFileW( IBAT_WIN32_NAME,\r
+ MAXIMUM_ALLOWED, 0, NULL,\r
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );\r
+ if( hIbatDev == INVALID_HANDLE_VALUE )\r
+ return ND_NO_MEMORY;\r
+\r
+ IOCTL_IBAT_IP_ADDRESSES_IN addrIn;\r
+\r
+ addrIn.Version = IBAT_IOCTL_VERSION;\r
+ addrIn.PortGuid = 0;\r
+\r
+ DWORD size = sizeof(IOCTL_IBAT_IP_ADDRESSES_OUT);\r
+ IOCTL_IBAT_IP_ADDRESSES_OUT *pAddrOut;\r
+ do\r
+ {\r
+ pAddrOut = (IOCTL_IBAT_IP_ADDRESSES_OUT*)HeapAlloc(\r
+ GetProcessHeap(),\r
+ 0,\r
+ size );\r
+ if( !pAddrOut )\r
+ {\r
+ //AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
+ // ("Failed to allocate output buffer.\n") );\r
+ return ND_NO_MEMORY;\r
+ }\r
+\r
+ if( !DeviceIoControl( hIbatDev, IOCTL_IBAT_IP_ADDRESSES,\r
+ &addrIn, sizeof(addrIn), pAddrOut, size, &size, NULL ) )\r
+ {\r
+ HeapFree( GetProcessHeap(), 0, pAddrOut );\r
+ //AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
+ // ("IOCTL_IBAT_IP_ADDRESSES failed (%x).\n", GetLastError()) );\r
+ return ND_UNSUCCESSFUL;\r
+ }\r
+\r
+ if( pAddrOut->Size > size )\r
+ {\r
+ size = pAddrOut->Size;\r
+ HeapFree( GetProcessHeap(), 0, pAddrOut );\r
+ pAddrOut = NULL;\r
+ }\r
+\r
+ } while( !pAddrOut );\r
+\r
+ CloseHandle( hIbatDev );\r
+\r
+ //\r
+ // Note: the required size computed is a few bytes larger than necessary, \r
+ // but that keeps the code clean.\r
+ //\r
+ SIZE_T size_req = sizeof(SOCKET_ADDRESS_LIST);\r
+\r
+ switch( pAddrOut->AddressCount )\r
+ {\r
+ case 0:\r
+ break;\r
+\r
+ default:\r
+ size_req += (pAddrOut->AddressCount - 1) *\r
+ (sizeof(SOCKET_ADDRESS) + sizeof(SOCKADDR));\r
+ /* Fall through. */\r
+ __fallthrough;\r
+\r
+ case 1:\r
+ /* Add the space for the first address. */\r
+ size_req += sizeof(SOCKADDR);\r
+ break;\r
+ }\r
+\r
+ if( size_req > *pBufferSize )\r
+ {\r
+ HeapFree( GetProcessHeap(), 0, pAddrOut );\r
+ *pBufferSize = size_req;\r
+ return ND_BUFFER_OVERFLOW;\r
+ }\r
+\r
+ ZeroMemory( pAddressList, *pBufferSize );\r
+\r
+ /* We store the array of addresses after the last address pointer:\r
+ * iAddressCount\r
+ * Address[0]; <-- points to sockaddr[0]\r
+ * Address[1]; <-- points to sockaddr[1]\r
+ * ...\r
+ * Address[n-1]; <-- points to sockaddr[n-1]\r
+ * sockaddr[0];\r
+ * sockaddr[1];\r
+ * ...\r
+ * sockaddr[n-1]\r
+ */\r
+ BYTE* pBuf = (BYTE*)(&(pAddressList->Address[pAddrOut->AddressCount]));\r
+ *pBufferSize = size_req;\r
+\r
+ pAddressList->iAddressCount = 0;\r
+ for( LONG i = 0; i < pAddrOut->AddressCount; i++ )\r
+ {\r
+ pAddressList->Address[pAddressList->iAddressCount].lpSockaddr =\r
+ (LPSOCKADDR)pBuf;\r
+\r
+ switch( pAddrOut->Address[i].IpVersion )\r
+ {\r
+ case 4:\r
+ {\r
+ struct sockaddr_in* pAddr4 = ((struct sockaddr_in*)pBuf);\r
+ pAddr4->sin_family = AF_INET;\r
+ pAddr4->sin_addr.s_addr =\r
+ *((u_long*)&pAddrOut->Address[i].Address[12]);\r
+ pAddressList->Address[pAddressList->iAddressCount].iSockaddrLength =\r
+ sizeof(struct sockaddr_in);\r
+ }\r
+ break;\r
+\r
+ case 6:\r
+ {\r
+ struct sockaddr_in6* pAddr6 = ((struct sockaddr_in6*)pBuf);\r
+ pAddr6->sin6_family = AF_INET6;\r
+ CopyMemory(\r
+ &pAddr6->sin6_addr,\r
+ pAddrOut->Address[i].Address,\r
+ sizeof(pAddr6->sin6_addr) );\r
+ pAddressList->Address[pAddressList->iAddressCount].iSockaddrLength =\r
+ sizeof(struct sockaddr_in6);\r
+ }\r
+ break;\r
+\r
+ default:\r
+ continue;\r
+ }\r
+\r
+ pBuf += pAddressList->Address[pAddressList->iAddressCount++].iSockaddrLength;\r
+ }\r
+\r
+ HeapFree( GetProcessHeap(), 0, pAddrOut );\r
+\r
+ return S_OK;\r
+ }\r
+\r
+ HRESULT CProvider::OpenAdapter(\r
+ __in_bcount(AddressLength) const struct sockaddr* pAddress,\r
+ __in SIZE_T AddressLength,\r
+ __deref_out INDAdapter** ppAdapter )\r
+ {\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ if( AddressLength < sizeof(struct sockaddr) )\r
+ return ND_INVALID_ADDRESS;\r
+\r
+ IOCTL_IBAT_IP_TO_PORT_IN in;\r
+ in.Version = IBAT_IOCTL_VERSION;\r
+\r
+ switch( pAddress->sa_family )\r
+ {\r
+ case AF_INET:\r
+ if( AddressLength < sizeof(struct sockaddr_in) )\r
+ return ND_INVALID_ADDRESS;\r
+ in.Address.IpVersion = 4;\r
+ RtlCopyMemory(\r
+ &in.Address.Address[12],\r
+ &((struct sockaddr_in*)pAddress)->sin_addr,\r
+ sizeof( ((struct sockaddr_in*)pAddress)->sin_addr ) );\r
+ break;\r
+\r
+ case AF_INET6:\r
+ if( AddressLength < sizeof(struct sockaddr_in6) )\r
+ return ND_INVALID_ADDRESS;\r
+ in.Address.IpVersion = 6;\r
+ RtlCopyMemory(\r
+ in.Address.Address,\r
+ &((struct sockaddr_in6*)pAddress)->sin6_addr,\r
+ sizeof(in.Address.Address) );\r
+ break;\r
+\r
+ default:\r
+ return ND_INVALID_ADDRESS;\r
+ }\r
+\r
+ HANDLE hIbatDev = CreateFileW( IBAT_WIN32_NAME,\r
+ MAXIMUM_ALLOWED, 0, NULL,\r
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );\r
+ if( hIbatDev == INVALID_HANDLE_VALUE )\r
+ return ND_NO_MEMORY;\r
+\r
+ IBAT_PORT_RECORD out;\r
+ DWORD size;\r
+ BOOL fSuccess = DeviceIoControl( hIbatDev, IOCTL_IBAT_IP_TO_PORT,\r
+ &in, sizeof(in), &out, sizeof(out), &size, NULL );\r
+ \r
+ CloseHandle( hIbatDev );\r
+ if( !fSuccess || size == 0 )\r
+ return ND_INVALID_ADDRESS;\r
+\r
+ return CAdapter::Create( this, pAddress, &out, ppAdapter );\r
+ }\r
+\r
+ CClassFactory::CClassFactory(void) :\r
+ m_nRef( 1 )\r
+ {\r
+ InterlockedIncrement( &gnRef );\r
+ }\r
+\r
+ CClassFactory::~CClassFactory(void)\r
+ {\r
+ InterlockedDecrement( &gnRef );\r
+ }\r
+\r
+ HRESULT CClassFactory::QueryInterface(\r
+ REFIID riid,\r
+ void** ppObject )\r
+ {\r
+ if( IsEqualIID( riid, IID_IUnknown ) )\r
+ {\r
+ *ppObject = this;\r
+ return S_OK;\r
+ }\r
+ if( IsEqualIID( riid, IID_IClassFactory ) )\r
+ {\r
+ *ppObject = this;\r
+ return S_OK;\r
+ }\r
+\r
+ return E_NOINTERFACE;\r
+ }\r
+\r
+ ULONG CClassFactory::AddRef()\r
+ {\r
+ return InterlockedIncrement( &m_nRef );\r
+ }\r
+\r
+ ULONG CClassFactory::Release()\r
+ {\r
+ ULONG ref = InterlockedDecrement( &m_nRef );\r
+ if( ref == 0 )\r
+ delete this;\r
+\r
+ return ref;\r
+ }\r
+\r
+ HRESULT CClassFactory::CreateInstance(\r
+ IUnknown* pUnkOuter,\r
+ REFIID riid,\r
+ void** ppObject )\r
+ {\r
+ if( pUnkOuter != NULL )\r
+ return CLASS_E_NOAGGREGATION;\r
+\r
+ if( IsEqualIID( riid, IID_INDProvider ) )\r
+ {\r
+ *ppObject = new CProvider();\r
+ if( !*ppObject )\r
+ return E_OUTOFMEMORY;\r
+\r
+ return S_OK;\r
+ }\r
+\r
+ return E_NOINTERFACE;\r
+ }\r
+\r
+ HRESULT CClassFactory::LockServer( BOOL fLock )\r
+ { \r
+ UNREFERENCED_PARAMETER( fLock );\r
+ return S_OK;\r
+ }\r
+\r
+} // namespace\r
+\r
+void* __cdecl operator new(\r
+ size_t count\r
+ )\r
+{\r
+ return HeapAlloc( GetProcessHeap(), 0, count );\r
+}\r
+\r
+\r
+void __cdecl operator delete(\r
+ void* object\r
+ )\r
+{\r
+ HeapFree( GetProcessHeap(), 0, object );\r
+}\r
+\r
+extern "C" {\r
+STDAPI DllGetClassObject(\r
+ REFCLSID rclsid,\r
+ REFIID riid,\r
+ LPVOID * ppv\r
+ )\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ UNREFERENCED_PARAMETER( rclsid );\r
+\r
+ if( IsEqualIID( riid, IID_IClassFactory ) )\r
+ {\r
+ NetworkDirect::CClassFactory* pFactory = new NetworkDirect::CClassFactory();\r
+ if( pFactory == NULL )\r
+ return E_OUTOFMEMORY;\r
+\r
+ *ppv = pFactory;\r
+ return S_OK;\r
+ }\r
+\r
+ return E_NOINTERFACE;\r
+}\r
+\r
+STDAPI DllCanUnloadNow(void)\r
+{\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ if( InterlockedCompareExchange( &NetworkDirect::gnRef, 0, 0 ) != 0 )\r
+ return S_FALSE;\r
+\r
+ return S_OK;\r
+}\r
+\r
+int\r
+WSPAPI\r
+WSPStartup(\r
+ IN WORD wVersionRequested,\r
+ OUT LPWSPDATA lpWSPData,\r
+ IN LPWSAPROTOCOL_INFOW lpProtocolInfo,\r
+ IN WSPUPCALLTABLE UpcallTable,\r
+ OUT LPWSPPROC_TABLE lpProcTable\r
+ )\r
+{\r
+ UNREFERENCED_PARAMETER( wVersionRequested );\r
+ UNREFERENCED_PARAMETER( lpWSPData );\r
+ UNREFERENCED_PARAMETER( lpProtocolInfo );\r
+ UNREFERENCED_PARAMETER( UpcallTable );\r
+ UNREFERENCED_PARAMETER( lpProcTable );\r
+ return WSASYSNOTREADY;\r
+}\r
+\r
+static BOOL\r
+_DllMain(\r
+ IN HINSTANCE hinstDll,\r
+ IN DWORD dwReason,\r
+ IN LPVOID lpvReserved )\r
+{\r
+\r
+ ND_ENTER( ND_DBG_NDI );\r
+\r
+ UNUSED_PARAM( hinstDll );\r
+ UNUSED_PARAM( lpvReserved );\r
+\r
+ switch( dwReason )\r
+ {\r
+ case DLL_PROCESS_ATTACH:\r
+\r
+\r
+#if defined(EVENT_TRACING)\r
+#if DBG\r
+ WPP_INIT_TRACING(L"ibndprov.dll");\r
+#else\r
+ WPP_INIT_TRACING(L"ibndprov.dll");\r
+#endif\r
+#endif\r
+\r
+\r
+#if !defined(EVENT_TRACING)\r
+#if DBG \r
+ TCHAR env_var[16];\r
+ DWORD i;\r
+\r
+ i = GetEnvironmentVariable( "IBNDPROV_DBG_LEVEL", env_var, sizeof(env_var) );\r
+ if( i && i <= 16 )\r
+ {\r
+ g_nd_dbg_level = _tcstoul( env_var, NULL, 16 );\r
+ }\r
+\r
+ i = GetEnvironmentVariable( "IBNDPROV_DBG_FLAGS", env_var, sizeof(env_var) );\r
+ if( i && i <= 16 )\r
+ {\r
+ g_nd_dbg_flags = _tcstoul( env_var, NULL, 16 );\r
+ }\r
+\r
+ if( g_nd_dbg_flags & ND_DBG_ERR )\r
+ g_nd_dbg_flags |= CL_DBG_ERROR;\r
+\r
+ ND_PRINT( TRACE_LEVEL_ERROR, ND_DBG_ERR ,\r
+ ("(pcs %#x) IbNdProv: Debug print: level:%d, flags 0x%x\n",\r
+ GetCurrentProcessId(), g_nd_dbg_level ,g_nd_dbg_flags) );\r
+\r
+#endif\r
+#endif\r
+\r
+ ND_PRINT(TRACE_LEVEL_INFORMATION, ND_DBG_NDI, ("DllMain: DLL_PROCESS_ATTACH\n") );\r
+ break;\r
+\r
+ case DLL_PROCESS_DETACH:\r
+ ND_PRINT(TRACE_LEVEL_INFORMATION, ND_DBG_NDI,\r
+ ("DllMain: DLL_PROCESS_DETACH, ref count %d\n", NetworkDirect::gnRef) );\r
+\r
+#if defined(EVENT_TRACING)\r
+ WPP_CLEANUP();\r
+#endif\r
+ break;\r
+ }\r
+\r
+ ND_EXIT( ND_DBG_NDI );\r
+\r
+ return TRUE;\r
+}\r
+\r
+\r
+extern BOOL APIENTRY\r
+_DllMainCRTStartupForGS(\r
+ IN HINSTANCE h_module,\r
+ IN DWORD ul_reason_for_call, \r
+ IN LPVOID lp_reserved );\r
+\r
+\r
+BOOL APIENTRY\r
+DllMain(\r
+ IN HINSTANCE h_module,\r
+ IN DWORD ul_reason_for_call, \r
+ IN LPVOID lp_reserved )\r
+{\r
+ switch( ul_reason_for_call )\r
+ {\r
+ case DLL_PROCESS_ATTACH:\r
+ if( !_DllMainCRTStartupForGS(\r
+ h_module, ul_reason_for_call, lp_reserved ) )\r
+ {\r
+ return FALSE;\r
+ }\r
+\r
+ return _DllMain( h_module, ul_reason_for_call, lp_reserved );\r
+\r
+ case DLL_THREAD_ATTACH:\r
+ ND_PRINT(TRACE_LEVEL_INFORMATION, ND_DBG_NDI, ("DllMain: DLL_THREAD_ATTACH\n") );\r
+ break;\r
+\r
+ case DLL_THREAD_DETACH:\r
+ ND_PRINT(TRACE_LEVEL_INFORMATION, ND_DBG_NDI, ("DllMain: DLL_THREAD_DETACH\n") );\r
+ break;\r
+\r
+ case DLL_PROCESS_DETACH:\r
+ _DllMain( h_module, ul_reason_for_call, lp_reserved );\r
+\r
+ return _DllMainCRTStartupForGS(\r
+ h_module, ul_reason_for_call, lp_reserved );\r
+ }\r
+ return TRUE;\r
+}\r
+\r
+} // extern "C"\r
+\r
--- /dev/null
+LIBRARY IbNdProv.dll\r
+\r
+EXPORTS\r
+ DllGetClassObject private\r
+ WSPStartup \r
+ DllCanUnloadNow private
\ No newline at end of file
--- /dev/null
+/*\r
+ * Copyright (c) 2008 Microsoft Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ * - Redistributions of source code must retain the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer.\r
+ *\r
+ * - Redistributions in binary form must reproduce the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer in the documentation and/or other materials\r
+ * provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id:$\r
+ */\r
+\r
+#pragma once\r
+#include <iba/ib_at_ioctl.h>\r
+\r
+#ifdef __cplusplus\r
+namespace NetworkDirect\r
+{\r
+\r
+\r
+///////////////////////////////////////////////////////////////////////////////\r
+//\r
+// HPC Pack 2008 Beta 2 SPI\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+class CProvider :\r
+ public INDProvider\r
+{\r
+ friend class CClassFactory;\r
+\r
+public:\r
+ CProvider(void);\r
+ ~CProvider(void);\r
+\r
+ // IUnknown Methods\r
+ HRESULT STDMETHODCALLTYPE QueryInterface(\r
+ REFIID riid,\r
+ void** ppObject\r
+ );\r
+\r
+ ULONG STDMETHODCALLTYPE AddRef(void);\r
+ ULONG STDMETHODCALLTYPE Release(void);\r
+\r
+ // INDProvider Methods\r
+ HRESULT STDMETHODCALLTYPE QueryAddressList(\r
+ __out_bcount_part_opt(*pBufferSize, *pBufferSize) SOCKET_ADDRESS_LIST* pAddressList,\r
+ __inout SIZE_T* pBufferSize\r
+ );\r
+\r
+ HRESULT STDMETHODCALLTYPE OpenAdapter(\r
+ __in_bcount(AddressLength) const struct sockaddr* pAddress,\r
+ __in SIZE_T AddressLength,\r
+ __deref_out INDAdapter** ppAdapter\r
+ );\r
+\r
+private:\r
+ volatile LONG m_nRef;\r
+};\r
+\r
+\r
+class CClassFactory : public IClassFactory\r
+{\r
+public:\r
+ CClassFactory(void);\r
+ ~CClassFactory(void);\r
+\r
+ // IUnknown Methods.\r
+ HRESULT STDMETHODCALLTYPE QueryInterface( REFIID riid, void** ppObject );\r
+ ULONG STDMETHODCALLTYPE AddRef(void);\r
+ ULONG STDMETHODCALLTYPE Release(void);\r
+\r
+ // IClassFactory Methods.\r
+ HRESULT STDMETHODCALLTYPE CreateInstance( IUnknown* pUnkOuter, REFIID riid, void** ppObject );\r
+ HRESULT STDMETHODCALLTYPE LockServer( BOOL fLock );\r
+\r
+private:\r
+ volatile LONG m_nRef;\r
+};\r
+\r
+} // namespace\r
+\r
+void* __cdecl operator new(\r
+ size_t count\r
+ );\r
+\r
+void __cdecl operator delete(\r
+ void* object\r
+ );\r
+\r
+#endif // __cplusplus\r
--- /dev/null
+/*\r
+ * Copyright (c) 2008 Microsoft Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ * - Redistributions of source code must retain the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer.\r
+ *\r
+ * - Redistributions in binary form must reproduce the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer in the documentation and/or other materials\r
+ * provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id$\r
+ */\r
+\r
+\r
+#include <oib_ver.h>\r
+\r
+#define VER_FILETYPE VFT_DLL\r
+#define VER_FILESUBTYPE VFT2_UNKNOWN\r
+\r
+#ifdef _DEBUG_\r
+#define VER_FILEDESCRIPTION_STR "OpenFabrics Network Direct Provider (Debug)"\r
+#define VER_INTERNALNAME_STR "ibndprov.dll"\r
+#define VER_ORIGINALFILENAME_STR "ibndprov.dll"\r
+#else\r
+#define VER_FILEDESCRIPTION_STR "OpenFabrics Network Direct Provider"\r
+#define VER_INTERNALNAME_STR "ibndprov.dll"\r
+#define VER_ORIGINALFILENAME_STR "ibndprov.dll"\r
+#endif\r
+\r
+#include <common.ver>\r
+\r
# file to this component. This file merely indirects to the real make file\r
# that is shared by all the driver components of the OpenIB Windows project.\r
#\r
+\r
+DDK_BLOCK_ON_IA64=1\r
!INCLUDE ..\..\..\inc\openib.def\r
--- /dev/null
+/*\r
+ * Copyright (c) 2008 Microsoft Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ * - Redistributions of source code must retain the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer.\r
+ *\r
+ * - Redistributions in binary form must reproduce the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer in the documentation and/or other materials\r
+ * provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id:$\r
+ */\r
+\r
+#pragma once\r
+\r
+#ifdef __MODULE__\r
+#undef __MODULE__\r
+#endif\r
+#define __MODULE__ "[ND]"\r
+\r
+\r
+#include <complib/cl_debug.h>\r
+\r
+extern uint32_t g_nd_dbg_level;\r
+extern uint32_t g_nd_dbg_flags;\r
+\r
+#if defined(EVENT_TRACING)\r
+//\r
+// Software Tracing Definitions \r
+//\r
+\r
+\r
+#define WPP_CONTROL_GUIDS \\r
+ WPP_DEFINE_CONTROL_GUID(NDCtlGuid1,(1463B4CE,7A66,47a4,ABDB,09EE7AD9E698), \\r
+ WPP_DEFINE_BIT( ND_DBG_ERROR)\\r
+ WPP_DEFINE_BIT( ND_DBG_NDI))\r
+ \r
+\r
+\r
+#define WPP_LEVEL_FLAGS_ENABLED(lvl, flags) (WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= lvl)\r
+#define WPP_LEVEL_FLAGS_LOGGER(lvl,flags) WPP_LEVEL_LOGGER(flags)\r
+#define WPP_FLAG_ENABLED(flags)(WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= TRACE_LEVEL_VERBOSE)\r
+#define WPP_FLAG_LOGGER(flags) WPP_LEVEL_LOGGER(flags)\r
+\r
+\r
+// begin_wpp config\r
+// ND_ENTER( FLAG );\r
+// ND_EXIT( FLAG );\r
+// USEPREFIX(ND_PRINT, "%!STDPREFIX! [ND] :%!FUNC!() :");\r
+// USESUFFIX(ND_ENTER, " [ND] :%!FUNC!():[");\r
+// USESUFFIX(ND_EXIT, " [ND] :%!FUNC!():]");\r
+// end_wpp\r
+\r
+\r
+\r
+#else\r
+\r
+#include <wmistr.h>\r
+#include <evntrace.h>\r
+\r
+/*\r
+ * Debug macros\r
+ */\r
+\r
+\r
+/* Debug message source */\r
+#define ND_DBG_ERR (1 << 0)\r
+#define ND_DBG_NDI (1 << 1)\r
+\r
+#define ND_DBG_ERROR (CL_DBG_ERROR | ND_DBG_ERR)\r
+\r
+#if DBG\r
+\r
+// assignment of _level_ is need to to overcome warning C4127\r
+#define ND_PRINT( _level_,_flag_,_msg_) \\r
+ { \\r
+ if( g_nd_dbg_level >= (_level_) ) \\r
+ CL_TRACE( _flag_, g_nd_dbg_flags, _msg_ ); \\r
+ }\r
+\r
+\r
+#define ND_PRINT_EXIT( _level_,_flag_,_msg_) \\r
+ { \\r
+ if( g_nd_dbg_level >= (_level_) ) \\r
+ CL_TRACE( _flag_, g_nd_dbg_flags, _msg_ );\\r
+ ND_EXIT( _flag_ );\\r
+ }\r
+\r
+#define ND_ENTER( _flag_) \\r
+ { \\r
+ if( g_nd_dbg_level >= TRACE_LEVEL_VERBOSE ) \\r
+ CL_ENTER( _flag_, g_nd_dbg_flags ); \\r
+ }\r
+\r
+#define ND_EXIT( _flag_)\\r
+ { \\r
+ if( g_nd_dbg_level >= TRACE_LEVEL_VERBOSE ) \\r
+ CL_EXIT( _flag_, g_nd_dbg_flags ); \\r
+ }\r
+\r
+\r
+#else\r
+\r
+#define ND_PRINT( lvl, flags, msg)\r
+\r
+#define ND_PRINT_EXIT( _level_,_flag_,_msg_)\r
+\r
+#define ND_ENTER( _flag_)\r
+\r
+#define ND_EXIT( _flag_)\r
+\r
+\r
+#endif\r
+\r
+#endif //EVENT_TRACING\r
+\r
+\r
+#if DBG\r
+struct dbg_data\r
+{ \r
+ int64_t rcv_cnt;\r
+ int64_t rcv_pkts;\r
+ int64_t rcv_bytes;\r
+ int64_t rcv_pkts_err;\r
+ int64_t rcv_pkts_zero;\r
+ int64_t snd_cnt;\r
+ int64_t snd_pkts;\r
+ int64_t snd_bytes;\r
+ int64_t snd_pkts_err;\r
+ int64_t snd_pkts_zero;\r
+ int64_t c_cnt;\r
+ int64_t c_rcv_pkts;\r
+ int64_t c_rcv_bytes;\r
+ int64_t c_rcv_pkts_err;\r
+ int64_t c_snd_pkts;\r
+ int64_t c_snd_bytes;\r
+ int64_t c_snd_pkts_err;\r
+};\r
+\r
+extern dbg_data g;\r
+\r
+#endif\r