From: aestrin Date: Thu, 14 Feb 2008 01:07:26 +0000 (+0000) Subject: [QLGCVNIC] renamed vnic directory to match driver's new name X-Git-Url: https://openfabrics.org/gitweb/?a=commitdiff_plain;h=1e689469618b77264f9446d271030bab1ef884a2;p=~shefty%2Frdma-win.git [QLGCVNIC] renamed vnic directory to match driver's new name git-svn-id: svn://openib.tc.cornell.edu/gen1@943 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86 --- diff --git a/trunk/ulp/dirs b/trunk/ulp/dirs index 5f52f432..601a0de0 100644 --- a/trunk/ulp/dirs +++ b/trunk/ulp/dirs @@ -5,4 +5,4 @@ DIRS=\ ipoib \ srp \ wsd \ - qlc_vnic + qlgcvnic diff --git a/trunk/ulp/qlc_vnic/dirs b/trunk/ulp/qlc_vnic/dirs deleted file mode 100644 index ed41dcf4..00000000 --- a/trunk/ulp/qlc_vnic/dirs +++ /dev/null @@ -1,2 +0,0 @@ -DIRS=\ - kernel diff --git a/trunk/ulp/qlc_vnic/kernel/SOURCES b/trunk/ulp/qlc_vnic/kernel/SOURCES deleted file mode 100644 index 3a29204d..00000000 --- a/trunk/ulp/qlc_vnic/kernel/SOURCES +++ /dev/null @@ -1,81 +0,0 @@ -######################################################################## -# -# Copyright(c) Infinicon Systems All rights reserved. -# -######################################################################## - - -# The TARGETNAME. This is name of the item being built (without the -# extension. -TARGETNAME=qlgcvnic - -######################################################################## -# The path where all binaries are built. -# -TARGETPATH=..\..\..\bin\kernel\obj$(BUILD_ALT_DIR) - -######################################################################## -# The type of item that is being built. This is manditory. -# Value Meaning -# DYNLINK - A DLL. -# DRIVER - A kernel device driver. -# EXPORT_DRIVER - A kernel device driver with exports. -# PROGRAM - A windows executable. -# PROGLIB - A windows library. -# MINPORT - A miniport driver. -# GDI_DRIVER - A video driver. -# LIBRARY - A library -TARGETTYPE=MINIPORT - -######################################################################## -# The type of driver being built. This affects the include paths. -# Comment out for non-WDM drivers. -#DRIVERTYPE=WDM - -# -######################################################################## -# All the source files in this project. -# -SOURCES= inic.rc \ - vnic_driver.c \ - vnic_adapter.c \ - vnic_ib.c \ - vnic_control.c \ - vnic_data.c \ - vnic_netpath.c \ - vnic_viport.c \ - - - - -INCLUDES=..;..\..\..\inc;..\..\..\inc\kernel; - -C_DEFINES=$(C_DEFINES) -DNDIS_MINIPORT_DRIVER -DNDIS_WDM=1 \ - -DDEPRECATE_DDK_FUNCTIONS -DNDIS51_MINIPORT -DBINARY_COMPATIBLE=0 -DLBFO_ENABLED=1 - -#!if $(FREEBUILD) -# Free build will printout error messages -#C_DEFINES=$(C_DEFINES) -DFREE_BUILD_DBG=1 -#!endif - -TARGETLIBS= \ - $(DDK_LIB_PATH)\ntoskrnl.lib \ - $(DDK_LIB_PATH)\hal.lib \ - $(DDK_LIB_PATH)\ndis.lib \ - $(TARGETPATH)\*\complib.lib \ - $(TARGETPATH)\*\ibal.lib - -#!if !defined(DDK_TARGET_OS) || "$(DDK_TARGET_OS)"=="Win2K" -# -# The driver is built in the Win2K build environment -# - use the library version of safe strings -# -#TARGETLIBS= $(TARGETLIBS) $(DDK_LIB_PATH)\ntstrsafe.lib -#!endif - -######################################################################## -# Set the warning levels to maximum. -MSC_WARNING_LEVEL= /W4 -# - - diff --git a/trunk/ulp/qlc_vnic/kernel/inic.rc b/trunk/ulp/qlc_vnic/kernel/inic.rc deleted file mode 100644 index 84699441..00000000 --- a/trunk/ulp/qlc_vnic/kernel/inic.rc +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2005 SilverStorm Technologies. All rights reserved. - * - * This software is available to you under the OpenIB.org BSD license - * below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * $Id$ - */ - - -#include - -#define VER_FILETYPE VFT_DRV -#define VER_FILESUBTYPE VFT2_DRV_NETWORK - -#ifdef _DEBUG_ -#define VER_FILEDESCRIPTION_STR "QLogic VNIC NDIS Miniport (Debug)" -#else -#define VER_FILEDESCRIPTION_STR "QLogic VNIC NDIS Miniport" -#endif - -#define VER_INTERNALNAME_STR "qlgcvnic.sys" -#define VER_ORIGINALFILENAME_STR "qlgcvnic.sys" - -#include diff --git a/trunk/ulp/qlc_vnic/kernel/makefile b/trunk/ulp/qlc_vnic/kernel/makefile deleted file mode 100644 index 128ed372..00000000 --- a/trunk/ulp/qlc_vnic/kernel/makefile +++ /dev/null @@ -1,7 +0,0 @@ -# -# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source -# file to this component. This file merely indirects to the real make file -# that is shared by all the driver components of the Windows NT DDK -# - -!INCLUDE ..\..\..\inc\openib.def diff --git a/trunk/ulp/qlc_vnic/kernel/netvnic.inf b/trunk/ulp/qlc_vnic/kernel/netvnic.inf deleted file mode 100644 index fc4ae520..00000000 --- a/trunk/ulp/qlc_vnic/kernel/netvnic.inf +++ /dev/null @@ -1,206 +0,0 @@ -; QLogic Corporation Ethernet over Infiniband NIC. -; Copyright (c) QLogic Corporation all Rights Reserved. - -[Version] -Signature="$Windows NT$" -Class=Net -ClassGUID={4d36e972-e325-11ce-bfc1-08002be10318} -Provider=%Inf_Provider% -DriverVer=01/21/2008,1.0.0000.927 - -[ControlFlags] -ExcludeFromSelect = IBA\V00066aP00000030 - -; ================= Device Install section ===================== - -[DestinationDirs] -DefaultDestDir=12 - -[SourceDisksNames.x86] -1=%DiskId%,,,"" - -[SourceDisksNames.amd64] -1=%DiskId%,,,"" - -[SourceDisksNames.ia64] -1=%DiskId%,,,"" - -[SourceDisksFiles] -qlgcvnic.sys=1 - -[Manufacturer] -%Inf_Provider% = vnic.DeviceSection,ntx86,ntamd64,ntia64 - -[vnic.DeviceSection] -; empty since we don't support W9x/Me - -[vnic.DeviceSection.ntx86] -%vnic.DeviceDesc% = VNIC.DDInstall,IBA\V00066aP00000030S00066as00000030v0001, \ - IBA\V00066aP00000030S00066as00000030, \ - IBA\V00066aP00000030v0001, \ - IBA\V00066aP00000030 - -[vnic.DeviceSection.ntamd64] -%vnic.DeviceDesc% = vnic.DDInstall,IBA\V00066aP00000030S00066as00000030v0001, \ - IBA\V00066aP00000030S00066as00000030, \ - IBA\V00066aP00000030v0001, \ - IBA\V00066aP00000030 - -[vnic.DeviceSection.ntia64] -%vnic.DeviceDesc% = vnic.DDInstall,IBA\V00066aP00000030S00066as00000030v0001, \ - IBA\V00066aP00000030S00066as00000030, \ - IBA\V00066aP00000030v0001, \ - IBA\V00066aP00000030 - -[vnic.DDInstall.ntx86] -Characteristics = %CHARACTERISTICS% -AddReg = vnic.AddReg -CopyFiles = vnic.CopyFiles - -[vnic.DDInstall.ntamd64] -Characteristics = %CHARACTERISTICS% -AddReg = vnic.AddReg -CopyFiles = vnic.CopyFiles - -[vnic.DDInstall.ntia64] -Characteristics = %CHARACTERISTICS% -AddReg = vnic.AddReg -CopyFiles = vnic.CopyFiles - -[vnic.DDInstall.ntx86.Services] -AddService = qlgcvnic,%SPSVCINST_ASSOCSERVICE%,vnic.ServiceInstall,vnic.EventLogInstall - -[vnic.DDInstall.ntamd64.Services] -AddService = qlgcvnic,%SPSVCINST_ASSOCSERVICE%,vnic.ServiceInstall,vnic.EventLogInstall - -[vnic.DDInstall.ntia64.Services] -AddService = qlgcvnic,%SPSVCINST_ASSOCSERVICE%,vnic.ServiceInstall,vnic.EventLogInstall - -[vnic.CopyFiles] -qlgcvnic.sys,,,2 - -[vnic.AddReg] -HKR, Ndi, Service, 0, "qlgcvnic" -HKR, Ndi\Interfaces, UpperRange, 0, "ndis5" -HKR, Ndi\Interfaces, LowerRange, 0, "ethernet" - -HKR, Ndi\params\VlanId, ParamDesc, 0, "802.1q VlanId" -HKR, Ndi\params\VlanId, Type, 0, "dword" -HKR, Ndi\params\VlanId, Optional, 0, "1" -HKR, Ndi\params\VlanId, Default, 0, "1" -HKR, Ndi\params\VlanId, Min, 0, "1" -HKR, Ndi\params\VlanId, Max, 0, "4094" -HKR, Ndi\params\VlanId, Step, 0, "1" -HKR, Ndi\params\VlanId, Base, 0, "10" - -HKR, Ndi\params\UserPriority, ParamDesc, 0, "802.1p Priority" -HKR, Ndi\params\UserPriority, Type, 0, "dword" -HKR, Ndi\Params\UserPriority, Optional, 0, "1" -HKR, Ndi\params\UserPriority, Default, 0, "0" -HKR, Ndi\params\UserPriority, Min, 0, "0" -HKR, Ndi\params\UserPriority, Max, 0, "7" -HKR, Ndi\params\UserPriority, Step, 0, "1" - -HKR, Ndi\Params\PayloadMtu, ParamDesc, 0, "Payload Mtu size" -HKR, Ndi\Params\PayloadMtu, Type, 0, "dword" -HKR, Ndi\Params\PayloadMtu, Default, 0, "1500" -HKR, Ndi\Params\PayloadMtu, Min, 0, "1500" -HKR, Ndi\Params\PayloadMtu, Max, 0, "9500" -HKR, Ndi\Params\PayloadMtu, Step, 0, "100" -HKR, Ndi\Params\PayloadMtu, Base, 0, "10" - -HKR, Ndi\Params\UseTxCsum, ParamDesc, 0, "Send Chksum Offload" -HKR, Ndi\Params\UseTxCsum, Type, 0, "enum" -HKR, Ndi\Params\UseTxCsum, Default, 0, "1" -HKR, Ndi\Params\UseTxCsum, Optional, 0, "0" -HKR, Ndi\Params\UseTxCsum\enum, "0", 0, "Disabled" -HKR, Ndi\Params\UseTxCsum\enum, "1", 0, "Enabled" - -HKR, Ndi\Params\UseRxCsum,ParamDesc, 0, "Recv Chksum Offload" -HKR, Ndi\Params\UseRxCsum,Type, 0, "enum" -HKR, Ndi\Params\UseRxCsum,Default, 0, "1" -HKR, Ndi\Params\UseRxCsum,Optional, 0, "0" -HKR, Ndi\Params\UseRxCsum\enum, "0", 0, "Disabled" -HKR, Ndi\Params\UseRxCsum\enum, "1", 0, "Enabled" - -HKR, Ndi\Params\SecondaryPath, ParamDesc, 0, "Secondary path" -HKR, Ndi\Params\SecondaryPath, Type, 0, "enum" -HKR, Ndi\Params\SecondaryPath, Default, 0, "0" -HKR, Ndi\Params\SecondaryPath, Optional, 0, "0" -HKR, Ndi\Params\SecondaryPath\enum, "0", 0, "Disabled" -HKR, Ndi\Params\SecondaryPath\enum, "1", 0, "Enabled" - -HKR, Ndi\Params\Heartbeat, ParamDesc, 0, "Heartbeat interval (ms)" -HKR, Ndi\Params\Heartbeat, Type, 0, "dword" -HKR, Ndi\Params\Heartbeat, Default, 0, "2000" -HKR, Ndi\Params\Heartbeat, Min, 0, "0" -HKR, Ndi\Params\Heartbeat, Max, 0, "10000" -HKR, Ndi\Params\Heartbeat, Step, 0, "1000" -HKR, Ndi\Params\Heartbeat, Base, 0, "10" - -HKR, Ndi\Params\BundleId, ParamDesc, 0, "LBFO Bundle Id" -HKR, Ndi\Params\BundleId, Type, 0, "enum" -HKR, Ndi\Params\BundleId, Default, 0, "1" -HKR, Ndi\Params\BundleId, Optional, 0, "1" -HKR, Ndi\Params\BundleId\enum, "1", 0, "Bundle 1" -HKR, Ndi\Params\BundleId\enum, "2", 0, "Bundle 2" -HKR, Ndi\Params\BundleId\enum, "3", 0, "Bundle 3" -HKR, Ndi\Params\BundleId\enum, "4", 0, "Bundle 4" -; -; -; ============= Service Install section ============== -; - -[vnic.ServiceInstall] -DisplayName = %vnic.ServiceDesc% -ServiceType = %SERVICE_KERNEL_DRIVER% -StartType = %SERVICE_DEMAND_START% -ErrorControl = %SERVICE_ERROR_NORMAL% -ServiceBinary = %12%\qlgcvnic.sys -LoadOrderGroup = NDIS -AddReg = vnic.ParamsReg - -[vnic.ParamsReg] - -HKR,"Parameters","DebugFlags",%REG_DWORD%,0x00000003 - -HKR,"Parameters","MinHostPoolSz",%REG_DWORD%,256 -HKR, "Parameters","HostRecvPoolEntries",%REG_DWORD%,512 -HKR, "Parameters","MinEiocPoolSz",%REG_DWORD%,256 -HKR, "Parameters","MaxEiocPoolSz",%REG_DWORD%,512 -HKR, "Parameters","MinHostKickTimeout",%REG_DWORD%,50 -HKR, "Parameters","MaxHostKickTimeout",%REG_DWORD%,100 -HKR, "Parameters","MinHostKickEntries",%REG_DWORD%,1 -HKR, "Parameters","MaxHostKickEntries",%REG_DWORD%,64 -HKR, "Parameters","MinHostKickBytes",%REG_DWORD%,0 -HKR, "Parameters","MaxHostKickBytes",%REG_DWORD%,5000 -HKR, "Parameters","MinHostUpdateSz",%REG_DWORD%,8 -HKR, "Parameters","MaxHostUpdateSz",%REG_DWORD%,32 -HKR, "Parameters","MinEiocUpdateSz",%REG_DWORD%,8 -HKR, "Parameters","MaxEiocUpdateSz",%REG_DWORD%,32 -HKR, "Parameters","HeartbeatTimeout",%REG_DWORD%,40000 - -[vnic.EventLogInstall] -AddReg = vnic.EventLogAddReg - -[vnic.EventLogAddReg] -HKR,,EventMessageFile,%REG_EXPAND_SZ%,"%%SystemRoot%%\System32\netevent.dll" -HKR,,TypesSupported,%REG_DWORD%,7 - -[Strings] -NetClassGuid="{4d36e972-e325-11ce-bfc1-08002be10318}" -Inf_Provider="QLogic Corporation" -vnic.DeviceDesc="Ethernet over InfiniBand Virtual NIC" -vnic.ServiceDesc="Virtual NIC" -DiskId="QLogic Ethernet over InfiniBand Disk" -InternalBus=0 -PNPBus=15 -SPSVCINST_NULL=0x0 -SPSVCINST_ASSOCSERVICE=0x00000002 -SERVICE_KERNEL_DRIVER=1 -SERVICE_DEMAND_START=3 -SERVICE_ERROR_NORMAL=1 -REG_DWORD=0x00010001 -REG_DWORD_NO_CLOBBER=0x00010003 -REG_EXPAND_SZ=0x00020000 -CHARACTERISTICS=0x81; NCF_VIRTUAL | NCF_HAS_UI diff --git a/trunk/ulp/qlc_vnic/kernel/vnic_adapter.c b/trunk/ulp/qlc_vnic/kernel/vnic_adapter.c deleted file mode 100644 index 7be95023..00000000 --- a/trunk/ulp/qlc_vnic/kernel/vnic_adapter.c +++ /dev/null @@ -1,1815 +0,0 @@ -/* - * Copyright (c) 2007 QLogic Corporation. All rights reserved. - * - * This software is available to you under the OpenIB.org BSD license - * below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * $Id$ - */ - -#include -#include -#include -#include "vnic_adapter.h" - -//#include "vnic_driver.h" - -extern struct _vnic_globals g_vnic; - -NDIS_STATUS -vnic_get_adapter_params( - IN NDIS_HANDLE h_handle, - OUT vnic_params_t* const p_params ); - -static -NDIS_STATUS -_adapter_set_sg_size( - IN NDIS_HANDLE h_handle, - IN ULONG mtu_size ); - -NDIS_STATUS -vnic_get_adapter_interface( - IN NDIS_HANDLE h_handle, - IN vnic_adapter_t *p_adapter); - -static -vnic_path_record_t* -__path_record_add( - IN vnic_adapter_t* const p_adapter, - IN ib_path_rec_t* const p_path_rec ); - -static -vnic_path_record_t* -__path_record_remove( - IN vnic_adapter_t* const p_adapter, - IN ib_path_rec_t* const p_path_rec ); - -static BOOLEAN -__path_records_match( - IN ib_path_rec_t* const p_path1, - IN ib_path_rec_t* const p_path2 ); - -static -vnic_path_record_t * -__path_record_find( - IN vnic_adapter_t* const p_adapter, - IN ib_path_rec_t* const p_path_rec ); - -static -vnic_path_record_t* -__path_record_get( - IN vnic_adapter_t* const p_adapter ); - -static void -__path_records_cleanup( - IN vnic_adapter_t *p_adapter ); - -static ib_api_status_t -_adapter_open_ca( - IN vnic_adapter_t* const p_adapter ); - - -static ib_api_status_t -_adapter_close_ca( - IN vnic_adapter_t* const p_adapter ); - -static -ib_api_status_t -_adapter_netpath_update( - IN vnic_adapter_t* const p_adapter, - IN viport_t* const p_viport, - IN vnic_path_record_t* p_path ); - -static -ib_api_status_t -adapter_netpath_update_and_connect( - IN vnic_adapter_t* const p_adapter, - IN vnic_path_record_t *p_path ); - -static inline uint8_t -_get_ioc_num_from_iocguid( - IN ib_net64_t *p_iocguid ); - -static BOOLEAN -__sid_valid( - IN vnic_adapter_t *p_adapter, - IN ib_net64_t sid ); - -static void -__adapter_cleanup( - IN vnic_adapter_t *p_adapter ); - -#if ( LBFO_ENABLED ) - -static NDIS_STATUS -__adapter_set_failover_primary( - IN vnic_adapter_t* const p_adapter, - IN BOOLEAN promote_secondary ); - -static NDIS_STATUS -__adapter_set_failover_secondary( - IN vnic_adapter_t* const p_adapter, - IN NDIS_HANDLE primary_handle ); - -static void -__adapter_add_to_failover_list( - IN vnic_adapter_t* const p_adapter, - IN lbfo_state_t failover_state ); -static void -__adapter_remove_from_failover_list( - IN vnic_adapter_t* const p_adapter ); - -static -vnic_adapter_t* -__adapter_find_on_failover_list( - IN int list_flag, - IN uint32_t bundle_id ); - -#endif // LBFO_ENABLED - -ib_api_status_t -vnic_create_adapter( - IN NDIS_HANDLE h_handle, - IN NDIS_HANDLE wrapper_config_context, - OUT vnic_adapter_t** const pp_adapter) -{ - NDIS_STATUS status; - ib_api_status_t ib_status; - vnic_adapter_t *p_adapter; - - VNIC_ENTER( VNIC_DBG_ADAPTER ); - - status = NdisAllocateMemoryWithTag( &p_adapter, sizeof(vnic_adapter_t), 'pada'); - - if ( status != NDIS_STATUS_SUCCESS ) - { - VNIC_TRACE_EXIT(VNIC_DBG_ERROR,("Failed to allocate adapter\n")); - return IB_INSUFFICIENT_MEMORY; - } - - NdisZeroMemory( p_adapter, sizeof(vnic_adapter_t) ); - - NdisAllocateSpinLock( &p_adapter->lock ); - NdisAllocateSpinLock( &p_adapter->path_records_lock ); - NdisAllocateSpinLock( &p_adapter->pending_list_lock ); - NdisAllocateSpinLock( &p_adapter->cancel_list_lock ); - - InitializeListHead( &p_adapter->send_pending_list ); - InitializeListHead( &p_adapter->cancel_send_list ); - - cl_qlist_init( &p_adapter->path_records_list ); - - status = - vnic_get_adapter_params( wrapper_config_context, &p_adapter->params ); - - if ( status != NDIS_STATUS_SUCCESS ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - (" vnic_get_adapter_params failed with status %d\n", status)); - NdisFreeMemory( p_adapter, sizeof(vnic_adapter_t), 0 ); - return IB_INVALID_PARAMETER; - } - - status = vnic_get_adapter_interface( h_handle, p_adapter ); - if ( status != NDIS_STATUS_SUCCESS ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("failed status %x\n", status ) ); - NdisFreeMemory( p_adapter, sizeof(vnic_adapter_t), 0 ); - return IB_INVALID_PARAMETER; - } - - /*Open AL */ - ib_status = p_adapter->ifc.open_al( &p_adapter->h_al ); - if ( ib_status != IB_SUCCESS ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("ib_open_al returned %s\n", - p_adapter->ifc.get_err_str( ib_status )) ); - NdisFreeMemory( p_adapter, sizeof(vnic_adapter_t), 0 ); - return ib_status; - } - - /* we will use these indexes later as an viport instance ID for connect request - * since target requires unique instance per connection per IOC. - */ - p_adapter->primaryPath.instance = NETPATH_PRIMARY; - p_adapter->secondaryPath.instance = NETPATH_SECONDARY; - - /* set adapter level params here */ - p_adapter->vlan_info = p_adapter->params.VlanInfo; - -#if ( LBFO_ENABLED ) - - p_adapter->failover.bundle_id = p_adapter->params.bundle_id; - p_adapter->failover.fo_state = _ADAPTER_NOT_BUNDLED; - -#endif - - p_adapter->h_handle = h_handle; - *pp_adapter = p_adapter; - - VNIC_EXIT( VNIC_DBG_ADAPTER ); - return IB_SUCCESS; -} - - -void -vnic_destroy_adapter( - IN vnic_adapter_t *p_adapter) -{ - ib_api_status_t ib_status = IB_SUCCESS; - ib_pnp_handle_t h_pnp; - ib_al_handle_t h_al; - - VNIC_ENTER( VNIC_DBG_ADAPTER ); - - ASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL ); - - if( ( h_pnp = InterlockedExchangePointer( (void *)&p_adapter->h_pnp, NULL ) ) != NULL ) - { - ib_status = - p_adapter->ifc.dereg_pnp( h_pnp, NULL ); - } - - /* should not receive new path notifications anymore, safe to cleanup */ - - if( InterlockedCompareExchange( (volatile LONG *)&p_adapter->state, - INIC_DEREGISTERING, INIC_REGISTERED ) == INIC_REGISTERED ) - { - __adapter_cleanup( p_adapter ); - } - - _adapter_close_ca( p_adapter ); - -#if ( LBFO_ENABLED ) - - __adapter_remove_from_failover_list( p_adapter ); - -#endif - - InterlockedExchange( (volatile LONG *)&p_adapter->state, INIC_UNINITIALIZED ); - if( ( h_al = InterlockedExchangePointer( (void *)&p_adapter->h_al, NULL ) ) != NULL ) - { - ib_status = p_adapter->ifc.close_al( h_al ); - ASSERT( ib_status == IB_SUCCESS ); - } - - NdisFreeSpinLock( &p_adapter->lock ); - NdisFreeSpinLock( &p_adapter->path_records_lock ); - NdisFreeMemory( p_adapter, sizeof(vnic_adapter_t), 0 ); - p_adapter = NULL; - - VNIC_EXIT( VNIC_DBG_ADAPTER ); -} - -static ib_api_status_t -_adapter_open_ca( - IN vnic_adapter_t* const p_adapter ) -{ - ib_api_status_t ib_status = IB_SUCCESS; - ib_al_ifc_t *p_ifc = &p_adapter->ifc; - uint32_t attr_size; - ib_ca_attr_t *p_ca_attrs; - uint32_t num; - uint64_t start_addr = 0; - - if( p_adapter->h_ca ) - return ib_status; - - ib_status = p_ifc->open_ca( p_adapter->h_al, - p_adapter->ifc_data.ca_guid, - NULL, //ib_asyncEvent, - p_adapter, - &p_adapter->h_ca ); - - if ( ib_status != IB_SUCCESS ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("Failed to open hca\n") ); - return IB_INSUFFICIENT_RESOURCES; - } - - ib_status = p_ifc->query_ca( p_adapter->h_ca, NULL , &attr_size ); - if( ib_status != IB_INSUFFICIENT_MEMORY ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("ib_query_ca failed status %s\n", - p_ifc->get_err_str( ib_status )) ); - - ib_status = IB_INSUFFICIENT_RESOURCES; - goto ca_failure; - } - - ASSERT( attr_size ); - - p_ca_attrs = cl_zalloc( attr_size ); - if ( p_ca_attrs == NULL ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("Allocate %d bytes failed for Channel adapter\n", attr_size )); - - ib_status = IB_INSUFFICIENT_MEMORY; - goto ca_failure; - } - - ib_status = p_ifc->query_ca( p_adapter->h_ca, p_ca_attrs , &attr_size ); - if ( ib_status != IB_SUCCESS ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("CA attributes query failed\n") ); - cl_free ( p_ca_attrs ); - goto ca_failure; - } - - p_adapter->ca.numPorts = p_ca_attrs->num_ports; - if( p_adapter->ca.numPorts > VNIC_CA_MAX_PORTS ) - p_adapter->ca.numPorts = VNIC_CA_MAX_PORTS; - - for( num = 0; num < p_adapter->ca.numPorts; num++ ) - p_adapter->ca.portGuids[num] = p_ca_attrs->p_port_attr[num].port_guid; - - p_adapter->ca.caGuid = p_adapter->ifc_data.ca_guid; - - cl_free ( p_ca_attrs ); - - ib_status = p_adapter->ifc.alloc_pd( p_adapter->h_ca, - IB_PDT_NORMAL, p_adapter, &p_adapter->ca.hPd ); - if ( ib_status != IB_SUCCESS ) - { - VNIC_TRACE_EXIT ( VNIC_DBG_ERROR, - ("Alloc PD failed status %s(%d)\n", - p_adapter->ifc.get_err_str(ib_status), ib_status )); - goto ca_failure; - } - - if ( ( ib_status = ibregion_physInit( p_adapter, - &p_adapter->ca.region, - p_adapter->ca.hPd, - &start_addr, - MAX_PHYS_MEMORY ) ) != IB_SUCCESS ) - { - VNIC_TRACE_EXIT ( VNIC_DBG_ERROR, - ("phys region init failed status %s(%d)\n", - p_adapter->ifc.get_err_str(ib_status), ib_status )); - p_adapter->ifc.dealloc_pd( p_adapter->ca.hPd, NULL ); - goto ca_failure; - } - - return ib_status; - -ca_failure: - if( p_adapter->h_ca ) - p_ifc->close_ca( p_adapter->h_ca, NULL ); - - return ib_status; -} - -static BOOLEAN -_adapter_params_sanity_check(vnic_params_t *p_params) -{ - DEFAULT_PARAM( p_params->MaxAddressEntries, MAX_ADDRESS_ENTRIES ); - DEFAULT_PARAM( p_params->MinAddressEntries, MIN_ADDRESS_ENTRIES ); - - DEFAULT_PARAM( p_params->ViportStatsInterval, VIPORT_STATS_INTERVAL ); - DEFAULT_PARAM( p_params->ViportHbInterval, VIPORT_HEARTBEAT_INTERVAL ); - DEFAULT_PARAM( p_params->ViportHbTimeout, VIPORT_HEARTBEAT_TIMEOUT ); - - DEFAULT_PARAM( p_params->ControlRspTimeout, CONTROL_RSP_TIMEOUT ); - DEFAULT_PARAM( p_params->ControlReqRetryCount, CONTROL_REQ_RETRY_COUNT ); - - DEFAULT_PARAM( p_params->RetryCount, RETRY_COUNT ); - DEFAULT_PARAM( p_params->MinRnrTimer, MIN_RNR_TIMER ); - - DEFAULT_PARAM( p_params->MaxViportsPerNetpath, MAX_VIPORTS_PER_NETPATH ); - DEFAULT_PARAM( p_params->DefaultViportsPerNetpath, DEFAULT_VIPORTS_PER_NETPATH ); - - DEFAULT_PARAM( p_params->DefaultPkey, DEFAULT_PKEY ); - DEFAULT_PARAM( p_params->NotifyBundleSz, NOTIFY_BUNDLE_SZ ); - DEFAULT_PARAM( p_params->DefaultNoPathTimeout, DEFAULT_NO_PATH_TIMEOUT ); - DEFAULT_PARAM( p_params->DefaultPrimaryConnectTimeout, DEFAULT_PRI_CON_TIMEOUT ); - DEFAULT_PARAM( p_params->DefaultPrimaryReconnectTimeout, DEFAULT_PRI_RECON_TIMEOUT ); - DEFAULT_PARAM( p_params->DefaultPrimarySwitchTimeout, DEFAULT_PRI_SWITCH_TIMEOUT ); - DEFAULT_PARAM( p_params->DefaultPreferPrimary, DEFAULT_PREFER_PRIMARY ); - - U32_RANGE( p_params->MaxAddressEntries ); - U32_RANGE( p_params->MinAddressEntries ); - RANGE_CHECK( p_params->MinMtu, MIN_MTU, MAX_MTU ); - RANGE_CHECK( p_params->MaxMtu, MIN_MTU, MAX_MTU ); - U32_RANGE( p_params->HostRecvPoolEntries ); - U32_RANGE( p_params->MinHostPoolSz ); - U32_RANGE( p_params->MinEiocPoolSz ); - U32_RANGE( p_params->MaxEiocPoolSz ); - U32_ZERO_RANGE( p_params->MinHostKickTimeout ); - U32_ZERO_RANGE( p_params->MaxHostKickTimeout ); - U32_ZERO_RANGE( p_params->MinHostKickEntries ); - U32_ZERO_RANGE( p_params->MaxHostKickEntries ); - U32_ZERO_RANGE( p_params->MinHostKickBytes ); - U32_ZERO_RANGE( p_params->MaxHostKickBytes ); - U32_RANGE( p_params->MinHostUpdateSz ); - U32_RANGE( p_params->MaxHostUpdateSz ); - U32_RANGE( p_params->MinEiocUpdateSz ); - U32_RANGE( p_params->MaxEiocUpdateSz ); - U8_RANGE( p_params->NotifyBundleSz ); - U32_ZERO_RANGE( p_params->ViportStatsInterval ); - U32_ZERO_RANGE( p_params->ViportHbInterval ); - U32_ZERO_RANGE( p_params->ViportHbTimeout ); - U32_RANGE( p_params->ControlRspTimeout ); - U8_RANGE( p_params->ControlReqRetryCount ); - ZERO_RANGE_CHECK( p_params->RetryCount, 0, 7 ); - ZERO_RANGE_CHECK( p_params->MinRnrTimer, 0, 31 ); - U32_RANGE( p_params->DefaultViportsPerNetpath ); - U8_RANGE( p_params->MaxViportsPerNetpath ); - U16_ZERO_RANGE( p_params->DefaultPkey ); - U32_RANGE( p_params->DefaultNoPathTimeout ); - U32_RANGE( p_params->DefaultPrimaryConnectTimeout ); - U32_RANGE( p_params->DefaultPrimaryReconnectTimeout ); - U32_RANGE( p_params->DefaultPrimarySwitchTimeout ); - BOOLEAN_RANGE( p_params->DefaultPreferPrimary ); - BOOLEAN_RANGE( p_params->UseRxCsum ); - BOOLEAN_RANGE( p_params->UseTxCsum ); - - LESS_THAN_OR_EQUAL( p_params->MinAddressEntries, p_params->MaxAddressEntries ); - LESS_THAN_OR_EQUAL( p_params->MinMtu, p_params->MaxMtu ); - LESS_THAN_OR_EQUAL( p_params->MinHostPoolSz, p_params->HostRecvPoolEntries ); - POWER_OF_2( p_params->HostRecvPoolEntries ); - POWER_OF_2( p_params->MinHostPoolSz ); - POWER_OF_2( p_params->NotifyBundleSz ); - LESS_THAN( p_params->NotifyBundleSz, p_params->MinEiocPoolSz ); - LESS_THAN_OR_EQUAL( p_params->MinEiocPoolSz, p_params->MaxEiocPoolSz ); - POWER_OF_2( p_params->MinEiocPoolSz ); - POWER_OF_2( p_params->MaxEiocPoolSz ); - LESS_THAN_OR_EQUAL( p_params->MinHostKickTimeout, p_params->MaxHostKickTimeout ); - LESS_THAN_OR_EQUAL( p_params->MinHostKickEntries, p_params->MaxHostKickEntries ); - LESS_THAN_OR_EQUAL( p_params->MinHostKickBytes, p_params->MaxHostKickBytes ); - LESS_THAN_OR_EQUAL( p_params->MinHostUpdateSz, p_params->MaxHostUpdateSz ); - POWER_OF_2( p_params->MinHostUpdateSz ); - POWER_OF_2( p_params->MaxHostUpdateSz ); - LESS_THAN( p_params->MinHostUpdateSz, p_params->MinHostPoolSz ); - LESS_THAN( p_params->MaxHostUpdateSz, p_params->HostRecvPoolEntries ); - LESS_THAN_OR_EQUAL( p_params->MinEiocUpdateSz, p_params->MaxEiocUpdateSz ); - POWER_OF_2( p_params->MinEiocUpdateSz ); - POWER_OF_2( p_params->MaxEiocUpdateSz ); - LESS_THAN( p_params->MinEiocUpdateSz, p_params->MinEiocPoolSz ); - LESS_THAN( p_params->MaxEiocUpdateSz, p_params->MaxEiocPoolSz ); - LESS_THAN_OR_EQUAL( p_params->DefaultViportsPerNetpath, p_params->MaxViportsPerNetpath ); - - return TRUE; - -} -NDIS_STATUS -vnic_get_adapter_params( - IN NDIS_HANDLE wrapper_config_context, - OUT vnic_params_t* const p_params ) -{ - NDIS_STATUS status; - NDIS_HANDLE h_config; - NDIS_CONFIGURATION_PARAMETER *p_reg_prm; - NDIS_STRING keyword; - - VNIC_ENTER( VNIC_DBG_ADAPTER ); - - CL_ASSERT(p_params ); - - /* prepare params for default initialization */ - cl_memset( p_params, 0xff, sizeof (vnic_params_t) ); - - NdisOpenConfiguration( &status, &h_config, wrapper_config_context ); - if( status != NDIS_STATUS_SUCCESS ) - { - VNIC_TRACE_EXIT( VNIC_DBG_ERROR, - ("NdisOpenConfiguration returned 0x%.8x\n", status) ); - return status; - } - - status = NDIS_STATUS_FAILURE; - p_reg_prm = NULL; - - RtlInitUnicodeString( &keyword, L"PayloadMtu" ); - NdisReadConfiguration( - &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger ); - - p_params->MinMtu = ( status != NDIS_STATUS_SUCCESS ) ? MIN_MTU: - p_reg_prm->ParameterData.IntegerData; - p_params->MaxMtu = MAX_MTU; - - RtlInitUnicodeString( &keyword, L"UseRxCsum" ); - NdisReadConfiguration( - &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger ); - - p_params->UseRxCsum = ( status != NDIS_STATUS_SUCCESS ) ? - TRUE : ( p_reg_prm->ParameterData.IntegerData )? TRUE : FALSE; - - RtlInitUnicodeString( &keyword, L"UseTxCsum" ); - NdisReadConfiguration( - &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger ); - - /* turn it on by default, if not present */ - p_params->UseTxCsum = ( status != NDIS_STATUS_SUCCESS ) ? - TRUE : ( p_reg_prm->ParameterData.IntegerData )? TRUE : FALSE; - - /* handle VLAN + Priority paramters */ - RtlInitUnicodeString( &keyword, L"VlanId" ); - NdisReadConfiguration( - &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger ); - - if( status == NDIS_STATUS_SUCCESS ) - { - p_params->VlanInfo = - ( p_reg_prm->ParameterData.IntegerData & 0x00000fff ); - - RtlInitUnicodeString( &keyword, L"UserPriority" ); - NdisReadConfiguration( - &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger ); - - p_params->VlanInfo |= ( status != NDIS_STATUS_SUCCESS ) ? 0 : - ( ( p_reg_prm->ParameterData.IntegerData & 0x00000007 ) << 13 ); - } - else - { - p_params->VlanInfo = 0; - } - - RtlInitUnicodeString( &keyword, L"SecondaryPath" ); - NdisReadConfiguration( - &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger ); - - /* disable, if not set. Save extra viport slot */ - p_params->SecondaryPath = ( status != NDIS_STATUS_SUCCESS ) ? - FALSE : ( p_reg_prm->ParameterData.IntegerData )? TRUE : FALSE; - - RtlInitUnicodeString( &keyword, L"Heartbeat" ); - NdisReadConfiguration( - &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger ); - - p_params->ViportHbInterval = ( status != NDIS_STATUS_SUCCESS ) ? - VIPORT_HEARTBEAT_INTERVAL : p_reg_prm->ParameterData.IntegerData; - -#if ( LBFO_ENABLED ) - /* read Failover group Name/Number */ - - RtlInitUnicodeString( &keyword, L"BundleId" ); - NdisReadConfiguration( - &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger ); - - p_params->bundle_id = ( status != NDIS_STATUS_SUCCESS ) ? 0 : - p_reg_prm->ParameterData.IntegerData; -#endif // LBFO_ENABLED - - NdisCloseConfiguration( h_config ); - - /* initialize the rest of adapter parameters with driver's global set */ - if( g_vnic.p_params != NULL ) - { - /* get global parameters from service entry */ - p_params->MinHostPoolSz = g_vnic.p_params[INDEX_MIN_HOST_POOL_SZ].value; - p_params->HostRecvPoolEntries = g_vnic.p_params[INDEX_HOST_RECV_POOL_ENTRIES].value; - - p_params->MinEiocPoolSz = g_vnic.p_params[INDEX_MIN_EIOC_POOL_SZ].value; - p_params->MaxEiocPoolSz = g_vnic.p_params[INDEX_MAX_EIOC_POOL_SZ].value; - - p_params->MinHostKickTimeout = g_vnic.p_params[INDEX_MIN_HOST_KICK_TIMEOUT].value; - p_params->MaxHostKickTimeout = g_vnic.p_params[INDEX_MAX_HOST_KICK_TIMEOUT].value; - - p_params->MinHostKickEntries = g_vnic.p_params[INDEX_MIN_HOST_KICK_ENTRIES].value; - p_params->MaxHostKickEntries = g_vnic.p_params[INDEX_MAX_HOST_KICK_ENTRIES].value; - - p_params->MinHostKickBytes = g_vnic.p_params[INDEX_MIN_HOST_KICK_BYTES].value; - p_params->MaxHostKickBytes = g_vnic.p_params[INDEX_MAX_HOST_KICK_BYTES].value; - - p_params->MinHostUpdateSz = g_vnic.p_params[INDEX_MIN_HOST_UPDATE_SZ].value; - p_params->MaxHostUpdateSz = g_vnic.p_params[INDEX_MAX_HOST_UPDATE_SZ].value; - - p_params->MinEiocUpdateSz = g_vnic.p_params[INDEX_MIN_EIOC_UPDATE_SZ].value; - p_params->MaxEiocUpdateSz = g_vnic.p_params[INDEX_MAX_EIOC_UPDATE_SZ].value; - - p_params->ViportHbTimeout = g_vnic.p_params[INDEX_HEARTBEAT_TIMEOUT].value; - } - else - { - /* set default constants */ - p_params->MinHostPoolSz = MIN_HOST_POOL_SZ; - p_params->HostRecvPoolEntries = HOST_RECV_POOL_ENTRIES; - p_params->MinEiocPoolSz = MIN_EIOC_POOL_SZ; - p_params->MaxEiocPoolSz = MAX_EIOC_POOL_SZ; - p_params->MinHostKickTimeout = MIN_HOST_KICK_TIMEOUT; - p_params->MaxHostKickTimeout = MAX_HOST_KICK_TIMEOUT; - p_params->MinHostKickEntries = MIN_HOST_KICK_ENTRIES; - p_params->MaxHostKickEntries = MAX_HOST_KICK_ENTRIES; - p_params->MinHostKickBytes = MIN_HOST_KICK_BYTES; - p_params->MaxHostKickBytes = MAX_HOST_KICK_BYTES; - p_params->MinHostUpdateSz = MIN_HOST_UPDATE_SZ; - p_params->MaxHostUpdateSz = MAX_HOST_UPDATE_SZ; - p_params->MinEiocUpdateSz = MIN_EIOC_UPDATE_SZ; - p_params->MaxEiocUpdateSz = MAX_EIOC_UPDATE_SZ; - } - - status = ( _adapter_params_sanity_check(p_params)? - NDIS_STATUS_SUCCESS: NDIS_STATUS_FAILURE ); - - VNIC_EXIT( VNIC_DBG_ADAPTER ); - return status; -} - -ib_api_status_t -adapter_viport_allocate( - IN vnic_adapter_t* const p_adapter, - IN OUT viport_t** const pp_viport ) -{ - viport_t *p_viport; - NDIS_STATUS status; - - VNIC_ENTER( VNIC_DBG_ADAPTER ); - - NdisAcquireSpinLock( &p_adapter->lock ); - - status = NdisAllocateMemoryWithTag( &p_viport, sizeof(viport_t), 'trop' ); - if( status != NDIS_STATUS_SUCCESS ) - { - NdisReleaseSpinLock( &p_adapter->lock ); - VNIC_TRACE_EXIT(VNIC_DBG_ERROR, - ( "Failed allocating Viport structure\n" )); - return IB_ERROR; - } - - NdisZeroMemory( p_viport, sizeof(viport_t) ); - NdisAllocateSpinLock( &p_viport->lock ); - InitializeListHead( &p_viport->listPtrs ); - cl_event_init( &p_viport->sync_event, FALSE ); - - p_viport->p_adapter = p_adapter; - viport_config_defaults ( p_viport ); - - control_construct( &p_viport->control, p_viport ); - data_construct( &p_viport->data, p_viport ); - - p_viport->ioc_num = _get_ioc_num_from_iocguid( &p_adapter->ifc_data.guid ); - if( !p_adapter->ioc_num ) - { - p_adapter->ioc_num = p_viport->ioc_num; - } - - CL_ASSERT( p_adapter->ioc_num == p_viport->ioc_num ); - - *pp_viport = p_viport; - - NdisReleaseSpinLock( &p_adapter->lock ); - - VNIC_EXIT( VNIC_DBG_ADAPTER ); - return IB_SUCCESS; -} - - -static void -_adapter_netpath_free( - IN vnic_adapter_t* const p_adapter, - IN Netpath_t* p_netpath ) -{ - - UNREFERENCED_PARAMETER( p_adapter ); - - if( netpath_is_valid( p_netpath ) ) - { - VNIC_TRACE( VNIC_DBG_INFO, - ("IOC[%d] instance %d Free Path\n", - p_adapter->ioc_num, p_netpath->instance )); - - netpath_free( p_netpath ); - netpath_init( p_netpath, NULL ); - } -} - -NDIS_STATUS -adapter_set_mcast( - IN vnic_adapter_t* const p_adapter, - IN mac_addr_t* const p_mac_array, - IN const uint8_t mc_count ) -{ - NDIS_STATUS status; - int i; - VNIC_ENTER( VNIC_DBG_MCAST ); - - if( !netpath_is_valid( p_adapter->p_currentPath ) ) - return NDIS_STATUS_NOT_ACCEPTED; - - VNIC_TRACE( VNIC_DBG_MCAST, - ("IOC[%d] MCAST COUNT to set = %d\n", - p_adapter->ioc_num, mc_count)); - - /* Copy the MC address list into the adapter. */ - if( mc_count ) - { - RtlCopyMemory( - p_adapter->mcast_array, p_mac_array, mc_count * MAC_ADDR_LEN ); - for( i = 0; i < mc_count; i++ ) - VNIC_TRACE( VNIC_DBG_MCAST, - ("[%d] %02x:%02x:%02x:%02x:%02x:%02x\n", i, - p_mac_array->addr[0], p_mac_array->addr[1], p_mac_array->addr[2], - p_mac_array->addr[3], p_mac_array->addr[4], p_mac_array->addr[5] )); - } - p_adapter->mc_count = mc_count; - - p_adapter->pending_set = TRUE; - status = netpath_setMulticast( p_adapter->p_currentPath ); - if( status != NDIS_STATUS_PENDING ) - { - p_adapter->pending_set = FALSE; - } - - VNIC_EXIT( VNIC_DBG_MCAST ); - return status; -} - - -static BOOLEAN -__path_records_match( - IN ib_path_rec_t* const p_path1, - IN ib_path_rec_t* const p_path2 ) -{ - if( p_path1->dgid.unicast.prefix != p_path2->dgid.unicast.prefix ) - return FALSE; - if( p_path1->dgid.unicast.interface_id != p_path2->dgid.unicast.interface_id ) - return FALSE; - if( p_path1->dlid != p_path2->dlid ) - return FALSE; - - if( p_path1->sgid.unicast.prefix != p_path2->sgid.unicast.prefix ) - return FALSE; - if( p_path1->sgid.unicast.interface_id != p_path2->sgid.unicast.interface_id ) - return FALSE; - if( p_path1->slid != p_path2->slid ) - return FALSE; - - if( p_path1->pkey != p_path2->pkey ) - return FALSE; - if( p_path1->rate != p_path2->rate ) - return FALSE; - if( p_path1->sl != p_path2->sl ) - return FALSE; - if( p_path1->tclass != p_path2->tclass ) - return FALSE; - - return TRUE; -} - -static BOOLEAN -__sid_valid( - IN vnic_adapter_t *p_adapter, - IN ib_net64_t sid ) -{ - vnic_sid_t svc_id; - svc_id.as_uint64 = sid; - if( ( svc_id.s.base_id & 0x10 ) != 0x10 ) - return FALSE; - if( svc_id.s.oui[0] != 0x00 && - svc_id.s.oui[1] != 0x06 && - svc_id.s.oui[2] != 0x6a ) - return FALSE; - if ( svc_id.s.type != CONTROL_SID && - svc_id.s.type != DATA_SID ) - return FALSE; - if ( svc_id.s.ioc_num != _get_ioc_num_from_iocguid( &p_adapter->ifc_data.guid ) ) - return FALSE; - return TRUE; -} -static inline uint8_t -_get_ioc_num_from_iocguid( - IN ib_net64_t *p_iocguid ) -{ - return ( (vnic_ioc_guid_t *)p_iocguid)->s.ioc_num; -} - -static -vnic_path_record_t* -__path_record_add( - IN vnic_adapter_t* const p_adapter, - IN ib_path_rec_t* const p_path_rec ) -{ - - vnic_path_record_t *p_path; - - p_path = __path_record_find( p_adapter, p_path_rec ); - - if( !p_path ) - { - p_path = cl_zalloc( sizeof( vnic_path_record_t ) ); - if( !p_path ) - return NULL; - - NdisAcquireSpinLock( &p_adapter->path_records_lock ); - - p_path->path_rec = *p_path_rec; - cl_qlist_insert_tail( &p_adapter->path_records_list, &p_path->list_entry ); - - NdisReleaseSpinLock( &p_adapter->path_records_lock ); - - VNIC_TRACE( VNIC_DBG_PNP, - ("New path Added to the list[ list size %d]\n", - cl_qlist_count(&p_adapter->path_records_list) )); - - return p_path; - } - VNIC_TRACE( VNIC_DBG_PNP, - ( "Path to add is already on the List\n" ) ); - - return NULL; -} - -static -vnic_path_record_t* -__path_record_get( - IN vnic_adapter_t* const p_adapter ) -{ - cl_list_item_t *p_item; - - p_item = cl_qlist_head( &p_adapter->path_records_list ); - - if( p_item != cl_qlist_end( &p_adapter->path_records_list ) ) - { - return ( vnic_path_record_t *)p_item; - } - return NULL; -} - -static -vnic_path_record_t* -__path_record_remove( - IN vnic_adapter_t* const p_adapter, - IN ib_path_rec_t* const p_path_rec ) -{ - - vnic_path_record_t *p_path; - - - p_path = __path_record_find( p_adapter, p_path_rec ); - - if ( p_path ) - { - NdisAcquireSpinLock( &p_adapter->path_records_lock ); - - cl_qlist_remove_item( &p_adapter->path_records_list, &p_path->list_entry ); - - NdisReleaseSpinLock( &p_adapter->path_records_lock ); - } - - return p_path; -} - -static -vnic_path_record_t * -__path_record_find( - IN vnic_adapter_t* const p_adapter, - IN ib_path_rec_t* const p_path_rec ) -{ - cl_list_item_t *p_item; - vnic_path_record_t *p_path = NULL; - - NdisAcquireSpinLock( &p_adapter->path_records_lock ); - - if( !cl_qlist_count( &p_adapter->path_records_list ) ) - { - NdisReleaseSpinLock( &p_adapter->path_records_lock ); - return NULL; - } - - p_item = cl_qlist_head( &p_adapter->path_records_list ); - - while( p_item != cl_qlist_end( &p_adapter->path_records_list ) ) - { - p_path = ( vnic_path_record_t *)p_item; - - if ( __path_records_match( &p_path->path_rec, p_path_rec ) ) - { - break; - } - - p_item = cl_qlist_next( p_item ); - } - - NdisReleaseSpinLock( &p_adapter->path_records_lock ); - - if( p_item == cl_qlist_end( &p_adapter->path_records_list ) ) - { - p_path = NULL; - } - return p_path; -} - -void -__pending_queue_cleanup( - IN vnic_adapter_t *p_adapter ) -{ - LIST_ENTRY *p_list_item; - NDIS_PACKET *p_packet; - - VNIC_ENTER( VNIC_DBG_ADAPTER ); - - /* clear pending queue if any */ - - while( ( p_list_item = NdisInterlockedRemoveHeadList( - &p_adapter->send_pending_list, - &p_adapter->pending_list_lock )) != NULL ) - { - p_packet = VNIC_PACKET_FROM_LIST_ITEM( p_list_item ); - if ( p_packet ) - { - NDIS_SET_PACKET_STATUS( p_packet, NDIS_STATUS_FAILURE ); - NdisMSendComplete( p_adapter->h_handle, p_packet, NDIS_STATUS_FAILURE ); - } - } - - VNIC_EXIT( VNIC_DBG_ADAPTER ); -} - -static void -__path_records_cleanup( - vnic_adapter_t *p_adapter ) -{ - - vnic_path_record_t *p_path; - cl_list_item_t *p_item; - - p_item = cl_qlist_remove_head( &p_adapter->path_records_list ); - - while( p_item != cl_qlist_end( &p_adapter->path_records_list ) ) - { - p_path = (vnic_path_record_t *)p_item; - - cl_free( p_path ); - - p_item = cl_qlist_remove_head( &p_adapter->path_records_list ); - } - - return; -} - -ib_api_status_t -__vnic_pnp_cb( - IN ib_pnp_rec_t *p_pnp_rec ) -{ - ib_api_status_t ib_status = IB_SUCCESS; - ib_pnp_ioc_rec_t *p_ioc_rec; - ib_pnp_ioc_path_rec_t *p_ioc_path; - vnic_path_record_t *p_path_record; - Netpath_t* p_netpath = NULL; - -#if ( LBFO_ENABLED ) - vnic_adapter_t *p_primary_adapter; -#endif - - vnic_adapter_t * __ptr64 p_adapter = (vnic_adapter_t * __ptr64)p_pnp_rec->pnp_context; - - VNIC_ENTER( VNIC_DBG_PNP ); - - CL_ASSERT( p_adapter ); - - switch( p_pnp_rec->pnp_event ) - { - case IB_PNP_IOC_ADD: - p_ioc_rec = (ib_pnp_ioc_rec_t*)p_pnp_rec; - - if( p_adapter->ifc_data.ca_guid != p_ioc_rec->ca_guid ) - { - ib_status = IB_INVALID_GUID; - break; - } - if( p_adapter->ifc_data.guid != p_ioc_rec->info.profile.ioc_guid ) - { - ib_status = IB_INVALID_GUID; - break; - } - InterlockedExchange( (volatile LONG*)&p_adapter->pnp_state, IB_PNP_IOC_ADD ); - - VNIC_TRACE( VNIC_DBG_PNP, ("IB_PNP_IOC_ADD for %s.\n", - p_ioc_rec->info.profile.id_string) ); - - /* get ioc profile data */ - NdisAcquireSpinLock( &p_adapter->lock ); - - if( !__sid_valid( p_adapter, p_ioc_rec->svc_entry_array[0].id ) ) - { - NdisReleaseSpinLock( &p_adapter->lock ); - - VNIC_TRACE_EXIT( VNIC_DBG_ERROR, - ("Invalid Service ID %#I64x\n",p_ioc_rec->svc_entry_array[0].id ) ); - - ib_status = IB_INVALID_GUID; // should it be set INVALID_SERVICE_TYPE ? - break; - } - - p_adapter->ioc_info = p_ioc_rec->info; - CL_ASSERT(p_adapter->ioc_info.profile.num_svc_entries == 2 ); - - p_adapter->svc_entries[0] = p_ioc_rec->svc_entry_array[0]; - p_adapter->svc_entries[1] = p_ioc_rec->svc_entry_array[1]; - p_adapter->ioc_num = _get_ioc_num_from_iocguid( &p_adapter->ifc_data.guid ); - - VNIC_TRACE( VNIC_DBG_PNP, - ("Found %d Service Entries.\n", p_adapter->ioc_info.profile.num_svc_entries)); - - NdisReleaseSpinLock( &p_adapter->lock ); - - break; - - case IB_PNP_IOC_REMOVE: - CL_ASSERT( p_pnp_rec->guid == p_adapter->ifc_data.guid ); - - p_ioc_rec = (ib_pnp_ioc_rec_t*)p_pnp_rec; - - if( InterlockedExchange( (volatile LONG*)&p_adapter->pnp_state, IB_PNP_IOC_REMOVE ) == IB_PNP_IOC_ADD ) - { - VNIC_TRACE( VNIC_DBG_INIT, ("IB_PNP_IOC_REMOVE for %s.\n", - p_adapter->ioc_info.profile.id_string) ); - - if( netpath_is_valid( p_adapter->p_currentPath ) ) - { - netpath_stopXmit( p_adapter->p_currentPath ); - InterlockedExchange( &p_adapter->p_currentPath->carrier, (LONG)FALSE ); - netpath_linkDown( p_adapter->p_currentPath ); - __pending_queue_cleanup( p_adapter ); - } - } - break; - - case IB_PNP_IOC_PATH_ADD: - /* path for our IOC ? */ - if ( p_pnp_rec->guid != p_adapter->ifc_data.guid ) - { - VNIC_TRACE( VNIC_DBG_PNP, - ("Getting path for wrong IOC\n") ); - ib_status = IB_INVALID_GUID; - break; - } - p_ioc_path = (ib_pnp_ioc_path_rec_t*)p_pnp_rec; - - p_path_record = __path_record_add( p_adapter, &p_ioc_path->path ); - if ( p_path_record == NULL ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("Failed to add path record\n") ); - break; - } - - if( p_adapter->state == INIC_REGISTERED ) - { - if( p_adapter->num_paths > 0 ) - { - if( p_adapter->params.SecondaryPath != TRUE ) - { - VNIC_TRACE ( VNIC_DBG_WARN, - ("Allowed one path at a time\n") ); - break; - } - } - - if( p_adapter->num_paths > 1 ) - { - VNIC_TRACE ( VNIC_DBG_WARN, - ("Max Paths[%d] Connected already\n", p_adapter->num_paths) ); - break; - } - } - - ib_status = adapter_netpath_update_and_connect( - p_adapter, p_path_record ); - if( ib_status != IB_SUCCESS ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("IOC[%d] adapter_netpath_update_and_connect return %s\n", - p_adapter->ioc_num, - p_adapter->ifc.get_err_str( ib_status )) ); - break; - } - - InterlockedCompareExchange( (volatile LONG *)&p_adapter->state, - INIC_REGISTERED, INIC_UNINITIALIZED ); -#if ( LBFO_ENABLED ) - - if( p_adapter->failover.fo_state == _ADAPTER_NOT_BUNDLED ) - { - /* we don't look for zero id, since it meant to be primary by default */ - if( p_adapter->failover.bundle_id != 0 && - ( p_primary_adapter = __adapter_find_on_failover_list( _ADAPTER_PRIMARY, - p_adapter->failover.bundle_id ) ) != NULL ) - { - /* found matching primary */ - __adapter_set_failover_secondary( - p_adapter, p_primary_adapter->h_handle ); - } - else - { - /* bundle_id '0' , all go to primary */ - __adapter_set_failover_primary( p_adapter, FALSE ); - } - } - -#endif // LBFO_ENABLED - - break; - - case IB_PNP_IOC_PATH_REMOVE: - p_ioc_path = (ib_pnp_ioc_path_rec_t*)p_pnp_rec; - - VNIC_TRACE( VNIC_DBG_PNP, - ("IB_PNP_IOC_PATH_REMOVE (slid:%d dlid:%d) for %s.\n", - ntoh16( p_ioc_path->path.slid ), - ntoh16( p_ioc_path->path.dlid ), - p_adapter->ioc_info.profile.id_string)); - - p_path_record = __path_record_remove( p_adapter, &p_ioc_path->path ); - - if ( p_path_record != NULL ) - { - int fail_over = 0; - - if( p_adapter->p_currentPath->p_path_rec != &p_path_record->path_rec ) - { - VNIC_TRACE( VNIC_DBG_INFO, - ("IOC[%d] Standby Path lost\n", p_adapter->ioc_num )); - - if( p_adapter->p_currentPath != &p_adapter->primaryPath ) - { - _adapter_netpath_free( p_adapter, &p_adapter->primaryPath ); - } - else - { - _adapter_netpath_free( p_adapter, &p_adapter->secondaryPath ); - } - - cl_free( p_path_record ); - break; - } - - VNIC_TRACE( VNIC_DBG_ERROR, - ("IOC[%d]Current Path lost\n", p_adapter->ioc_num )); - - p_netpath = p_adapter->p_currentPath; - netpath_stopXmit( p_netpath ); - viport_timerStop( p_netpath->pViport ); - - if( !p_adapter->params.SecondaryPath ) - { - vnic_path_record_t* p_record; - - netpath_linkDown( p_netpath ); - _adapter_netpath_free(p_adapter, p_netpath ); - - p_record = __path_record_get( p_adapter ); - if( p_record ) - { - ib_status = adapter_netpath_update_and_connect( p_adapter, p_record ); - } - - cl_free( p_path_record ); - break; - } - - if( p_netpath == &p_adapter->primaryPath ) - { - if( netpath_is_connected( &p_adapter->secondaryPath ) ) - { - netpath_stopXmit( &p_adapter->secondaryPath ); - p_adapter->p_currentPath = &p_adapter->secondaryPath; - fail_over = 1; - VNIC_TRACE( VNIC_DBG_ERROR, - ("IOC[%d]Switch to Secondary Path\n", p_adapter->ioc_num )); - } - } - else - { - if( netpath_is_connected( &p_adapter->primaryPath ) ) - { - netpath_stopXmit( &p_adapter->primaryPath ); - p_adapter->p_currentPath = &p_adapter->primaryPath; - fail_over = 1; - VNIC_TRACE( VNIC_DBG_ERROR, - ("IOC[%d]Switch to Primary Path\n", p_adapter->ioc_num )); - } - } - if( fail_over ) - { - viport_setLink( p_adapter->p_currentPath->pViport, - INIC_FLAG_ENABLE_NIC| INIC_FLAG_SET_MTU, - (uint16_t)p_adapter->params.MinMtu, FALSE ); - } - - _adapter_netpath_free(p_adapter, p_netpath ); - cl_free( p_path_record ); - } - - break; - - default: - VNIC_TRACE( VNIC_DBG_PNP, - (" Received unhandled PnP event %#x\n", p_pnp_rec->pnp_event ) ); - break; - } - - VNIC_EXIT( VNIC_DBG_PNP ); - return ib_status; -} - - -NDIS_STATUS -vnic_get_adapter_interface( - IN NDIS_HANDLE h_handle, - IN vnic_adapter_t *p_adapter) -{ - NTSTATUS status; - ib_al_ifc_data_t data; - IO_STACK_LOCATION io_stack; - - VNIC_ENTER( VNIC_DBG_ADAPTER ); - - NdisMGetDeviceProperty( h_handle, &p_adapter->p_pdo, NULL, NULL, NULL, NULL ); - - data.size = sizeof(ioc_ifc_data_t); - data.type = &GUID_IOC_INTERFACE_DATA; - data.version = IOC_INTERFACE_DATA_VERSION; - data.p_data = &p_adapter->ifc_data; - - io_stack.MinorFunction = IRP_MN_QUERY_INTERFACE; - io_stack.Parameters.QueryInterface.Version = AL_INTERFACE_VERSION; - io_stack.Parameters.QueryInterface.Size = sizeof(ib_al_ifc_t); - io_stack.Parameters.QueryInterface.Interface = (INTERFACE*)&p_adapter->ifc; - io_stack.Parameters.QueryInterface.InterfaceSpecificData = &data; - io_stack.Parameters.QueryInterface.InterfaceType = &GUID_IB_AL_INTERFACE; - - status = cl_fwd_query_ifc( p_adapter->p_pdo, &io_stack ); - - if( !NT_SUCCESS( status ) ) - { - VNIC_TRACE_EXIT( VNIC_DBG_ERROR, - ("Query interface for VNIC interface returned %08x.\n", status) ); - return status; - } - /* - * Dereference the interface now so that the bus driver doesn't fail a - * query remove IRP. We will always get unloaded before the bus driver - * since we're a child device. - */ - p_adapter->ifc.wdm.InterfaceDereference( - p_adapter->ifc.wdm.Context ); - - VNIC_EXIT( VNIC_DBG_ADAPTER ); - - return NDIS_STATUS_SUCCESS; -} - - -static void -__adapter_cleanup( - IN vnic_adapter_t *p_adapter ) -{ - __pending_queue_cleanup( p_adapter ); - - __path_records_cleanup( p_adapter ); - - _adapter_netpath_free( p_adapter, &p_adapter->primaryPath ); - _adapter_netpath_free( p_adapter, &p_adapter->secondaryPath ); - - VNIC_EXIT( VNIC_DBG_ADAPTER ); -} - -void -__vnic_pnp_dereg_cb( - IN void* context ) -{ - vnic_adapter_t* p_adapter; - ib_api_status_t ib_status; - ib_pnp_req_t pnp_req; - - NDIS_STATUS ndis_status = NDIS_STATUS_SUCCESS; - - VNIC_ENTER( VNIC_DBG_INIT ); - - p_adapter = (vnic_adapter_t*)context; - - CL_ASSERT( !p_adapter->h_pnp ); - - /* Destroy port instances if still exist. */ - __adapter_cleanup( p_adapter ); - - if( p_adapter->pnp_state != IB_PNP_IOC_REMOVE ) - { - p_adapter->pnp_state = IB_PNP_IOC_ADD; - /* Register for IOC events */ - pnp_req.pfn_pnp_cb = __vnic_pnp_cb; - pnp_req.pnp_class = IB_PNP_IOC | IB_PNP_FLAG_REG_SYNC; - pnp_req.pnp_context = (const void *)p_adapter; - - ib_status = p_adapter->ifc.reg_pnp( p_adapter->h_al, &pnp_req, &p_adapter->h_pnp ); - if( ib_status != IB_SUCCESS ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("pnp_reg returned %s\n", - p_adapter->ifc.get_err_str( ib_status )) ); - ndis_status = NDIS_STATUS_HARD_ERRORS; - } - } - else - { - ndis_status = NDIS_STATUS_HARD_ERRORS; - } - - if( p_adapter->reset ) - { - p_adapter->reset = FALSE; - NdisMResetComplete( - p_adapter->h_handle, ndis_status, TRUE ); - } - - VNIC_EXIT( VNIC_DBG_INIT ); -} - - -ib_api_status_t -adapter_reset( - IN vnic_adapter_t* const p_adapter ) -{ - - ib_api_status_t status; - ib_pnp_handle_t h_pnp; - - VNIC_ENTER( VNIC_DBG_INIT ); - - if( p_adapter->reset ) - return IB_INVALID_STATE; - - p_adapter->reset = TRUE; - p_adapter->hung = 0; - -#if ( LBFO_ENABLED ) - __adapter_remove_from_failover_list( p_adapter ); - -#endif // LBFO_ENABLED - - if( p_adapter->h_pnp ) - { - h_pnp = p_adapter->h_pnp; - p_adapter->h_pnp = NULL; - status = p_adapter->ifc.dereg_pnp( h_pnp, __vnic_pnp_dereg_cb ); - if( status == IB_SUCCESS ) - status = IB_NOT_DONE; - } - else - { - status = IB_NOT_FOUND; - } - - VNIC_EXIT( VNIC_DBG_INIT ); - return status; -} - -static -NDIS_STATUS -_adapter_set_sg_size( - IN NDIS_HANDLE h_handle, - IN ULONG mtu_size ) -{ - NDIS_STATUS status; - ULONG buf_size; - - VNIC_ENTER( VNIC_DBG_INIT ); - - buf_size = mtu_size + ETH_VLAN_HLEN; - - status = NdisMInitializeScatterGatherDma( h_handle, TRUE, buf_size ); - - if ( status != NDIS_STATUS_SUCCESS ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("Init ScatterGatherDma failed status %#x\n", status ) ); - } - - VNIC_EXIT( VNIC_DBG_INIT ); - return status; -} - -static ib_api_status_t -_adapter_close_ca( - IN vnic_adapter_t* const p_adapter ) -{ - ib_api_status_t ib_status = IB_SUCCESS; - ib_ca_handle_t h_ca; - - VNIC_ENTER( VNIC_DBG_INIT ); - - if( !p_adapter ) - return ib_status; - - VNIC_TRACE(VNIC_DBG_INIT, - ("IOC[%d] Close CA\n", p_adapter->ioc_num )); - - if( p_adapter->ca.region.h_mr ) - { - ib_status = p_adapter->ifc.dereg_mr( p_adapter->ca.region.h_mr ); - if( ib_status != IB_SUCCESS ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("Failed to dereg MR\n")); - } - p_adapter->ca.region.h_mr = NULL; - } - - if( p_adapter->ca.hPd ) - { - ib_status = p_adapter->ifc.dealloc_pd( p_adapter->ca.hPd, NULL ); - if( ib_status != IB_SUCCESS ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("Failed to dealloc PD\n")); - } - p_adapter->ca.hPd = NULL; - } - - if( ( h_ca = InterlockedExchangePointer( (void *)&p_adapter->h_ca, NULL ) ) != NULL ) - { - - ib_status = p_adapter->ifc.close_ca( h_ca, NULL ); - if( ib_status != IB_SUCCESS ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("Failed to close CA\n")); - } - } - - VNIC_EXIT( VNIC_DBG_INIT ); - return ib_status; -} - -static -ib_api_status_t -_adapter_netpath_update( - IN vnic_adapter_t* const p_adapter, - IN viport_t* const p_viport, - IN vnic_path_record_t* p_path ) -{ - - Netpath_t *p_netpath_init; - - VNIC_ENTER( VNIC_DBG_PNP ); - - NdisAcquireSpinLock( &p_adapter->lock ); - /* set primary first */ - if( !netpath_is_valid( p_adapter->p_currentPath ) ) - { - p_netpath_init = &p_adapter->primaryPath; - p_adapter->p_currentPath = p_netpath_init; - } - - else - { - if( p_adapter->p_currentPath != &p_adapter->primaryPath ) - { - p_netpath_init = &p_adapter->primaryPath; - } - else - { - p_netpath_init = &p_adapter->secondaryPath; - } - } - - /* shouldn't really happened ?? */ - if( netpath_is_connected( p_netpath_init ) ) - { - VNIC_TRACE( VNIC_DBG_WARN, - ("No available Netpath found for update\n")); - - NdisReleaseSpinLock( &p_adapter->lock ); - return IB_NO_MATCH; - } - - p_netpath_init->p_path_rec = &p_path->path_rec; - - /* netpath initialization */ - - p_netpath_init->p_adapter = p_adapter; - p_netpath_init->pViport = p_viport; - p_netpath_init->carrier = FALSE; - - /* viport initialization */ - p_viport->p_netpath = p_netpath_init; - - p_viport->portGuid = p_netpath_init->p_path_rec->sgid.unicast.interface_id; - p_viport->port_config.dataConfig.ibConfig.pathInfo = *p_netpath_init->p_path_rec; - p_viport->port_config.controlConfig.ibConfig.pathInfo = *p_netpath_init->p_path_rec; - - /* set our instance id per IOC */ - p_viport->port_config.controlConfig.ibConfig.connData.inicInstance = (uint8_t)p_netpath_init->instance; - p_viport->port_config.dataConfig.ibConfig.connData.inicInstance = (uint8_t)p_netpath_init->instance; - /* save for later use */ - p_viport->port_config.controlConfig.inicInstance = (uint8_t)p_netpath_init->instance; - - p_viport->iocGuid = p_adapter->ioc_info.profile.ioc_guid; - p_viport->port_config.controlConfig.ibConfig.sid = p_adapter->svc_entries[0].id; - p_viport->port_config.dataConfig.ibConfig.sid = p_adapter->svc_entries[1].id; - - VNIC_TRACE( VNIC_DBG_INFO, - ("IOC[%d] instance %d [%s] is using SLID=%d DLID=%d Target:%s\n", - p_viport->ioc_num, - p_netpath_init->instance, - netpath_to_string( p_netpath_init ), - cl_ntoh16( p_path->path_rec.slid ), - cl_ntoh16( p_path->path_rec.dlid), - p_adapter->ioc_info.profile.id_string) ); - - NdisReleaseSpinLock( &p_adapter->lock ); - - VNIC_EXIT( VNIC_DBG_PNP ); - return IB_SUCCESS; -} - -static -ib_api_status_t -adapter_netpath_update_and_connect( - IN vnic_adapter_t* const p_adapter, - IN vnic_path_record_t* p_path ) -{ - ib_api_status_t ib_status; - viport_t* p_viport; - - ib_status = adapter_viport_allocate( p_adapter, &p_viport ); - if( ib_status != IB_SUCCESS ) - { - VNIC_TRACE ( VNIC_DBG_ERROR, - ("IOC[%] Viport allocate Failed status %s\n", - p_adapter->ioc_num, p_adapter->ifc.get_err_str( ib_status )) ); - goto err; - } - - ib_status = _adapter_open_ca( p_adapter ); - if( ib_status != IB_SUCCESS ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("IOC[%d]Open CA failed %s\n", p_adapter->ioc_num, - p_adapter->ifc.get_err_str( ib_status )) ); - goto err; - } - - ib_status = _adapter_netpath_update( p_adapter, p_viport, p_path ); - if( ib_status != IB_SUCCESS ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("IOC[%d]Update New Path failed %s\n", p_adapter->ioc_num, - p_adapter->ifc.get_err_str( ib_status )) ); - goto err; - } - - ib_status = viport_control_connect( p_viport ); - if( ib_status != IB_SUCCESS ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("IOC[%d]Control QP connect return %s\n", p_adapter->ioc_num, - p_adapter->ifc.get_err_str( ib_status )) ); - goto err; - } - - /* should call this only once */ - if( p_adapter->state == INIC_UNINITIALIZED ) - { - if( _adapter_set_sg_size( p_adapter->h_handle, - p_adapter->params.MinMtu ) != NDIS_STATUS_SUCCESS ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("IOC[%d]ScatterGather Init using MTU size %d failed\n", p_adapter->ioc_num, - p_adapter->params.MinMtu ) ); - goto err; - } - } - - ib_status = viport_data_connect( p_viport ); - if( ib_status != IB_SUCCESS ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("IOC[%d]Data QP connect return %s\n", p_adapter->ioc_num, - p_adapter->ifc.get_err_str( ib_status )) ); - goto err; - } - - VNIC_TRACE( VNIC_DBG_INFO, - ("IOC[%d] instance %d %s is CONNECTED\n", - p_viport->ioc_num, - p_viport->p_netpath->instance, - netpath_to_string( p_viport->p_netpath ) )); - - if( p_viport->state == VIPORT_CONNECTED ) - { - p_adapter->num_paths++; - } - - if( p_adapter->num_paths > 1 && - p_viport->p_netpath != p_adapter->p_currentPath ) - { - if ( !netpath_setUnicast( p_viport->p_netpath, - p_adapter->p_currentPath->pViport->hwMacAddress ) ) - { - ib_status = IB_ERROR; - goto err; - } - } - - return ib_status; - -err: - VNIC_TRACE( VNIC_DBG_ERROR, - ("IOC[%d] allocate return %#x (%s)\n", p_adapter->ioc_num, - ib_status, p_adapter->ifc.get_err_str( ib_status )) ); - - if( p_viport != NULL && - p_viport->p_netpath != NULL ) - { - netpath_free( p_viport->p_netpath ); - } - return ib_status; -} - -#if ( LBFO_ENABLED ) - -static void -__adapter_add_to_failover_list( - IN vnic_adapter_t* const p_adapter, - IN lbfo_state_t state ) -{ - - CL_ASSERT( p_adapter ); - CL_ASSERT( state == _ADAPTER_PRIMARY || state == _ADAPTER_SECONDARY ); - - p_adapter->failover.fo_state = state; - - if( state == _ADAPTER_PRIMARY ) - { - p_adapter->failover.primary_handle = p_adapter; - cl_qlist_insert_tail( &g_vnic.primary_list, &p_adapter->list_item ); - } - else - { - cl_qlist_insert_tail( &g_vnic.secondary_list, &p_adapter->list_item ); - } -} - -static void -__adapter_remove_from_failover_list( - IN vnic_adapter_t* const p_adapter ) -{ - lbfo_state_t lbfo_state; - vnic_adapter_t *p_adapter_to_promote; - uint32_t bundle_id; - - CL_ASSERT( p_adapter ); - - lbfo_state = p_adapter->failover.fo_state; - p_adapter->failover.fo_state = _ADAPTER_NOT_BUNDLED; - bundle_id = p_adapter->failover.bundle_id; - - if( lbfo_state == _ADAPTER_PRIMARY ) - { - cl_qlist_remove_item( &g_vnic.primary_list, &p_adapter->list_item ); - - /* search for secondary adapter with same id && (id != 0 ) */ - if( bundle_id != 0 ) - { - p_adapter_to_promote = - __adapter_find_on_failover_list( _ADAPTER_SECONDARY, bundle_id ); - - if( p_adapter_to_promote && - p_adapter_to_promote->pnp_state != IB_PNP_IOC_REMOVE && - p_adapter_to_promote->state == INIC_REGISTERED && - p_adapter_to_promote->reset == FALSE ) - { - /* a small recursion */ - __adapter_set_failover_primary( p_adapter_to_promote, TRUE ); - } - } - } - else if( lbfo_state == _ADAPTER_SECONDARY ) - { - cl_qlist_remove_item( &g_vnic.secondary_list, &p_adapter->list_item ); - VNIC_TRACE( VNIC_DBG_INFO, - ("IOC[%d] LBFO bundle %d Secondary Adapter Removed\n", - p_adapter->ioc_num, p_adapter->failover.bundle_id )); - } - else if( lbfo_state == _ADAPTER_NOT_BUNDLED ) - { - VNIC_TRACE( VNIC_DBG_INFO, - ("IOC[%d] Adapter not bundled\n", p_adapter->ioc_num )); - } - - return; -} - - -static vnic_adapter_t* -__adapter_find_on_failover_list( - IN lbfo_state_t list_flag, - IN uint32_t bundle_id ) -{ - vnic_adapter_t *p_adapter = NULL; - cl_list_item_t *p_item; - cl_qlist_t *p_qlist = ( list_flag == _ADAPTER_PRIMARY ) ? - &g_vnic.primary_list : &g_vnic.secondary_list; - - p_item = cl_qlist_head( p_qlist ); - - while( p_item != cl_qlist_end( p_qlist ) ) - { - p_adapter = PARENT_STRUCT( p_item, vnic_adapter_t, list_item ); - - if( p_adapter && - p_adapter->failover.bundle_id == bundle_id ) - { - return p_adapter; - } - - p_item = cl_qlist_next( p_item ); - } - return NULL; -} - -static NDIS_STATUS -__adapter_set_failover_primary( - IN vnic_adapter_t* const p_adapter, - IN BOOLEAN promote_secondary ) -{ - NDIS_STATUS status = NDIS_STATUS_SUCCESS; - - CL_ASSERT( p_adapter ); - - if( promote_secondary ) - { - if( p_adapter->failover.fo_state != _ADAPTER_SECONDARY ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("LBFO Can't promote NON_SECONDARY\n")); - return NDIS_STATUS_NOT_ACCEPTED; - } - __adapter_remove_from_failover_list( p_adapter ); - status = NdisMPromoteMiniport( p_adapter->h_handle ); - } - - if( status == NDIS_STATUS_SUCCESS ) - { - p_adapter->failover.p_adapter = p_adapter; - p_adapter->failover.fo_state = _ADAPTER_PRIMARY; - p_adapter->failover.primary_handle = p_adapter->h_handle; - __adapter_add_to_failover_list( p_adapter, _ADAPTER_PRIMARY ); - - VNIC_TRACE( VNIC_DBG_INFO, - ("IOC[%d] Set LBFO bundle %d Primary Adapter\n", - p_adapter->ioc_num, p_adapter->failover.bundle_id )); - } - else - VNIC_TRACE( VNIC_DBG_ERROR, - ("LBFO Set to Primary Failed\n")); - - return status; -} - -static NDIS_STATUS -__adapter_set_failover_secondary( - IN vnic_adapter_t* const p_adapter, - IN NDIS_HANDLE primary_handle ) -{ - NDIS_STATUS status; - - CL_ASSERT( p_adapter ); - - status = NdisMSetMiniportSecondary( p_adapter->h_handle, primary_handle ); - - if ( status == NDIS_STATUS_SUCCESS ) - { - p_adapter->failover.fo_state = _ADAPTER_SECONDARY; - p_adapter->failover.primary_handle = primary_handle; - __adapter_add_to_failover_list( p_adapter, _ADAPTER_SECONDARY ); - - VNIC_TRACE( VNIC_DBG_INFO, - ("IOC[%d] Set LBFO bundle %d Secondary Adapter\n", - p_adapter->ioc_num, p_adapter->failover.bundle_id )); - } - - return status; -} - -#endif //LBFO_ENABLED diff --git a/trunk/ulp/qlc_vnic/kernel/vnic_adapter.h b/trunk/ulp/qlc_vnic/kernel/vnic_adapter.h deleted file mode 100644 index cd143b52..00000000 --- a/trunk/ulp/qlc_vnic/kernel/vnic_adapter.h +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright (c) 2007 QLogic Corporation. All rights reserved. - * - * This software is available to you under the OpenIB.org BSD license - * below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * $Id$ - */ - -#if !defined _VNIC_ADAPTER_H_ -#define _VNIC_ADAPTER_H_ - -#include -#include -#include -#include -#include "vnic_ib.h" -#include "vnic_controlpkt.h" -#include "vnic_config.h" -#include "vnic_control.h" -#include "vnic_data.h" -#include "vnic_viport.h" -#include - -typedef struct _pending_oid -{ - NDIS_OID oid; - PVOID p_buf; - ULONG buf_len; - PULONG p_bytes_used; - PULONG p_bytes_needed; - -} pending_oid_t; - -typedef struct _ipv4_address_item -{ - union _net_address_item_address - { - ULONG as_ulong; - UCHAR as_bytes[4]; - } address; - -} ipv4_address_item_t; - -typedef struct _lbfo_failover { - struct _vnic_adapter *p_adapter; - NDIS_HANDLE primary_handle; - uint32_t bundle_id; - lbfo_state_t fo_state; -} lbfo_failover_t; - -typedef struct _vnic_params { - uint32_t MaxAddressEntries; - uint32_t MinAddressEntries; - uint32_t MinMtu; - uint32_t MaxMtu; - uint32_t HostRecvPoolEntries; - uint32_t MinHostPoolSz; - uint32_t MinEiocPoolSz; - uint32_t MaxEiocPoolSz; - uint32_t MinHostKickTimeout; - uint32_t MaxHostKickTimeout; - uint32_t MinHostKickEntries; - uint32_t MaxHostKickEntries; - uint32_t MinHostKickBytes; - uint32_t MaxHostKickBytes; - uint32_t MinHostUpdateSz; - uint32_t MaxHostUpdateSz; - uint32_t MinEiocUpdateSz; - uint32_t MaxEiocUpdateSz; - uint32_t NotifyBundleSz; - uint32_t ViportStatsInterval; - uint32_t ViportHbInterval; - uint32_t ViportHbTimeout; - uint32_t ControlRspTimeout; - uint32_t ControlReqRetryCount; - uint32_t RetryCount; - uint32_t MinRnrTimer; - uint32_t MaxViportsPerNetpath; - uint32_t DefaultViportsPerNetpath; - uint32_t DefaultPkey; - uint32_t DefaultNoPathTimeout; - uint32_t DefaultPrimaryConnectTimeout; - uint32_t DefaultPrimaryReconnectTimeout; - uint32_t DefaultPrimarySwitchTimeout; - uint32_t DefaultPreferPrimary; - uint32_t UseRxCsum; - uint32_t UseTxCsum; - uint32_t VlanInfo; - uint32_t SecondaryPath; - uint32_t bundle_id; - mac_addr_t conf_mac; -} vnic_params_t; - - -typedef struct _vnic_adapter { - cl_list_item_t list_item; - NDIS_HANDLE h_handle; - DEVICE_OBJECT *p_pdo; - NDIS_SPIN_LOCK lock; - ib_al_ifc_t ifc; - ioc_ifc_data_t ifc_data; - ib_ioc_info_t ioc_info; - LIST_ENTRY send_pending_list; - LIST_ENTRY cancel_send_list; - NDIS_SPIN_LOCK pending_list_lock; - NDIS_SPIN_LOCK cancel_list_lock; - NDIS_SPIN_LOCK path_records_lock; - cl_qlist_t path_records_list; - ib_al_handle_t h_al; - ib_ca_handle_t h_ca; - ib_pnp_handle_t h_pnp; - ib_pnp_event_t pnp_state; - IbCa_t ca; - InicState_t state; - struct Netpath primaryPath; - struct Netpath secondaryPath; - struct Netpath *p_currentPath; - vnic_params_t params; - uint32_t num_paths; - int macSet; - int mc_count; - mac_addr_t mcast_array[MAX_MCAST]; - LONG xmitStarted; - LONG carrier; - uint32_t ioc_num; - uint32_t link_speed; - uint32_t packet_filter; - uint32_t vlan_info; - uint32_t hung; - BOOLEAN reset; - BOOLEAN pending_set; - BOOLEAN pending_query; - pending_oid_t query_oid; - pending_oid_t set_oid; - ib_svc_entry_t svc_entries[2]; - -#if ( LBFO_ENABLED ) - lbfo_failover_t failover; -#endif -#ifdef VNIC_STATISTIC - struct { - uint64_t startTime; - uint64_t connTime; - uint64_t disconnRef; /* Intermediate time */ - uint64_t disconnTime; - uint32_t disconnNum; - uint64_t xmitTime; - uint32_t xmitNum; - uint32_t xmitFail; - uint64_t recvTime; - uint32_t recvNum; - uint64_t xmitRef; /* Intermediate time */ - uint64_t xmitOffTime; - uint32_t xmitOffNum; - uint64_t carrierRef; /* Intermediate time */ - uint64_t carrierOffTime; - uint32_t carrierOffNum; - } statistics; -#endif /* VNIC_STATISTIC */ - -} vnic_adapter_t; - -ib_api_status_t -vnic_create_adapter( - IN NDIS_HANDLE h_handle, - IN NDIS_HANDLE wrapper_config_context, - OUT vnic_adapter_t** const pp_adapter); - -void -vnic_destroy_adapter( - IN vnic_adapter_t* p_adapter); - -ib_api_status_t -vnic_construct_adapter( - IN vnic_adapter_t *p_adapter); - -NDIS_STATUS -adapter_set_mcast( - IN vnic_adapter_t* const p_adapter, - IN mac_addr_t* const p_mac_array, - IN const uint8_t mc_count ); - -ib_api_status_t -adapter_viport_allocate( - IN vnic_adapter_t* const p_adapter, - IN OUT viport_t** const pp_viport ); - -void -vnic_resume_set_oids( - IN vnic_adapter_t* const p_adapter ); - -void -vnic_resume_oids( - IN vnic_adapter_t* const p_adapter ); - -ib_api_status_t -__vnic_pnp_cb( - IN ib_pnp_rec_t *p_pnp_rec ); - -ib_api_status_t -ibregion_physInit( - IN struct _vnic_adapter* p_adapter, - OUT IbRegion_t *pRegion, - IN ib_pd_handle_t hPd, - IN uint64_t *p_vaddr, - IN uint64_t len ); - -void -__vnic_pnp_dereg_cb( - IN void* context ); - -ib_api_status_t -adapter_reset( - IN vnic_adapter_t* const p_adapter ); -void -__pending_queue_cleanup( - IN vnic_adapter_t *p_adapter ); - -#endif /* !defined _VNIC_ADAPTER_H_ */ diff --git a/trunk/ulp/qlc_vnic/kernel/vnic_config.h b/trunk/ulp/qlc_vnic/kernel/vnic_config.h deleted file mode 100644 index 9568b08f..00000000 --- a/trunk/ulp/qlc_vnic/kernel/vnic_config.h +++ /dev/null @@ -1,301 +0,0 @@ -/* - * Copyright (c) 2007 QLogic Corporation. All rights reserved. - * - * This software is available to you under the OpenIB.org BSD license - * below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * $Id$ - */ -#ifndef _VNIC_CONFIG_H_ -#define _VNIC_CONFIG_H_ - -#include "vnic_util.h" -/* These are hard, compile time limits. - * Lower runtime overrides may be in effect - */ -#define INIC_CLASS_SUBCLASS 0x2000066A -#define INIC_PROTOCOL 0 -#define INIC_PROT_VERSION 1 - -#define INIC_MAJORVERSION 1 -#define INIC_MINORVERSION 1 - -#define LIMIT_OUTSTANDING_SENDS 0 - -#define MAX_ADDRESS_ENTRIES 64 /* max entries to negotiate with remote */ -#define MIN_ADDRESS_ENTRIES 16 /* min entries remote can return to us that we agree with */ -#define MAX_ADDR_ARRAY 32 /* address array we can handle. for now */ -#define MIN_MTU 1500 /* Minimum Negotiated payload size */ -#define MAX_MTU 9500 /* max Jumbo frame payload size */ -#define ETH_VLAN_HLEN 18 /* ethernet header with VLAN tag */ - -#define HOST_RECV_POOL_ENTRIES 512 /* TBD: Abritrary */ -#define MIN_HOST_POOL_SZ 256 /* TBD: Abritrary */ -#define MIN_EIOC_POOL_SZ 256 /* TBD: Abritrary */ -#define MAX_EIOC_POOL_SZ 512 /* TBD: Abritrary */ - -#define MIN_HOST_KICK_TIMEOUT 100 /* TBD: Arbitrary */ -#define MAX_HOST_KICK_TIMEOUT 200 /* In uSec */ - -#define MIN_HOST_KICK_ENTRIES 1 /* TBD: Arbitrary */ -#define MAX_HOST_KICK_ENTRIES 128 /* TBD: Arbitrary */ - -#define MIN_HOST_KICK_BYTES 0 -#define MAX_HOST_KICK_BYTES 5000 - -#define MIN_HOST_UPDATE_SZ 8 /* TBD: Arbitrary */ -#define MAX_HOST_UPDATE_SZ 32 /* TBD: Arbitrary */ -#define MIN_EIOC_UPDATE_SZ 8 /* TBD: Arbitrary */ -#define MAX_EIOC_UPDATE_SZ 32 /* TBD: Arbitrary */ - -#define NOTIFY_BUNDLE_SZ 32 - -#define MAX_PARAM_VALUE 0x40000000 - -#define DEFAULT_VIPORTS_PER_NETPATH 1 -#define MAX_VIPORTS_PER_NETPATH 1 - -#define INIC_USE_RX_CSUM TRUE -#define INIC_USE_TX_CSUM TRUE -#define DEFAULT_NO_PATH_TIMEOUT 10000 /* TBD: Arbitrary */ -#define DEFAULT_PRI_CON_TIMEOUT 10000 /* TBD: Arbitrary */ -#define DEFAULT_PRI_RECON_TIMEOUT 10000 /* TBD: Arbitrary */ -#define DEFAULT_PRI_SWITCH_TIMEOUT 10000 /* TBD: Arbitrary */ -#define DEFAULT_PREFER_PRIMARY TRUE - -/* timeouts: !! all data defined in milliseconds, - some later will be converted to microseconds */ -#define VIPORT_STATS_INTERVAL 5000 /* 5 sec */ -#define VIPORT_HEARTBEAT_INTERVAL 2000 /* 2 seconds */ -#define VIPORT_HEARTBEAT_TIMEOUT 60000 /* 60 sec */ -#define CONTROL_RSP_TIMEOUT 2000 /* 2 sec */ - -#define _100NS_IN_1MS (10000) -inline uint64_t -get_time_stamp_ms( void ) -{ - return( (KeQueryInterruptTime() / _100NS_IN_1MS ) ); -} - -/* InfiniBand Connection Parameters */ -#define CONTROL_REQ_RETRY_COUNT 4 -#define RETRY_COUNT 3 -#define MIN_RNR_TIMER 22 /* 20 ms */ -#define DEFAULT_PKEY 0 /* Pkey table index */ - -/* phys memory size to register with HCA*/ -#define MEM_REG_SIZE 0xFFFFFFFFFFFFFFFF - -/* link speed in 100 bits/sec units */ -#define LINK_SPEED_1MBIT_x100BPS 10000 -#define LINK_SPEED_1GBIT_x100BPS 10000000 -#define LINK_SPEED_10GBIT_x100BPS 100000000 - /* if VEx does not report it's link speed, so set it 1Gb/s so far */ -#define DEFAULT_LINK_SPEED_x100BPS LINK_SPEED_1GBIT_x100BPS - -#define DEFAULT_PARAM(x,y) if(x == MAXU32) { \ - x = y; } -#define POWER_OF_2(x) if (!IsPowerOf2(x)) { \ - VNIC_TRACE( VNIC_DBG_WARN, (" %s (%d) must be a power of 2\n",#x,x) ); \ - x = SetMinPowerOf2(x); \ - } -#define LESS_THAN(lo, hi) if (lo >= hi) { \ - VNIC_TRACE( VNIC_DBG_ERROR, (" %s (%d) must be less than %s (%d)\n",#lo,lo,#hi,hi) ); \ - lo = hi >> 1; \ - } -#define LESS_THAN_OR_EQUAL(lo, hi) if (lo > hi) { \ - VNIC_TRACE( VNIC_DBG_WARN, (" %s (%d) cannot be greater than %s (%d)\n",#lo,lo,#hi,hi) ); \ - lo = hi; \ - } -#define RANGE_CHECK(x, min, max) if ((x < min) || (x > max)) { \ - VNIC_TRACE( VNIC_DBG_WARN, (" %s (%d) must be between %d and %d\n",#x,x,min,max) ); \ - if (x < min) \ - x = min; \ - else \ - x = max; \ - } -#define ZERO_RANGE_CHECK(x, min, max) if (x > max) { \ - VNIC_TRACE( VNIC_DBG_WARN, (" %s (%d) must be between %d and %d\n",#x,x,min,max) ); \ - x = max; \ - } - -#define BOOLEAN_RANGE(x) ZERO_RANGE_CHECK(x, 0, 1) -#define U32_ZERO_RANGE(x) ZERO_RANGE_CHECK(x, 0, 0x7FFFFFFF) -#define U32_RANGE(x) RANGE_CHECK(x, 1, 0x7FFFFFFF) -#define U16_ZERO_RANGE(x) ZERO_RANGE_CHECK(x, 0, 0xFFFF) -#define U16_RANGE(x) RANGE_CHECK(x, 1, 0xFFFF) -#define U8_ZERO_RANGE(x) ZERO_RANGE_CHECK(x, 0, 0xFF) -#define U8_RANGE(x) RANGE_CHECK(x, 1, 0xFF) - -enum { - INDEX_RESERVED, - INDEX_MIN_HOST_POOL_SZ, - INDEX_HOST_RECV_POOL_ENTRIES, - INDEX_MIN_EIOC_POOL_SZ, - INDEX_MAX_EIOC_POOL_SZ, - INDEX_MIN_HOST_KICK_TIMEOUT, - INDEX_MAX_HOST_KICK_TIMEOUT, - INDEX_MIN_HOST_KICK_ENTRIES, - INDEX_MAX_HOST_KICK_ENTRIES, - INDEX_MIN_HOST_KICK_BYTES, - INDEX_MAX_HOST_KICK_BYTES, - INDEX_MIN_HOST_UPDATE_SZ, - INDEX_MAX_HOST_UPDATE_SZ, - INDEX_MIN_EIOC_UPDATE_SZ, - INDEX_MAX_EIOC_UPDATE_SZ, - INDEX_HEARTBEAT_TIMEOUT, - INDEX_LAST // keep it the last entry -}; - -typedef struct _g_registry_params { - PWSTR name; - uint32_t value; -}g_registry_params_t; - -#define ENTRY_INIT_VALUE MAXULONG -#define VNIC_REGISTRY_TBL_SIZE INDEX_LAST - -typedef struct { - uint64_t ioc_guid; - uint64_t portGuid; - uint64_t port; - uint64_t hca; - uint64_t instance; - char ioc_string[65]; - char ioc_guid_set; - char ioc_string_set; -} PathParam_t; - -typedef struct _vnic_globals { - NDIS_HANDLE ndis_handle; // ndis wrapper handle - NDIS_SPIN_LOCK lock; -#if ( LBFO_ENABLED ) - cl_qlist_t primary_list; - cl_qlist_t secondary_list; -#endif - uint32_t shutdown; - uint8_t host_name[IB_NODE_DESCRIPTION_SIZE]; - g_registry_params_t *p_params; -} vnic_globals_t; - -typedef struct IbConfig { - ib_path_rec_t pathInfo; - uint64_t sid; - Inic_ConnectionData_t connData; - uint32_t retryCount; - uint32_t rnrRetryCount; - uint8_t minRnrTimer; - uint32_t numSends; - uint32_t numRecvs; - uint32_t recvScatter; /* 1 */ - uint32_t sendGather; /* 1 or 2 */ - uint32_t overrides; -} IbConfig_t; - -typedef struct ControlConfig { - IbConfig_t ibConfig; - uint32_t numRecvs; - uint8_t inicInstance; - uint16_t maxAddressEntries; - uint16_t minAddressEntries; - uint32_t rspTimeout; - uint8_t reqRetryCount; - uint32_t overrides; -} ControlConfig_t; - -typedef struct DataConfig { - IbConfig_t ibConfig; - uint64_t pathId; - uint32_t numRecvs; - uint32_t hostRecvPoolEntries; - Inic_RecvPoolConfig_t hostMin; - Inic_RecvPoolConfig_t hostMax; - Inic_RecvPoolConfig_t eiocMin; - Inic_RecvPoolConfig_t eiocMax; - uint32_t notifyBundle; - uint32_t overrides; -} DataConfig_t; - -typedef struct ViportConfig { - struct _viport *pViport; - ControlConfig_t controlConfig; - DataConfig_t dataConfig; - uint32_t hca; - uint32_t port; - uint32_t statsInterval; - uint32_t hbInterval; /* heartbeat interval */ - uint32_t hbTimeout; /* heartbeat timeout */ - uint64_t portGuid; - uint64_t guid; - size_t instance; - char ioc_string[65]; - -#define HB_INTERVAL_OVERRIDE 0x1 -#define GUID_OVERRIDE 0x2 -#define STRING_OVERRIDE 0x4 -#define HCA_OVERRIDE 0x8 -#define PORT_OVERRIDE 0x10 -#define PORTGUID_OVERRIDE 0x20 - uint32_t overrides; -} ViportConfig_t; - -/* - * primaryConnectTimeout - If the secondary connects first, how long do we - * give the primary? - * primaryReconnectTimeout - Same as above, but used when recovering when - * both paths fail - * primarySwitchTimeout - How long do we wait before switching to the - * primary when it comes back? - */ -#define IFNAMSIZ 65 -typedef struct InicConfig { - //struct Inic *pInic; - char name[IFNAMSIZ]; - uint32_t noPathTimeout; - uint32_t primaryConnectTimeout; - uint32_t primaryReconnectTimeout; - uint32_t primarySwitchTimeout; - int preferPrimary; - BOOLEAN useRxCsum; - BOOLEAN useTxCsum; -#define USE_RX_CSUM_OVERRIDE 0x1 -#define USE_TX_CSUM_OVERRIDE 0x2 - uint32_t overrides; -} InicConfig_t; - -typedef enum { - INIC_UNINITIALIZED, - INIC_DEREGISTERING, - INIC_REGISTERED, -} InicState_t; - -typedef enum { - _ADAPTER_NOT_BUNDLED = 0, - _ADAPTER_PRIMARY, - _ADAPTER_SECONDARY -} lbfo_state_t; - -#endif /* _VNIC_CONFIG_H_ */ - diff --git a/trunk/ulp/qlc_vnic/kernel/vnic_control.c b/trunk/ulp/qlc_vnic/kernel/vnic_control.c deleted file mode 100644 index c8967a86..00000000 --- a/trunk/ulp/qlc_vnic/kernel/vnic_control.c +++ /dev/null @@ -1,2090 +0,0 @@ -/* - * Copyright (c) 2007 QLogic Corporation. All rights reserved. - * - * This software is available to you under the OpenIB.org BSD license - * below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * $Id$ - */ - -#include "vnic_adapter.h" - -static void -control_recv( Control_t *pControl, RecvIo_t *pRecvIo ); - -static void -control_recvComplete( - IN Io_t *pIo ); - -static ib_api_status_t -control_send( Control_t *pControl ); - -static void -control_sendComplete( Io_t *pIo ); -static void -control_timeout( void * context ); - -static void -control_timer( Control_t *pControl, int timeout ); - -static void -control_timerStop( Control_t *pControl ); - -static void -control_initHdr( Control_t *pControl, uint8_t cmd ); - -static RecvIo_t * -control_getRsp( Control_t *pControl ); - -static void -copyRecvPoolConfig( Inic_RecvPoolConfig_t *pSrc, - Inic_RecvPoolConfig_t *pDst ); - -static BOOLEAN -checkRecvPoolConfigValue( - IN void *pSrc, - IN void *pDst, - IN void *pMax, - IN void *pMin, - IN char *name ); - -static BOOLEAN checkRecvPoolConfig( - Inic_RecvPoolConfig_t *pSrc, - Inic_RecvPoolConfig_t *pDst, - Inic_RecvPoolConfig_t *pMax, - Inic_RecvPoolConfig_t *pMin); - -static void -__control_logControlPacket( - Inic_ControlPacket_t *pPkt ); - -void -control_construct( - IN Control_t *pControl, - IN viport_t *pViport ) -{ - VNIC_ENTER( VNIC_DBG_CTRL ); - - cl_memclr(pControl, sizeof(Control_t)); - - pControl->p_viport = pViport; - - pControl->reqOutstanding = FALSE; - pControl->seqNum = 0; - - pControl->pResponse = NULL; - pControl->pInfo = NULL; - - pControl->p_viport->addrs_query_done = TRUE; - - InitializeListHead(&pControl->failureList); - KeInitializeSpinLock(&pControl->ioLock); - - cl_timer_construct( &pControl->timer ); - - ibqp_construct( &pControl->qp, pViport ); - - VNIC_EXIT( VNIC_DBG_CTRL ); -} - - -ib_api_status_t -control_init( - IN Control_t *pControl, - IN viport_t *pViport, - IN ControlConfig_t *pConfig, - IN uint64_t guid ) -{ - ib_api_status_t ib_status; - ib_pd_handle_t hPd; - Inic_ControlPacket_t *pkt; - Io_t *pIo; - int sz; - unsigned int i; - - VNIC_ENTER( VNIC_DBG_CTRL ); - - pControl->p_conf = pConfig; - - hPd = pViport->p_adapter->ca.hPd; - - cl_timer_init( &pControl->timer, control_timeout, pControl ); - - ib_status = ibqp_init( - &pControl->qp, guid, &pConfig->ibConfig ); - if( ib_status != IB_SUCCESS ) - { - VNIC_TRACE_EXIT( VNIC_DBG_ERROR, ("ibqp_init returned %s\n", - pViport->p_adapter->ifc.get_err_str( ib_status )) ); - goto failure; - } - - sz = (sizeof(RecvIo_t) * pConfig->numRecvs ) + - (sizeof(Inic_ControlPacket_t) * (pConfig->numRecvs + 1)); - - pControl->pLocalStorage = cl_zalloc( sz ); - - if ( pControl->pLocalStorage == NULL ) - { - VNIC_TRACE_EXIT( VNIC_DBG_ERROR, - ("Failed allocating space for local storage\n" )); - - ibqp_cleanup(&pControl->qp); - ib_status = IB_INSUFFICIENT_MEMORY; - goto failure; - } - - pControl->pRecvIos = (RecvIo_t *)pControl->pLocalStorage; - - pkt = (Inic_ControlPacket_t *)(pControl->pLocalStorage + - sizeof(SendIo_t) * pConfig->numRecvs); - - sz = sizeof(Inic_ControlPacket_t) * (pConfig->numRecvs + 1); - - ib_status = ibregion_init( pViport, &pControl->region, hPd, - pkt, sz, IB_AC_LOCAL_WRITE ); - if ( ib_status != IB_SUCCESS ) - { - /* NOTE: I'm allowing recvs into the send buffer as well - * as the receive buffers. I'm doing this to combine them - * into a single region, and conserve a region. - */ - VNIC_TRACE_EXIT( VNIC_DBG_ERROR , - (" Failed setting up control space region\n" )); - - ibqp_cleanup( &pControl->qp ); - cl_free( pControl->pLocalStorage ); - pControl->pLocalStorage = NULL; - goto failure; - } - pIo = &pControl->sendIo.io; - pIo->pViport = pViport; - pIo->pRoutine = control_sendComplete; - - pIo->wrq.p_next = NULL; - pIo->wrq.wr_type = WR_SEND; - pIo->wrq.send_opt = IB_SEND_OPT_SIGNALED; - pIo->wrq.wr_id = (uint64_t)(pIo); - pIo->wrq.num_ds = 1; - pIo->wrq.ds_array = &pControl->sendIo.dsList; - pIo->wrq.ds_array[0].length = sizeof(Inic_ControlPacket_t); - pIo->wrq.ds_array[0].lkey = pControl->region.lkey; - pIo->wrq.ds_array[0].vaddr = (uint64_t)(pkt++); - - for (i = 0; i < pConfig->numRecvs; i++ ) - { - pIo = &pControl->pRecvIos[i].io; - pIo->pViport = pViport; - pIo->pRoutine = control_recvComplete; - - pIo->r_wrq.wr_id = (uint64_t)(pIo); - pIo->r_wrq.p_next = NULL; - pIo->r_wrq.num_ds = 1; - pIo->r_wrq.ds_array = &pControl->pRecvIos[i].dsList; - pIo->r_wrq.ds_array[0].length = sizeof(Inic_ControlPacket_t); - pIo->r_wrq.ds_array[0].vaddr = (uint64_t)(pkt++); - pIo->r_wrq.ds_array[0].lkey = pControl->region.lkey; - - if ( ibqp_postRecv( &pControl->qp, pIo ) != IB_SUCCESS ) - { - control_cleanup( pControl ); - ib_status = IB_ERROR; - break; - } - } - -failure: - VNIC_EXIT( VNIC_DBG_CTRL ); - return ib_status; -} - - -void -control_cleanup( - IN Control_t *pControl ) -{ - VNIC_ENTER( VNIC_DBG_CTRL ); - - control_timerStop( pControl ); - ibqp_detach( &pControl->qp ); - ibregion_cleanup( pControl->p_viport, &pControl->region ); - - if ( pControl->pLocalStorage ) - { - cl_free( pControl->pLocalStorage ); - pControl->pLocalStorage = NULL; - } - - cl_timer_destroy( &pControl->timer ); - - VNIC_EXIT( VNIC_DBG_CTRL ); - return; -} - -void -control_processAsync( - IN Control_t *pControl ) -{ - RecvIo_t *pRecvIo; - Inic_ControlPacket_t *pPkt; - LIST_ENTRY *p_list_entry; - - VNIC_ENTER( VNIC_DBG_CTRL ); - - pRecvIo = InterlockedExchangePointer( &pControl->pInfo, NULL ); - - if ( pRecvIo != NULL ) - { - VNIC_TRACE( VNIC_DBG_CTRL, - ("IOC %d: processing info packet\n", - pControl->p_viport->ioc_num ) ); - - pPkt = control_packet( pRecvIo ); - - if ( pPkt->hdr.pktCmd == CMD_REPORT_STATUS ) - { - switch( ntoh32(pPkt->cmd.reportStatus.statusNumber) ) - { - case INIC_STATUS_LINK_UP: - VNIC_TRACE( VNIC_DBG_CTRL, - ("IOC %d: STATUS LINK UP\n", pControl->p_viport->ioc_num ) ); - /* renew link speed info since it can change */ - pControl->p_viport->p_adapter->link_speed = - ntoh32( pPkt->cmd.reportStatus.statusInfo ); - viport_linkUp( pControl->p_viport ); - break; - - case INIC_STATUS_LINK_DOWN: - VNIC_TRACE( VNIC_DBG_CTRL, - ("IOC %d: STATUS LINK DOWN\n", pControl->p_viport->ioc_num ) ); - - viport_linkDown( pControl->p_viport ); - break; - case INIC_STATUS_EIOC_ERROR: - case INIC_STATUS_EIOC_SHUTDOWN: - viport_failure( pControl->p_viport ); - VNIC_TRACE( VNIC_DBG_ERROR, - ("IOC %d: STATUS EIOC ERROR\n", - pControl->p_viport->ioc_num ) ); - break; - default: - VNIC_TRACE( VNIC_DBG_CTRL | VNIC_DBG_ERROR, - ("IOC %d: Asynchronous status %#x received\n", - pControl->p_viport->ioc_num, - ntoh32(pPkt->cmd.reportStatus.statusNumber)) ); - __control_logControlPacket( pPkt ); - break; - } - } - - if ( pPkt->hdr.pktCmd != CMD_REPORT_STATUS || - pPkt->cmd.reportStatus.isFatal ) - { - viport_failure( pControl->p_viport ); - } - - control_recv( pControl, pRecvIo ); - } - - while ( !IsListEmpty( &pControl->failureList ) ) - { - - VNIC_TRACE( VNIC_DBG_CTRL, - ("IOC %d: processing error packet\n", - pControl->p_viport->ioc_num ) ); - - p_list_entry = ExInterlockedRemoveHeadList( &pControl->failureList, &pControl->ioLock ); - pRecvIo = (RecvIo_t *)p_list_entry; - pPkt = control_packet( pRecvIo ); - - VNIC_TRACE( VNIC_DBG_CTRL, - ("IOC %d: Asynchronous error received from EIOC\n", - pControl->p_viport->ioc_num ) ); - - __control_logControlPacket( pPkt ); - - if ( ( pPkt->hdr.pktType != TYPE_ERR ) || - ( pPkt->hdr.pktCmd != CMD_REPORT_STATUS ) || - ( pPkt->cmd.reportStatus.isFatal ) ) - { - viport_failure( pControl->p_viport ); - break; - } - - control_recv( pControl, pRecvIo ); - } - - VNIC_EXIT( VNIC_DBG_CTRL ); -} - - -ib_api_status_t -control_initInicReq( - IN Control_t *pControl ) -{ - ControlConfig_t *p_conf = pControl->p_conf; - Inic_ControlPacket_t *pPkt; - Inic_CmdInitInicReq_t *pInitInicReq; - ib_api_status_t ib_status; - - VNIC_ENTER( VNIC_DBG_CTRL ); - - if( pControl->p_viport->errored ) - { - return IB_ERROR; - } - control_initHdr( pControl, CMD_INIT_INIC ); - - pPkt = control_packet( &pControl->sendIo ); - pInitInicReq = &pPkt->cmd.initInicReq; - pInitInicReq->inicMajorVersion = hton16( INIC_MAJORVERSION ); - pInitInicReq->inicMinorVersion = hton16( INIC_MINORVERSION ); - pInitInicReq->inicInstance = p_conf->inicInstance; - pInitInicReq->numDataPaths = 1; - pInitInicReq->numAddressEntries = hton16( p_conf->maxAddressEntries ); - - ib_status = control_send( pControl ); - VNIC_EXIT( VNIC_DBG_CTRL ); - return ib_status; -} - - -BOOLEAN -control_initInicRsp( - IN Control_t *pControl, - IN uint32_t *pFeatures, - IN uint8_t *pMacAddress, - IN uint16_t *pNumAddrs, - IN uint16_t *pVlan ) -{ - RecvIo_t *pRecvIo; - ControlConfig_t *p_conf = pControl->p_conf; - Inic_ControlPacket_t *pPkt; - Inic_CmdInitInicRsp_t *pInitInicRsp; - uint8_t numDataPaths, - numLanSwitches; - - VNIC_ENTER( VNIC_DBG_CTRL ); - - pRecvIo = control_getRsp( pControl ); - if (!pRecvIo) - return FALSE; - - pPkt = control_packet( pRecvIo ); - - if ( pPkt->hdr.pktCmd != CMD_INIT_INIC ) - { - - VNIC_TRACE( VNIC_DBG_CTRL | VNIC_DBG_ERROR, - ("IOC %d: Sent control request:\n", - pControl->p_viport->ioc_num ) ); - - __control_logControlPacket( control_lastReq( pControl ) ); - - VNIC_TRACE_EXIT( VNIC_DBG_CTRL | VNIC_DBG_ERROR, - ("IOC %d: Received control response:\n", - pControl->p_viport->ioc_num ) ); - - __control_logControlPacket( pPkt ); - goto failure; - } -#ifdef _DEBUG_ - VNIC_TRACE( VNIC_DBG_CTRL_PKT, - ("IOC %d: instance %d Sent initINIC request:\n", - pControl->p_viport->ioc_num, - pControl->p_viport->p_netpath->instance ) ); - __control_logControlPacket( control_lastReq( pControl ) ); - - VNIC_TRACE(VNIC_DBG_CTRL_PKT, - ("IOC %d: instance %d Received initInic response:\n", - pControl->p_viport->ioc_num, - pControl->p_viport->p_netpath->instance ) ); - __control_logControlPacket( pPkt ); -#endif - - pInitInicRsp = &pPkt->cmd.initInicRsp; - pControl->majVer = ntoh16( pInitInicRsp->inicMajorVersion ); - pControl->minVer = ntoh16( pInitInicRsp->inicMinorVersion ); - numDataPaths = pInitInicRsp->numDataPaths; - numLanSwitches = pInitInicRsp->numLanSwitches; - *pFeatures = ntoh32( pInitInicRsp->featuresSupported ); - *pNumAddrs = ntoh16( pInitInicRsp->numAddressEntries ); - - if ( ( pControl->majVer > INIC_MAJORVERSION ) || - (( pControl->majVer == INIC_MAJORVERSION ) && - ( pControl->minVer > INIC_MINORVERSION )) ) - { - VNIC_TRACE_EXIT( VNIC_DBG_CTRL | VNIC_DBG_ERROR, - ("IOC %d: Unsupported version\n", - pControl->p_viport->ioc_num ) ); - goto failure; - } - - if ( numDataPaths != 1 ) - { - VNIC_TRACE_EXIT( VNIC_DBG_CTRL | VNIC_DBG_ERROR, - ("IOC %d: EIOC returned too many datapaths\n", - pControl->p_viport->ioc_num ) ); - goto failure; - } - - if ( *pNumAddrs > p_conf->maxAddressEntries ) - { - VNIC_TRACE_EXIT( VNIC_DBG_CTRL | VNIC_DBG_ERROR, - ("IOC %d: EIOC returned more Address entries than requested\n", - pControl->p_viport->ioc_num) ); - goto failure; - } - if ( *pNumAddrs < p_conf->minAddressEntries ) - { - VNIC_TRACE_EXIT( VNIC_DBG_CTRL | VNIC_DBG_ERROR, - ("IOC %d: Not enough address entries\n", - pControl->p_viport->ioc_num ) ); - goto failure; - } - if ( numLanSwitches < 1 ) - { - VNIC_TRACE_EXIT( VNIC_DBG_CTRL | VNIC_DBG_ERROR, - ("IOC %d: EIOC returned no lan switches\n", - pControl->p_viport->ioc_num ) ); - goto failure; - } - if ( numLanSwitches > 1 ) - { - VNIC_TRACE_EXIT( VNIC_DBG_CTRL | VNIC_DBG_ERROR, - ("IOC %d: EIOC returned multiple lan switches\n", - pControl->p_viport->ioc_num ) ); - goto failure; - } - - pControl->lanSwitch.lanSwitchNum = - pInitInicRsp->lanSwitch[0].lanSwitchNum ; - pControl->lanSwitch.numEnetPorts = - pInitInicRsp->lanSwitch[0].numEnetPorts ; - pControl->lanSwitch.defaultVlan = - ntoh16( pInitInicRsp->lanSwitch[0].defaultVlan ); - *pVlan = pControl->lanSwitch.defaultVlan; - cl_memcpy( pControl->lanSwitch.hwMacAddress, - pInitInicRsp->lanSwitch[0].hwMacAddress, MAC_ADDR_LEN ); - cl_memcpy( pMacAddress, - pInitInicRsp->lanSwitch[0].hwMacAddress, MAC_ADDR_LEN); - - control_recv( pControl, pRecvIo ); - - VNIC_EXIT( VNIC_DBG_CTRL ); - return TRUE; -failure: - viport_failure( pControl->p_viport ); - return FALSE; -} - - -ib_api_status_t -control_configDataPathReq( - IN Control_t *pControl, - IN uint64_t pathId, - IN Inic_RecvPoolConfig_t *pHost, - IN Inic_RecvPoolConfig_t *pEioc ) -{ - Inic_ControlPacket_t *pPkt; - Inic_CmdConfigDataPath_t *pConfigDataPath; - ib_api_status_t ib_status; - - VNIC_ENTER( VNIC_DBG_CTRL ); - - if( pControl->p_viport->errored ) - { - return IB_ERROR; - } - control_initHdr( pControl, CMD_CONFIG_DATA_PATH ); - - pPkt = control_packet( &pControl->sendIo ); - pConfigDataPath = &pPkt->cmd.configDataPathReq; - NdisZeroMemory( pConfigDataPath, sizeof( Inic_CmdConfigDataPath_t ) ); - pConfigDataPath->dataPath = 0; - pConfigDataPath->pathIdentifier = pathId; - copyRecvPoolConfig( pHost, &pConfigDataPath->hostRecvPoolConfig ); - copyRecvPoolConfig( pEioc, &pConfigDataPath->eiocRecvPoolConfig ); - - ib_status = control_send( pControl ); - VNIC_EXIT( VNIC_DBG_CTRL ); - return ib_status; -} - - -BOOLEAN -control_configDataPathRsp( - IN Control_t *pControl, - IN Inic_RecvPoolConfig_t *pHost, - IN Inic_RecvPoolConfig_t *pEioc, - IN Inic_RecvPoolConfig_t *pMaxHost, - IN Inic_RecvPoolConfig_t *pMaxEioc, - IN Inic_RecvPoolConfig_t *pMinHost, - IN Inic_RecvPoolConfig_t *pMinEioc ) -{ - RecvIo_t *pRecvIo; - Inic_ControlPacket_t *pPkt; - Inic_CmdConfigDataPath_t *pConfigDataPath; - - VNIC_ENTER( VNIC_DBG_CTRL ); - - pRecvIo = control_getRsp( pControl ); - if ( !pRecvIo ) - return FALSE; - - pPkt = control_packet( pRecvIo ); - - if ( pPkt->hdr.pktCmd != CMD_CONFIG_DATA_PATH ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("IOC %d: Sent control request:\n", - pControl->p_viport->ioc_num ) ); - - __control_logControlPacket( control_lastReq( pControl ) ); - - VNIC_TRACE( VNIC_DBG_ERROR, - ("IOC %d: Received control response:\n", - pControl->p_viport->ioc_num ) ); - - __control_logControlPacket( pPkt ); - goto failure; - } -#ifdef _DEBUG_ - VNIC_TRACE( VNIC_DBG_CTRL_PKT, - ("IOC %d: instance %d Sent configDATAPATH request:\n", - pControl->p_viport->ioc_num, - pControl->p_viport->p_netpath->instance ) ); - __control_logControlPacket( control_lastReq( pControl ) ); - - VNIC_TRACE(VNIC_DBG_CTRL_PKT, - ("IOC %d: instance %d Received configDATAPATH response:\n", - pControl->p_viport->ioc_num, - pControl->p_viport->p_netpath->instance ) ); - __control_logControlPacket( pPkt ); -#endif - pConfigDataPath = &pPkt->cmd.configDataPathRsp; - - if ( pConfigDataPath->dataPath != 0 ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("IOC %d: Received CMD_CONFIG_DATA_PATH response for wrong data path: %u\n", - pControl->p_viport->ioc_num , pConfigDataPath->dataPath) ); - goto failure; - } - - if ( !checkRecvPoolConfig(&pConfigDataPath->hostRecvPoolConfig, - pHost, pMaxHost, pMinHost ) - || !checkRecvPoolConfig(&pConfigDataPath->eiocRecvPoolConfig, - pEioc, pMaxEioc, pMinEioc)) - { - goto failure; - } - - control_recv( pControl, pRecvIo ); - - VNIC_EXIT( VNIC_DBG_CTRL ); - return TRUE; -failure: - viport_failure( pControl->p_viport ); - VNIC_EXIT( VNIC_DBG_CTRL ); - return FALSE; -} - - -ib_api_status_t -control_exchangePoolsReq( - IN Control_t *pControl, - IN uint64_t addr, - IN uint32_t rkey ) -{ - Inic_CmdExchangePools_t *pExchangePools; - Inic_ControlPacket_t *pPkt; - ib_api_status_t ib_status; - - VNIC_ENTER( VNIC_DBG_CTRL ); - - if( pControl->p_viport->errored ) - { - return IB_ERROR; - } - control_initHdr(pControl, CMD_EXCHANGE_POOLS ); - - pPkt = control_packet( &pControl->sendIo ); - pExchangePools = &pPkt->cmd.exchangePoolsReq; - NdisZeroMemory( pExchangePools, sizeof( Inic_CmdExchangePools_t ) ); - pExchangePools->dataPath = 0; - pExchangePools->poolRKey = rkey; - pExchangePools->poolAddr = hton64( addr ); - - ib_status = control_send( pControl ); - VNIC_EXIT( VNIC_DBG_CTRL ); - return ib_status; -} - - -BOOLEAN -control_exchangePoolsRsp( - IN Control_t *pControl, - IN OUT uint64_t *pAddr, - IN OUT uint32_t *pRkey ) -{ - RecvIo_t *pRecvIo; - Inic_ControlPacket_t *pPkt; - Inic_CmdExchangePools_t *pExchangePools; - - VNIC_ENTER( VNIC_DBG_CTRL ); - - pRecvIo = control_getRsp( pControl ); - if ( !pRecvIo ) - return FALSE; - - pPkt = control_packet( pRecvIo ); - - if ( pPkt->hdr.pktCmd != CMD_EXCHANGE_POOLS ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("IOC %d: Sent control request:\n", - pControl->p_viport->ioc_num ) ); - - __control_logControlPacket( control_lastReq(pControl ) ); - - VNIC_TRACE( VNIC_DBG_ERROR, - ("IOC %d: Received control response:\n", - pControl->p_viport->ioc_num ) ); - - __control_logControlPacket( pPkt ); - goto failure; - } - -#ifdef _DEBUG_ - VNIC_TRACE( VNIC_DBG_CTRL_PKT, - ("IOC %d: instance %d Sent exchangePOOLS request:\n", - pControl->p_viport->ioc_num, - pControl->p_viport->p_netpath->instance ) ); - __control_logControlPacket( control_lastReq( pControl ) ); - - VNIC_TRACE(VNIC_DBG_CTRL_PKT, - ("IOC %d: instance %d Received exchangePOOLS response:\n", - pControl->p_viport->ioc_num, - pControl->p_viport->p_netpath->instance ) ); - __control_logControlPacket( pPkt ); -#endif - pExchangePools = &pPkt->cmd.exchangePoolsRsp; - *pRkey = pExchangePools->poolRKey; - *pAddr = ntoh64( pExchangePools->poolAddr ); - - if ( hton32( pExchangePools->dataPath ) != 0 ) - { - VNIC_TRACE_EXIT( VNIC_DBG_ERROR, - ("IOC %d: Received CMD_EXCHANGE_POOLS response for wrong data path: %u\n", - pControl->p_viport->ioc_num , pExchangePools->dataPath ) ); - goto failure; - } - - control_recv( pControl, pRecvIo ); - - VNIC_EXIT( VNIC_DBG_CTRL ); - return TRUE; - -failure: - viport_failure( pControl->p_viport ); - return FALSE; -} - - -ib_api_status_t -control_configLinkReq( - IN Control_t *pControl, - IN uint8_t flags, - IN uint16_t mtu ) -{ - Inic_CmdConfigLink_t *pConfigLinkReq; - Inic_ControlPacket_t *pPkt; - ib_api_status_t ib_status; - - VNIC_ENTER( VNIC_DBG_CTRL ); - - if( pControl->p_viport->errored ) - { - return IB_ERROR; - } - control_initHdr( pControl, CMD_CONFIG_LINK ); - - pPkt = control_packet( &pControl->sendIo ); - pConfigLinkReq = &pPkt->cmd.configLinkReq; - NdisZeroMemory( pConfigLinkReq, sizeof( Inic_CmdConfigLink_t ) ); - pConfigLinkReq->lanSwitchNum = pControl->lanSwitch.lanSwitchNum; - - if ( flags & INIC_FLAG_ENABLE_NIC ) - { - pConfigLinkReq->cmdFlags |= INIC_FLAG_ENABLE_NIC; - } - else - { - pConfigLinkReq->cmdFlags |= INIC_FLAG_DISABLE_NIC; - } - - if (flags & INIC_FLAG_ENABLE_MCAST_ALL ) - { - pConfigLinkReq->cmdFlags |= INIC_FLAG_ENABLE_MCAST_ALL; - } - else - { - pConfigLinkReq->cmdFlags |= INIC_FLAG_DISABLE_MCAST_ALL; - } - if (flags & INIC_FLAG_ENABLE_PROMISC ) - { - pConfigLinkReq->cmdFlags |= INIC_FLAG_ENABLE_PROMISC; - /* The EIOU doesn't really do PROMISC mode. - * If PROMISC is set, it only receives unicast packets - * I also have to set MCAST_ALL if I want real - * PROMISC mode. - */ - pConfigLinkReq->cmdFlags &= ~INIC_FLAG_DISABLE_MCAST_ALL; - pConfigLinkReq->cmdFlags |= INIC_FLAG_ENABLE_MCAST_ALL; - } - else - { - pConfigLinkReq->cmdFlags |= INIC_FLAG_DISABLE_PROMISC; - } - - if( flags & INIC_FLAG_SET_MTU ) - { - pConfigLinkReq->cmdFlags |= INIC_FLAG_SET_MTU; - pConfigLinkReq->mtuSize = hton16( mtu ); - } - - ib_status = control_send( pControl ); - VNIC_EXIT( VNIC_DBG_CTRL ); - return ib_status; -} - - -BOOLEAN -control_configLinkRsp( - IN Control_t *pControl, - IN OUT uint8_t *pFlags, - IN OUT uint16_t *pMtu ) -{ - RecvIo_t *pRecvIo; - Inic_ControlPacket_t *pPkt; - Inic_CmdConfigLink_t *pConfigLinkRsp; - - VNIC_ENTER( VNIC_DBG_CTRL ); - - pRecvIo = control_getRsp( pControl ); - if ( !pRecvIo ) - return FALSE; - - pPkt = control_packet( pRecvIo ); - if ( pPkt->hdr.pktCmd != CMD_CONFIG_LINK ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("IOC %d: Sent control request:\n", - pControl->p_viport->ioc_num ) ); - - __control_logControlPacket( control_lastReq( pControl ) ); - - VNIC_TRACE( VNIC_DBG_ERROR, - ("IOC %d: Received control response:\n", - pControl->p_viport->ioc_num ) ); - - __control_logControlPacket( pPkt ); - goto failure; - } -#ifdef _DEBUG_ - VNIC_TRACE( VNIC_DBG_CTRL_PKT, - ("IOC %d: instance %d Sent configLINK request:\n", - pControl->p_viport->ioc_num, - pControl->p_viport->p_netpath->instance ) ); - __control_logControlPacket( control_lastReq( pControl ) ); - - VNIC_TRACE(VNIC_DBG_CTRL_PKT, - ("IOC %d: instance %d Received configLINK response:\n", - pControl->p_viport->ioc_num, - pControl->p_viport->p_netpath->instance ) ); - __control_logControlPacket( pPkt ); -#endif - pConfigLinkRsp = &pPkt->cmd.configLinkRsp; - - *pFlags = pConfigLinkRsp->cmdFlags; - *pMtu = ntoh16( pConfigLinkRsp->mtuSize ); - - control_recv( pControl, pRecvIo ); - - VNIC_EXIT( VNIC_DBG_CTRL ); - return TRUE; - -failure: - viport_failure( pControl->p_viport ); - VNIC_EXIT( VNIC_DBG_CTRL ); - return FALSE; -} - -/* control_configAddrsReq: - * Return values: - * -1: failure - * 0: incomplete (successful operation, but more address - * table entries to be updated) - * 1: complete - */ -ib_api_status_t -control_configAddrsReq( - IN Control_t *pControl, - IN Inic_AddressOp_t *pAddrs, - IN uint16_t num, - OUT int32_t *pAddrQueryDone ) -{ - Inic_CmdConfigAddresses_t *pConfigAddrsReq; - Inic_ControlPacket_t *pPkt; - uint16_t i; - uint8_t j; - ib_api_status_t ib_status; - - VNIC_ENTER( VNIC_DBG_CTRL ); - - if( pControl->p_viport->errored ) - { - return IB_ERROR; - } - control_initHdr( pControl, CMD_CONFIG_ADDRESSES ); - - pPkt = control_packet( &pControl->sendIo ); - pConfigAddrsReq = &pPkt->cmd.configAddressesReq; - NdisZeroMemory( pConfigAddrsReq, sizeof( Inic_CmdConfigAddresses_t ) ); - pConfigAddrsReq->lanSwitchNum = pControl->lanSwitch.lanSwitchNum; - - for ( i=0, j = 0; ( i < num ) && ( j < 16 ); i++ ) - { - if ( !pAddrs[i].operation ) - continue; - - pConfigAddrsReq->listAddressOps[j].index = hton16(i); - pConfigAddrsReq->listAddressOps[j].operation = INIC_OP_SET_ENTRY; - pConfigAddrsReq->listAddressOps[j].valid = pAddrs[i].valid; - - cl_memcpy( pConfigAddrsReq->listAddressOps[j].address, - pAddrs[i].address, MAC_ADDR_LEN ); - pConfigAddrsReq->listAddressOps[j].vlan = hton16( pAddrs[i].vlan ); - pAddrs[i].operation = 0; - j++; - } - pConfigAddrsReq->numAddressOps = j; - - for ( ; i < num; i++ ) - { - if ( pAddrs[i].operation ) - break; - } - *pAddrQueryDone = (i == num); - - ib_status = control_send( pControl ); - VNIC_EXIT( VNIC_DBG_CTRL ); - return ib_status; -} - - -BOOLEAN -control_configAddrsRsp( - IN Control_t *pControl ) -{ - RecvIo_t *pRecvIo; - Inic_ControlPacket_t *pPkt; - Inic_CmdConfigAddresses_t *pConfigAddrsRsp; - - VNIC_ENTER( VNIC_DBG_CTRL ); - - pRecvIo = control_getRsp( pControl ); - if ( !pRecvIo ) - return FALSE; - - pPkt = control_packet( pRecvIo ); - if ( pPkt->hdr.pktCmd != CMD_CONFIG_ADDRESSES ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("IOC %d: Sent control request:\n", - pControl->p_viport->ioc_num ) ); - - __control_logControlPacket( control_lastReq( pControl ) ); - - VNIC_TRACE_EXIT(VNIC_DBG_ERROR, - ("IOC %d: Received control response:\n", - pControl->p_viport->ioc_num ) ); - - __control_logControlPacket( pPkt ); - - goto failure; - } - -#ifdef _DEBUG_ - VNIC_TRACE( VNIC_DBG_CTRL_PKT, - ("IOC %d: instance %d Sent configADDRS request:\n", - pControl->p_viport->ioc_num, - pControl->p_viport->p_netpath->instance ) ); - __control_logControlPacket( control_lastReq( pControl ) ); - - VNIC_TRACE(VNIC_DBG_CTRL_PKT, - ("IOC %d: instance %d Received configADDRS response:\n", - pControl->p_viport->ioc_num, - pControl->p_viport->p_netpath->instance ) ); - __control_logControlPacket( pPkt ); -#endif - - pConfigAddrsRsp = &pPkt->cmd.configAddressesRsp; - - control_recv( pControl, pRecvIo ); - VNIC_EXIT( VNIC_DBG_CTRL ); - return TRUE; - -failure: - viport_failure( pControl->p_viport ); - return FALSE; -} - - -ib_api_status_t -control_reportStatisticsReq( - IN Control_t *pControl ) -{ - Inic_ControlPacket_t *pPkt; - Inic_CmdReportStatisticsReq_t *pReportStatisticsReq; - ib_api_status_t ib_status; - - VNIC_ENTER( VNIC_DBG_CTRL ); - - control_initHdr( pControl, CMD_REPORT_STATISTICS ); - - pPkt = control_packet( &pControl->sendIo ); - pReportStatisticsReq = &pPkt->cmd.reportStatisticsReq; - pReportStatisticsReq->lanSwitchNum = pControl->lanSwitch.lanSwitchNum; - - ib_status = control_send( pControl ); - VNIC_EXIT( VNIC_DBG_CTRL ); - return ib_status; -} - - -BOOLEAN -control_reportStatisticsRsp( - IN Control_t *pControl, - IN Inic_CmdReportStatisticsRsp_t *pStats ) -{ - RecvIo_t *pRecvIo; - Inic_ControlPacket_t *pPkt; - Inic_CmdReportStatisticsRsp_t *pRepStatRsp; - - VNIC_ENTER( VNIC_DBG_CTRL ); - - pRecvIo = control_getRsp( pControl ); - if (!pRecvIo) - return FALSE; - - pPkt = control_packet( pRecvIo ); - if ( pPkt->hdr.pktCmd != CMD_REPORT_STATISTICS ) - { - VNIC_TRACE(VNIC_DBG_ERROR, - ("IOC %d: Sent control request:\n", - pControl->p_viport->ioc_num ) ); - - __control_logControlPacket( control_lastReq( pControl ) ); - - VNIC_TRACE_EXIT(VNIC_DBG_ERROR, - ("IOC %d: Received control response:\n", - pControl->p_viport->ioc_num ) ); - - __control_logControlPacket( pPkt ); - - goto failure; - } - - pRepStatRsp = &pPkt->cmd.reportStatisticsRsp; - pStats->ifInBroadcastPkts = ntoh64(pRepStatRsp->ifInBroadcastPkts); - pStats->ifInMulticastPkts = ntoh64(pRepStatRsp->ifInMulticastPkts); - pStats->ifInOctets = ntoh64(pRepStatRsp->ifInOctets); - pStats->ifInUcastPkts = ntoh64(pRepStatRsp->ifInUcastPkts); - pStats->ifInNUcastPkts = ntoh64(pRepStatRsp->ifInNUcastPkts); - pStats->ifInUnderrun = ntoh64(pRepStatRsp->ifInUnderrun); - pStats->ifInErrors = ntoh64(pRepStatRsp->ifInErrors); - pStats->ifOutErrors = ntoh64(pRepStatRsp->ifOutErrors); - pStats->ifOutOctets = ntoh64(pRepStatRsp->ifOutOctets); - pStats->ifOutUcastPkts = ntoh64(pRepStatRsp->ifOutUcastPkts); - pStats->ifOutMulticastPkts = ntoh64(pRepStatRsp->ifOutMulticastPkts); - pStats->ifOutBroadcastPkts = ntoh64(pRepStatRsp->ifOutBroadcastPkts); - pStats->ifOutNUcastPkts = ntoh64(pRepStatRsp->ifOutNUcastPkts); - pStats->ifOutOk = ntoh64(pRepStatRsp->ifOutOk); - pStats->ifInOk = ntoh64(pRepStatRsp->ifInOk); - pStats->ifOutUcastBytes = ntoh64(pRepStatRsp->ifOutUcastBytes); - pStats->ifOutMulticastBytes = ntoh64(pRepStatRsp->ifOutMulticastBytes); - pStats->ifOutBroadcastBytes = ntoh64(pRepStatRsp->ifOutBroadcastBytes); - pStats->ifInUcastBytes = ntoh64(pRepStatRsp->ifInUcastBytes); - pStats->ifInMulticastBytes = ntoh64(pRepStatRsp->ifInMulticastBytes); - pStats->ifInBroadcastBytes = ntoh64(pRepStatRsp->ifInBroadcastBytes); - pStats->ethernetStatus = ntoh64(pRepStatRsp->ethernetStatus); - - control_recv(pControl, pRecvIo); - - VNIC_EXIT( VNIC_DBG_CTRL ); - return TRUE; -failure: - viport_failure( pControl->p_viport ); - return FALSE; -} - - -ib_api_status_t -control_resetReq( - IN Control_t *pControl ) -{ - ib_api_status_t ib_status; - - VNIC_ENTER( VNIC_DBG_CTRL ); - - control_initHdr( pControl, CMD_RESET ); - ib_status = control_send( pControl ); - - VNIC_EXIT( VNIC_DBG_CTRL ); - return ib_status; -} - -BOOLEAN -control_resetRsp( - IN Control_t *pControl ) -{ - RecvIo_t *pRecvIo; - Inic_ControlPacket_t *pPkt; - - VNIC_ENTER( VNIC_DBG_CTRL ); - - pRecvIo = control_getRsp( pControl ); - if ( !pRecvIo ) return FALSE; - - pPkt = control_packet( pRecvIo ); - - if ( pPkt->hdr.pktCmd != CMD_RESET ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("IOC %d: Sent control request:\n", - pControl->p_viport->ioc_num ) ); - - __control_logControlPacket( control_lastReq( pControl ) ); - - VNIC_TRACE( VNIC_DBG_ERROR, - ("IOC %d: Received control response:\n", - pControl->p_viport->ioc_num ) ); - - __control_logControlPacket( pPkt ); - - goto failure; - } - - control_recv( pControl, pRecvIo ); - VNIC_EXIT( VNIC_DBG_CTRL ); - return TRUE; -failure: - viport_failure( pControl->p_viport ); - VNIC_EXIT( VNIC_DBG_CTRL ); - return FALSE; -} - - -ib_api_status_t -control_heartbeatReq( - IN Control_t *pControl, - IN uint32_t hbInterval ) -{ - Inic_ControlPacket_t *pPkt; - Inic_CmdHeartbeat_t *pHeartbeatReq; - ib_api_status_t ib_status; - - VNIC_ENTER( VNIC_DBG_CTRL ); - if( pControl->p_viport->errored ) - { - return IB_ERROR; - } - control_initHdr(pControl, CMD_HEARTBEAT); - - pPkt = control_packet(&pControl->sendIo); - pHeartbeatReq = &pPkt->cmd.heartbeatReq; - - /* pass timeout for the target in microseconds */ - pHeartbeatReq->hbInterval = hton32( hbInterval*1000 ); - - ib_status = control_send( pControl ); - VNIC_EXIT( VNIC_DBG_CTRL ); - return ib_status; -} - -BOOLEAN -control_heartbeatRsp( - IN Control_t *pControl ) -{ - RecvIo_t *pRecvIo; - Inic_ControlPacket_t *pPkt; - Inic_CmdHeartbeat_t *pHeartbeatRsp; - - VNIC_ENTER( VNIC_DBG_CTRL ); - - pRecvIo = control_getRsp( pControl ); - - if (!pRecvIo) - return FALSE; - - pPkt = control_packet(pRecvIo); - - if ( pPkt->hdr.pktCmd != CMD_HEARTBEAT ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("IOC %d: Sent control request:\n", - pControl->p_viport->ioc_num ) ); - - __control_logControlPacket( control_lastReq(pControl) ); - - VNIC_TRACE( VNIC_DBG_ERROR, - ("IOC %d: Received control response:\n", - pControl->p_viport->ioc_num ) ); - - __control_logControlPacket( pPkt ); - goto failure; - } - - pHeartbeatRsp = &pPkt->cmd.heartbeatRsp; - - control_recv( pControl, pRecvIo ); - VNIC_EXIT ( VNIC_DBG_CTRL ); - return TRUE; - -failure: - viport_failure( pControl->p_viport ); - VNIC_EXIT ( VNIC_DBG_CTRL ); - return FALSE; -} - -static void -control_recv( - IN Control_t *pControl, - IN RecvIo_t *pRecvIo ) -{ - VNIC_ENTER( VNIC_DBG_CTRL ); - - if ( ibqp_postRecv( &pControl->qp, &pRecvIo->io ) != IB_SUCCESS ) - viport_failure( pControl->p_viport ); - - VNIC_EXIT ( VNIC_DBG_CTRL ); -} - - -static void -control_recvComplete( - IN Io_t *pIo ) -{ - RecvIo_t *pRecvIo = (RecvIo_t *)pIo; - RecvIo_t *pLastRecvIo; - BOOLEAN status = FALSE; - Control_t *pControl = &pIo->pViport->control; - viport_t *p_viport = pIo->pViport; - Inic_ControlPacket_t *pPkt = control_packet(pRecvIo); - Inic_ControlHeader_t *pCHdr = &pPkt->hdr; - - if( p_viport->errored ) - { - return; - } - switch ( pCHdr->pktType ) - { - case TYPE_INFO: - pLastRecvIo = InterlockedExchangePointer( &pControl->pInfo, pRecvIo ); - - control_processAsync( pControl ); - - if ( pLastRecvIo ) - { - control_recv( pControl, pLastRecvIo ); - } - return; - - case TYPE_RSP: - break; - - default: - //TODO: Should we ever reach this? Who processes the list entries? - ASSERT( pCHdr->pktType == TYPE_INFO || pCHdr->pktType == TYPE_RSP ); - ExInterlockedInsertTailList( &pRecvIo->io.listPtrs, - &pControl->failureList, - &pControl->ioLock ); - return; - } - - if( !InterlockedExchange( (volatile LONG*)&pControl->rspExpected, FALSE ) ) - { - VNIC_TRACE_EXIT( VNIC_DBG_ERROR, - ("UNEXPECTED RSP Packet CMD: %d\n", pCHdr->pktCmd ) ); - return; - } - - InterlockedExchangePointer( &pControl->pResponse, pRecvIo ); - - switch ( pCHdr->pktCmd ) - { - case CMD_INIT_INIC: - status = control_initInicRsp( pControl, - &p_viport->featuresSupported, - p_viport->hwMacAddress, - &p_viport->numMacAddresses, - &p_viport->defaultVlan ); - if( status ) - { - InterlockedExchange( - (volatile LONG*)&p_viport->linkState, - (LONG)LINK_INITINICRSP ); - } - InterlockedOr( &p_viport->updates, SYNC_QUERY ); - break; - - case CMD_CONFIG_DATA_PATH: - status = control_configDataPathRsp( pControl, - data_hostPool( &p_viport->data ), - data_eiocPool( &p_viport->data ), - data_hostPoolMax( &p_viport->data ), - data_eiocPoolMax( &p_viport->data ), - data_hostPoolMin( &p_viport->data ), - data_eiocPoolMin( &p_viport->data )); - if( status ) - { - InterlockedExchange( - (volatile LONG*)&p_viport->linkState, - (LONG)LINK_CONFIGDATAPATHRSP ); - } - InterlockedOr( &p_viport->updates, SYNC_QUERY ); - break; - - case CMD_EXCHANGE_POOLS: - status = control_exchangePoolsRsp( &p_viport->control, - data_remotePoolAddr( &p_viport->data ), - data_remotePoolRkey( &p_viport->data ) ); - if( status ) - { - InterlockedExchange( - (volatile LONG*)&p_viport->linkState, - (LONG)LINK_XCHGPOOLRSP ); - } - InterlockedOr( &p_viport->updates, SYNC_QUERY ); - break; - - /* process other responses */ - case CMD_CONFIG_LINK: - status = control_configLinkRsp( &p_viport->control, - &p_viport->flags, - &p_viport->mtu ); - if( status ) - { - InterlockedExchange( - (volatile LONG*)&p_viport->linkState, - (LONG)LINK_CONFIGLINKRSP ); - - if( p_viport->flags & INIC_FLAG_ENABLE_NIC ) - { - /* don't indicate media state yet if in sync query */ - if( ( InterlockedExchange( &p_viport->p_netpath->carrier, TRUE ) == FALSE ) && - !( p_viport->updates & SYNC_QUERY ) ) - { - viport_restartXmit( p_viport ); - //viport_linkUp( p_viport ); - } - } - else if( p_viport->flags & INIC_FLAG_DISABLE_NIC ) - { - if( InterlockedExchange( &p_viport->p_netpath->carrier, FALSE ) == TRUE ) - { - viport_stopXmit( p_viport ); - viport_linkDown( p_viport ); - } - } - InterlockedAnd( &p_viport->updates, ~NEED_LINK_CONFIG ); - } - break; - - case CMD_HEARTBEAT: - status = control_heartbeatRsp( pControl ); - if( status && - !p_viport->errored && - !p_viport->disconnect ) - { - InterlockedExchange( - (volatile LONG*)&p_viport->link_hb_state, - (LONG)LINK_HEARTBEATRSP ); - } - // Don't signal any waiting thread or start processing other updates. - return; - - case CMD_CONFIG_ADDRESSES: - status = control_configAddrsRsp( pControl ); - if( status == TRUE ) - { // need more entries to send? - if( p_viport->addrs_query_done == 0 ) - { - if( !p_viport->errored ) - { - if( control_configAddrsReq( pControl, - p_viport->macAddresses, - p_viport->numMacAddresses, - &p_viport->addrs_query_done ) != IB_SUCCESS ) - { - viport_failure( p_viport ); - } - } - // Don't signal any waiting thread or start processing other updates. - return; - } - - InterlockedAnd( &p_viport->updates, ~NEED_ADDRESS_CONFIG ); - InterlockedExchange( (volatile LONG*)&p_viport->linkState, - (LONG)LINK_CONFIGADDRSRSP ); - } - break; - - case CMD_REPORT_STATISTICS: - status = control_reportStatisticsRsp( pControl, &p_viport->stats ); - if ( status ) - { - if( p_viport->stats.ethernetStatus > 0 && - !p_viport->errored ) - { - viport_linkUp( p_viport ); - } - else - { - viport_linkDown( p_viport ); - } - } - InterlockedAnd( &p_viport->updates, ~NEED_STATS ); - break; - - case CMD_RESET: - status = control_resetRsp( pControl ); - if( status ) - { - status = FALSE; - InterlockedExchange( - (volatile LONG*)&p_viport->linkState, - (LONG)LINK_RESETRSP ); - } - break; - - default: - break; - } - - if( _viport_process_query( p_viport, FALSE ) != NDIS_STATUS_PENDING ) - { - /* Complete any pending set OID. */ - vnic_resume_set_oids( p_viport->p_adapter ); - } - - if( InterlockedAnd( &p_viport->updates, ~SYNC_QUERY ) & SYNC_QUERY ) - cl_event_signal( &p_viport->sync_event ); -} - - -static ib_api_status_t -control_send( - IN Control_t *pControl ) -{ - Inic_ControlPacket_t *pPkt = control_packet(&pControl->sendIo); - - VNIC_ENTER ( VNIC_DBG_CTRL ); - - if ( InterlockedCompareExchange( (volatile LONG*)&pControl->reqOutstanding, - TRUE, FALSE ) == TRUE ) - { - /* IF WE HIT THIS WE ARE HOSED!!! - * by the time we detect this error, the send buffer has been - * overwritten, and if we retry we will send garbage data. - */ - VNIC_TRACE_EXIT( VNIC_DBG_ERROR, - ("IB Send never completed\n" ) ); - goto failure; - } - -#ifdef _DEBUG_ - //__control_logControlPacket( pPkt ); -#endif - InterlockedExchange( (volatile LONG*)&pControl->rspExpected, - (LONG)pPkt->hdr.pktCmd ); - - control_timer( pControl, pControl->p_conf->rspTimeout ); - -#ifdef VNIC_STATISTIC - pControl->statistics.requestTime = cl_get_time_stamp(); -#endif /* VNIC_STATISTIC */ - - if( ( ibqp_postSend( &pControl->qp, &pControl->sendIo.io )) != IB_SUCCESS ) - { - InterlockedExchange((volatile LONG*)&pControl->reqOutstanding, FALSE ); - - VNIC_TRACE( VNIC_DBG_ERROR, - ("IOC %d: Failed to post send\n", pControl->p_viport->ioc_num ) ); - goto failure; - } - - VNIC_EXIT( VNIC_DBG_CTRL ); - return IB_SUCCESS; - -failure: - pControl->p_viport->p_adapter->hung++; - viport_failure( pControl->p_viport ); - VNIC_EXIT( VNIC_DBG_CTRL ); - return IB_ERROR; -} - - -static void -control_sendComplete( - IN Io_t *pIo ) -{ - Control_t *pControl = &pIo->pViport->control; - - VNIC_ENTER( VNIC_DBG_CTRL ); - - InterlockedExchange((volatile LONG*)&pControl->reqOutstanding, FALSE ); - - VNIC_EXIT( VNIC_DBG_CTRL ); - return; -} - -static void -control_timeout( - IN void *p_context ) -{ - Control_t *pControl; - - VNIC_ENTER( VNIC_DBG_CTRL ); - - pControl = (Control_t *)p_context; - - InterlockedExchange( (LONG *)&pControl->timerstate, (LONG)TIMER_EXPIRED ); - - InterlockedExchange( (volatile LONG*)&pControl->rspExpected, FALSE ); - - VNIC_EXIT( VNIC_DBG_CTRL ); - return; -} - -static void -control_timer( - IN Control_t *pControl, - IN int timeout ) -{ - VNIC_ENTER( VNIC_DBG_CTRL ); - - InterlockedExchange( (LONG *)&pControl->timerstate, (LONG)TIMER_ACTIVE ); - - cl_timer_start(&pControl->timer, timeout); - - VNIC_EXIT( VNIC_DBG_CTRL ); - return; -} - -static void -control_timerStop( - IN Control_t *pControl ) -{ - VNIC_ENTER( VNIC_DBG_CTRL ); - - - if ( ( InterlockedExchange( (LONG *)&pControl->timerstate, - (LONG)TIMER_IDLE )) == TIMER_ACTIVE ) - { - cl_timer_stop( &pControl->timer ); - } - - VNIC_EXIT( VNIC_DBG_CTRL ); - return; -} - -static void -control_initHdr( - IN Control_t * pControl, - IN uint8_t cmd ) -{ - ControlConfig_t *p_conf; - Inic_ControlPacket_t *pPkt; - Inic_ControlHeader_t *pHdr; - - VNIC_ENTER( VNIC_DBG_CTRL ); - - p_conf = pControl->p_conf; - - pPkt = control_packet( &pControl->sendIo ); - pHdr = &pPkt->hdr; - - pHdr->pktType = TYPE_REQ; - pHdr->pktCmd = cmd; - pHdr->pktSeqNum = ++pControl->seqNum; - pControl->reqRetryCounter = 0; - pHdr->pktRetryCount = 0; - - VNIC_EXIT( VNIC_DBG_CTRL ); -} - -static RecvIo_t* -control_getRsp( - IN Control_t *pControl ) -{ - RecvIo_t *pRecvIo; - - VNIC_ENTER ( VNIC_DBG_CTRL ); - - pRecvIo = InterlockedExchangePointer( &pControl->pResponse, NULL ); - - if ( pRecvIo != NULL ) - { - control_timerStop(pControl); - return pRecvIo; - } - - if ( ( pControl->timerstate = - InterlockedCompareExchange( (LONG *)&pControl->timerstate, - (LONG)TIMER_IDLE, (LONG)TIMER_EXPIRED )) == TIMER_EXPIRED ) - { - Inic_ControlPacket_t *pPkt = control_packet( &pControl->sendIo ); - Inic_ControlHeader_t *pHdr = &pPkt->hdr; - - VNIC_TRACE( VNIC_DBG_ERROR, - ("IOC %d: No response received from EIOC\n", - pControl->p_viport->ioc_num ) ); -#ifdef VNIC_STATISTIC - pControl->statistics.timeoutNum++; -#endif /* VNIC_STATISTIC */ - - pControl->reqRetryCounter++; - - if ( pControl->reqRetryCounter >= pControl->p_conf->reqRetryCount ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("IOC %d: Control packet retry exceeded\n", - pControl->p_viport->ioc_num ) ); - } - else - { - pHdr->pktRetryCount = pControl->reqRetryCounter; - control_send( pControl ); - } - } - return NULL; -} - -static void -copyRecvPoolConfig( - IN Inic_RecvPoolConfig_t *pSrc, - IN OUT Inic_RecvPoolConfig_t *pDst ) -{ - - pDst->sizeRecvPoolEntry = hton32(pSrc->sizeRecvPoolEntry); - pDst->numRecvPoolEntries = hton32(pSrc->numRecvPoolEntries); - pDst->timeoutBeforeKick = hton32(pSrc->timeoutBeforeKick); - pDst->numRecvPoolEntriesBeforeKick = hton32(pSrc->numRecvPoolEntriesBeforeKick); - pDst->numRecvPoolBytesBeforeKick = hton32(pSrc->numRecvPoolBytesBeforeKick); - pDst->freeRecvPoolEntriesPerUpdate = hton32(pSrc->freeRecvPoolEntriesPerUpdate); - return; -} - -static BOOLEAN -checkRecvPoolConfigValue( - IN void *pSrc, - IN void *pDst, - IN void *pMax, - IN void *pMin, - IN char *name ) -{ - uint32_t value; - uint32_t *p_src = (uint32_t *)pSrc; - uint32_t *p_dst = (uint32_t *)pDst; - uint32_t *p_min = (uint32_t *)pMin; - uint32_t *p_max = (uint32_t *)pMax; - - UNREFERENCED_PARAMETER( name ); - - value = ntoh32( *p_src ); - - if (value > *p_max ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("Value %s too large\n", name) ); - return FALSE; - } - else if (value < *p_min ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("Value %s too small\n", name) ); - return FALSE; - } - - *p_dst = value; - return TRUE; -} - -static BOOLEAN -checkRecvPoolConfig( - IN Inic_RecvPoolConfig_t *pSrc, - IN Inic_RecvPoolConfig_t *pDst, - IN Inic_RecvPoolConfig_t *pMax, - IN Inic_RecvPoolConfig_t *pMin ) -{ - if (!checkRecvPoolConfigValue(&pSrc->sizeRecvPoolEntry, &pDst->sizeRecvPoolEntry, - &pMax->sizeRecvPoolEntry, &pMin->sizeRecvPoolEntry, "sizeRecvPoolEntry") - || !checkRecvPoolConfigValue(&pSrc->numRecvPoolEntries, &pDst->numRecvPoolEntries, - &pMax->numRecvPoolEntries, &pMin->numRecvPoolEntries, "numRecvPoolEntries") - || !checkRecvPoolConfigValue(&pSrc->timeoutBeforeKick, &pDst->timeoutBeforeKick, - &pMax->timeoutBeforeKick, &pMin->timeoutBeforeKick, "timeoutBeforeKick") - || !checkRecvPoolConfigValue(&pSrc->numRecvPoolEntriesBeforeKick, - &pDst->numRecvPoolEntriesBeforeKick, &pMax->numRecvPoolEntriesBeforeKick, - &pMin->numRecvPoolEntriesBeforeKick, "numRecvPoolEntriesBeforeKick") - || !checkRecvPoolConfigValue(&pSrc->numRecvPoolBytesBeforeKick, - &pDst->numRecvPoolBytesBeforeKick, &pMax->numRecvPoolBytesBeforeKick, - &pMin->numRecvPoolBytesBeforeKick, "numRecvPoolBytesBeforeKick") - || !checkRecvPoolConfigValue(&pSrc->freeRecvPoolEntriesPerUpdate, - &pDst->freeRecvPoolEntriesPerUpdate, &pMax->freeRecvPoolEntriesPerUpdate, - &pMin->freeRecvPoolEntriesPerUpdate, "freeRecvPoolEntriesPerUpdate")) - return FALSE; - - if ( !IsPowerOf2( pDst->numRecvPoolEntries ) ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("numRecvPoolEntries (%d) must be power of 2\n", - pDst->numRecvPoolEntries) ); - return FALSE; - } - if ( !IsPowerOf2( pDst->freeRecvPoolEntriesPerUpdate ) ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("freeRecvPoolEntriesPerUpdate (%d) must be power of 2\n", - pDst->freeRecvPoolEntriesPerUpdate) ); - return FALSE; - } - if ( pDst->freeRecvPoolEntriesPerUpdate >= pDst->numRecvPoolEntries ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("freeRecvPoolEntriesPerUpdate (%d) must be less than numRecvPoolEntries (%d)\n", - pDst->freeRecvPoolEntriesPerUpdate, pDst->numRecvPoolEntries) ); - return FALSE; - } - if ( pDst->numRecvPoolEntriesBeforeKick >= pDst->numRecvPoolEntries ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("numRecvPoolEntriesBeforeKick (%d) must be less than numRecvPoolEntries (%d)\n", - pDst->numRecvPoolEntriesBeforeKick, pDst->numRecvPoolEntries) ); - return FALSE; - } - - return TRUE; -} - -static void -__control_logControlPacket( - IN Inic_ControlPacket_t *pPkt ) -{ - char *type; - int i; - - switch( pPkt->hdr.pktType ) - { - case TYPE_INFO: - type = "TYPE_INFO"; - break; - case TYPE_REQ: - type = "TYPE_REQ"; - break; - case TYPE_RSP: - type = "TYPE_RSP"; - break; - case TYPE_ERR: - type = "TYPE_ERR"; - break; - default: - type = "UNKNOWN"; - } - switch( pPkt->hdr.pktCmd ) - { - case CMD_INIT_INIC: - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - ("ControlPacket: pktType = %s, pktCmd = CMD_INIT_INIC\n", type ) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" pktSeqNum = %u, pktRetryCount = %u\n", - pPkt->hdr.pktSeqNum, - pPkt->hdr.pktRetryCount) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" inicMajorVersion = %u, inicMinorVersion = %u\n", - ntoh16(pPkt->cmd.initInicReq.inicMajorVersion), - ntoh16(pPkt->cmd.initInicReq.inicMinorVersion)) ); - if (pPkt->hdr.pktType == TYPE_REQ) - { - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" inicInstance = %u, numDataPaths = %u\n", - pPkt->cmd.initInicReq.inicInstance, - pPkt->cmd.initInicReq.numDataPaths) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" numAddressEntries = %u\n", - ntoh16(pPkt->cmd.initInicReq.numAddressEntries)) ); - } - else - { - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" numLanSwitches = %u, numDataPaths = %u\n", - pPkt->cmd.initInicRsp.numLanSwitches, - pPkt->cmd.initInicRsp.numDataPaths) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" numAddressEntries = %u, featuresSupported = %08x\n", - ntoh16(pPkt->cmd.initInicRsp.numAddressEntries), - ntoh32(pPkt->cmd.initInicRsp.featuresSupported)) ); - if (pPkt->cmd.initInicRsp.numLanSwitches != 0) - { - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - ("lanSwitch[0] lanSwitchNum = %u, numEnetPorts = %08x\n", - pPkt->cmd.initInicRsp.lanSwitch[0].lanSwitchNum, - pPkt->cmd.initInicRsp.lanSwitch[0].numEnetPorts) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" defaultVlan = %u, hwMacAddress = %02x:%02x:%02x:%02x:%02x:%02x\n", - ntoh16(pPkt->cmd.initInicRsp.lanSwitch[0].defaultVlan), - pPkt->cmd.initInicRsp.lanSwitch[0].hwMacAddress[0], - pPkt->cmd.initInicRsp.lanSwitch[0].hwMacAddress[1], - pPkt->cmd.initInicRsp.lanSwitch[0].hwMacAddress[2], - pPkt->cmd.initInicRsp.lanSwitch[0].hwMacAddress[3], - pPkt->cmd.initInicRsp.lanSwitch[0].hwMacAddress[4], - pPkt->cmd.initInicRsp.lanSwitch[0].hwMacAddress[5]) ); - } - } - break; - case CMD_CONFIG_DATA_PATH: - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - ( "ControlPacket: pktType = %s, pktCmd = CMD_CONFIG_DATA_PATH\n", type) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" pktSeqNum = %u, pktRetryCount = %u\n", - pPkt->hdr.pktSeqNum, - pPkt->hdr.pktRetryCount) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" pathIdentifier = %"PRIx64", dataPath = %u\n", - pPkt->cmd.configDataPathReq.pathIdentifier, - pPkt->cmd.configDataPathReq.dataPath) ); - - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - ("Host Config sizeRecvPoolEntry = %u, numRecvPoolEntries = %u\n", - ntoh32(pPkt->cmd.configDataPathReq.hostRecvPoolConfig.sizeRecvPoolEntry), - ntoh32(pPkt->cmd.configDataPathReq.hostRecvPoolConfig.numRecvPoolEntries)) ); - - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" timeoutBeforeKick = %u, numRecvPoolEntriesBeforeKick = %u\n", - ntoh32(pPkt->cmd.configDataPathReq.hostRecvPoolConfig.timeoutBeforeKick), - ntoh32(pPkt->cmd.configDataPathReq.hostRecvPoolConfig.numRecvPoolEntriesBeforeKick)) ); - - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" numRecvPoolBytesBeforeKick = %u, freeRecvPoolEntriesPerUpdate = %u\n", - ntoh32(pPkt->cmd.configDataPathReq.hostRecvPoolConfig.numRecvPoolBytesBeforeKick), - ntoh32(pPkt->cmd.configDataPathReq.hostRecvPoolConfig.freeRecvPoolEntriesPerUpdate)) ); - - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - ("Eioc Config sizeRecvPoolEntry = %u, numRecvPoolEntries = %u\n", - ntoh32(pPkt->cmd.configDataPathReq.eiocRecvPoolConfig.sizeRecvPoolEntry), - ntoh32(pPkt->cmd.configDataPathReq.eiocRecvPoolConfig.numRecvPoolEntries)) ); - - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" timeoutBeforeKick = %u, numRecvPoolEntriesBeforeKick = %u\n", - ntoh32(pPkt->cmd.configDataPathReq.eiocRecvPoolConfig.timeoutBeforeKick), - ntoh32(pPkt->cmd.configDataPathReq.eiocRecvPoolConfig.numRecvPoolEntriesBeforeKick)) ); - - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" numRecvPoolBytesBeforeKick = %u, freeRecvPoolEntriesPerUpdate = %u\n", - ntoh32(pPkt->cmd.configDataPathReq.eiocRecvPoolConfig.numRecvPoolBytesBeforeKick), - ntoh32(pPkt->cmd.configDataPathReq.eiocRecvPoolConfig.freeRecvPoolEntriesPerUpdate)) ); - break; - case CMD_EXCHANGE_POOLS: - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - ("ControlPacket: pktType = %s, pktCmd = CMD_EXCHANGE_POOLS\n", type ) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" pktSeqNum = %u, pktRetryCount = %u\n", - pPkt->hdr.pktSeqNum, - pPkt->hdr.pktRetryCount) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" datapath = %u\n", - pPkt->cmd.exchangePoolsReq.dataPath) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" poolRKey = %08x poolAddr = %"PRIx64"\n", - ntoh32(pPkt->cmd.exchangePoolsReq.poolRKey), - ntoh64(pPkt->cmd.exchangePoolsReq.poolAddr)) ); - break; - case CMD_CONFIG_ADDRESSES: - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - ( "ControlPacket: pktType = %s, pktCmd = CMD_CONFIG_ADDRESSES\n", type ) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" pktSeqNum = %u, pktRetryCount = %u\n", - pPkt->hdr.pktSeqNum, - pPkt->hdr.pktRetryCount) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" numAddressOps = %x, lanSwitchNum = %d\n", - pPkt->cmd.configAddressesReq.numAddressOps, - pPkt->cmd.configAddressesReq.lanSwitchNum) ); - for (i = 0; ( i < pPkt->cmd.configAddressesReq.numAddressOps) && (i < 16); i++) - { - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" listAddressOps[%u].index = %u\n", - i, ntoh16(pPkt->cmd.configAddressesReq.listAddressOps[i].index)) ); - - switch(pPkt->cmd.configAddressesReq.listAddressOps[i].operation) - { - case INIC_OP_GET_ENTRY: - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" listAddressOps[%u].operation = INIC_OP_GET_ENTRY\n", i) ); - break; - case INIC_OP_SET_ENTRY: - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" listAddressOps[%u].operation = INIC_OP_SET_ENTRY\n", i) ); - break; - default: - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" listAddressOps[%u].operation = UNKNOWN(%d)\n", - i, pPkt->cmd.configAddressesReq.listAddressOps[i].operation) ); - break; - } - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" listAddressOps[%u].valid = %u\n", - i, pPkt->cmd.configAddressesReq.listAddressOps[i].valid) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" listAddressOps[%u].address = %02x:%02x:%02x:%02x:%02x:%02x\n", i, - pPkt->cmd.configAddressesReq.listAddressOps[i].address[0], - pPkt->cmd.configAddressesReq.listAddressOps[i].address[1], - pPkt->cmd.configAddressesReq.listAddressOps[i].address[2], - pPkt->cmd.configAddressesReq.listAddressOps[i].address[3], - pPkt->cmd.configAddressesReq.listAddressOps[i].address[4], - pPkt->cmd.configAddressesReq.listAddressOps[i].address[5]) ); - - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" listAddressOps[%u].vlan = %u\n", - i, ntoh16(pPkt->cmd.configAddressesReq.listAddressOps[i].vlan)) ); - } - break; - case CMD_CONFIG_LINK: - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - ("ControlPacket: pktType = %s, pktCmd = CMD_CONFIG_LINK\n", type) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" pktSeqNum = %u, pktRetryCount = %u\n", - pPkt->hdr.pktSeqNum, - pPkt->hdr.pktRetryCount) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" cmdFlags = %x\n", - pPkt->cmd.configLinkReq.cmdFlags) ); - - if ( pPkt->cmd.configLinkReq.cmdFlags & INIC_FLAG_ENABLE_NIC ) - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" INIC_FLAG_ENABLE_NIC\n") ); - - if ( pPkt->cmd.configLinkReq.cmdFlags & INIC_FLAG_DISABLE_NIC ) - - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" INIC_FLAG_DISABLE_NIC\n") ); - - if ( pPkt->cmd.configLinkReq.cmdFlags & INIC_FLAG_ENABLE_MCAST_ALL ) - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" INIC_FLAG_ENABLE_MCAST_ALL\n") ); - - if ( pPkt->cmd.configLinkReq.cmdFlags & INIC_FLAG_DISABLE_MCAST_ALL ) - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" INIC_FLAG_DISABLE_MCAST_ALL\n") ); - - if ( pPkt->cmd.configLinkReq.cmdFlags & INIC_FLAG_ENABLE_PROMISC ) - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" INIC_FLAG_ENABLE_PROMISC\n") ); - - if ( pPkt->cmd.configLinkReq.cmdFlags & INIC_FLAG_DISABLE_PROMISC ) - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" INIC_FLAG_DISABLE_PROMISC\n") ); - if ( pPkt->cmd.configLinkReq.cmdFlags & INIC_FLAG_SET_MTU ) - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" INIC_FLAG_SET_MTU\n") ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" lanSwitchNum = %x, mtuSize = %d\n", - pPkt->cmd.configLinkReq.lanSwitchNum, - ntoh16(pPkt->cmd.configLinkReq.mtuSize)) ); - if ( pPkt->hdr.pktType == TYPE_RSP ) - { - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" defaultVlan = %u, hwMacAddress = %02x:%02x:%02x:%02x:%02x:%02x\n", - ntoh16(pPkt->cmd.configLinkReq.defaultVlan), - pPkt->cmd.configLinkReq.hwMacAddress[0], - pPkt->cmd.configLinkReq.hwMacAddress[1], - pPkt->cmd.configLinkReq.hwMacAddress[2], - pPkt->cmd.configLinkReq.hwMacAddress[3], - pPkt->cmd.configLinkReq.hwMacAddress[4], - pPkt->cmd.configLinkReq.hwMacAddress[5]) ); - } - break; - case CMD_REPORT_STATISTICS: - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - ("ControlPacket: pktType = %s, pktCmd = CMD_REPORT_STATISTICS\n", type ) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" pktSeqNum = %u, pktRetryCount = %u\n", - pPkt->hdr.pktSeqNum, - pPkt->hdr.pktRetryCount) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" lanSwitchNum = %u\n", - pPkt->cmd.reportStatisticsReq.lanSwitchNum) ); - - if (pPkt->hdr.pktType == TYPE_REQ) - break; - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" ifInBroadcastPkts = %"PRIu64, - ntoh64(pPkt->cmd.reportStatisticsRsp.ifInBroadcastPkts)) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" ifInMulticastPkts = %"PRIu64"\n", - ntoh64(pPkt->cmd.reportStatisticsRsp.ifInMulticastPkts)) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" ifInOctets = %"PRIu64, - ntoh64(pPkt->cmd.reportStatisticsRsp.ifInOctets)) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" ifInUcastPkts = %"PRIu64"\n", - ntoh64(pPkt->cmd.reportStatisticsRsp.ifInUcastPkts)) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" ifInNUcastPkts = %"PRIu64, - ntoh64(pPkt->cmd.reportStatisticsRsp.ifInNUcastPkts)) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" ifInUnderrun = %"PRIu64"\n", - ntoh64(pPkt->cmd.reportStatisticsRsp.ifInUnderrun)) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" ifInErrors = %"PRIu64, - ntoh64(pPkt->cmd.reportStatisticsRsp.ifInErrors)) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" ifOutErrors = %"PRIu64"\n", - ntoh64(pPkt->cmd.reportStatisticsRsp.ifOutErrors)) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" ifOutOctets = %"PRIu64, - ntoh64(pPkt->cmd.reportStatisticsRsp.ifOutOctets)) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" ifOutUcastPkts = %"PRIu64"\n", - ntoh64(pPkt->cmd.reportStatisticsRsp.ifOutUcastPkts)) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" ifOutMulticastPkts = %"PRIu64, - ntoh64(pPkt->cmd.reportStatisticsRsp.ifOutMulticastPkts)) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" ifOutBroadcastPkts = %"PRIu64"\n", - ntoh64(pPkt->cmd.reportStatisticsRsp.ifOutBroadcastPkts)) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" ifOutNUcastPkts = %"PRIu64, - ntoh64(pPkt->cmd.reportStatisticsRsp.ifOutNUcastPkts)) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" ifOutOk = %"PRIu64"\n", - ntoh64(pPkt->cmd.reportStatisticsRsp.ifOutOk)) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" ifInOk = %"PRIu64, - ntoh64(pPkt->cmd.reportStatisticsRsp.ifInOk)) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" ifOutUcastBytes = %"PRIu64"\n", - ntoh64(pPkt->cmd.reportStatisticsRsp.ifOutUcastBytes)) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" ifOutMulticastBytes = %"PRIu64, - ntoh64(pPkt->cmd.reportStatisticsRsp.ifOutMulticastBytes)) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" ifOutBroadcastBytes = %"PRIu64"\n", - ntoh64(pPkt->cmd.reportStatisticsRsp.ifOutBroadcastBytes)) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" ifInUcastBytes = %"PRIu64, - ntoh64(pPkt->cmd.reportStatisticsRsp.ifInUcastBytes)) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" ifInMulticastBytes = %"PRIu64"\n", - ntoh64(pPkt->cmd.reportStatisticsRsp.ifInMulticastBytes)) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" ifInBroadcastBytes = %"PRIu64, - ntoh64(pPkt->cmd.reportStatisticsRsp.ifInBroadcastBytes)) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" ethernetStatus = %"PRIu64"\n", - ntoh64(pPkt->cmd.reportStatisticsRsp.ethernetStatus)) ); - break; - case CMD_CLEAR_STATISTICS: - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - ("ControlPacket: pktType = %s, pktCmd = CMD_CLEAR_STATISTICS\n", type ) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" pktSeqNum = %u, pktRetryCount = %u\n", - pPkt->hdr.pktSeqNum, - pPkt->hdr.pktRetryCount) ); - break; - case CMD_REPORT_STATUS: - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - ("ControlPacket: pktType = %s, pktCmd = CMD_REPORT_STATUS\n", - type) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" pktSeqNum = %u, pktRetryCount = %u\n", - pPkt->hdr.pktSeqNum, - pPkt->hdr.pktRetryCount) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" lanSwitchNum = %u, isFatal = %u\n", - pPkt->cmd.reportStatus.lanSwitchNum, - pPkt->cmd.reportStatus.isFatal) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" statusNumber = %u, statusInfo = %u\n", - ntoh32(pPkt->cmd.reportStatus.statusNumber), - ntoh32(pPkt->cmd.reportStatus.statusInfo)) ); - pPkt->cmd.reportStatus.fileName[31] = '\0'; - pPkt->cmd.reportStatus.routine[31] = '\0'; - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" filename = %s, routine = %s\n", - pPkt->cmd.reportStatus.fileName, - pPkt->cmd.reportStatus.routine) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" lineNum = %u, errorParameter = %u\n", - ntoh32(pPkt->cmd.reportStatus.lineNum), - ntoh32(pPkt->cmd.reportStatus.errorParameter)) ); - pPkt->cmd.reportStatus.descText[127] = '\0'; - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" descText = %s\n", - pPkt->cmd.reportStatus.descText) ); - break; - case CMD_RESET: - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - ("ControlPacket: pktType = %s, pktCmd = CMD_RESET\n", type ) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" pktSeqNum = %u, pktRetryCount = %u\n", - pPkt->hdr.pktSeqNum, - pPkt->hdr.pktRetryCount) ); - break; - case CMD_HEARTBEAT: - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - ("ControlPacket: pktType = %s, pktCmd = CMD_HEARTBEAT\n", type ) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" pktSeqNum = %u, pktRetryCount = %u\n", - pPkt->hdr.pktSeqNum, - pPkt->hdr.pktRetryCount) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" hbInterval = %d\n", - ntoh32(pPkt->cmd.heartbeatReq.hbInterval)) ); - break; - default: - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - ("ControlPacket: pktType = %s, pktCmd = UNKNOWN (%u)\n", - type,pPkt->hdr.pktCmd) ); - VNIC_PRINT( VNIC_DBG_CTRL_PKT, - (" pktSeqNum = %u, pktRetryCount = %u\n", - pPkt->hdr.pktSeqNum, - pPkt->hdr.pktRetryCount) ); - break; - } - return; -} diff --git a/trunk/ulp/qlc_vnic/kernel/vnic_control.h b/trunk/ulp/qlc_vnic/kernel/vnic_control.h deleted file mode 100644 index b18372bf..00000000 --- a/trunk/ulp/qlc_vnic/kernel/vnic_control.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (c) 2007 QLogic Corporation. All rights reserved. - * - * This software is available to you under the OpenIB.org BSD license - * below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * $Id$ - */ - -#ifndef _VNIC_CONTROL_H_ -#define _VNIC_CONTROL_H_ - -#include "vnic_controlpkt.h" -#include "vnic_util.h" - -typedef enum { - TIMER_IDLE, - TIMER_ACTIVE, - TIMER_EXPIRED -}timerstate_t; - -typedef struct Control { - struct _viport *p_viport; - struct ControlConfig *p_conf; - IbRegion_t region; - IbQp_t qp; - uint8_t *pLocalStorage; - uint16_t majVer; - uint16_t minVer; - Inic_LanSwitchAttributes_t lanSwitch; - SendIo_t sendIo; - RecvIo_t *pRecvIos; - - timerstate_t timerstate; - cl_timer_t timer; - uint8_t reqRetryCounter; - uint8_t seqNum; - uint32_t reqOutstanding; - uint32_t rspExpected; - RecvIo_t *pResponse; - RecvIo_t *pInfo; - LIST_ENTRY failureList; - KSPIN_LOCK ioLock; - -#ifdef VNIC_STATISTIC - struct { - uint64_t requestTime; /* Intermediate value */ - uint64_t responseTime; - uint32_t responseNum; - uint64_t responseMax; - uint64_t responseMin; - uint32_t timeoutNum; - } statistics; -#endif /* VNIC_STATISTIC */ -} Control_t; - -void -control_construct( - IN Control_t *pControl, - IN struct _viport *pViport ); - -ib_api_status_t control_init(Control_t *pControl, struct _viport *pViport, - struct ControlConfig *p_conf, uint64_t guid); -void control_cleanup(Control_t *pControl); -void control_processAsync(Control_t *pControl); -ib_api_status_t control_initInicReq(Control_t *pControl); -BOOLEAN control_initInicRsp(Control_t *pControl, uint32_t *pFeatures, - uint8_t *pMacAddress, uint16_t *pNumAddrs, uint16_t *pVlan); -ib_api_status_t control_configDataPathReq(Control_t *pControl, uint64_t pathId, - struct Inic_RecvPoolConfig *pHost, - struct Inic_RecvPoolConfig *pEioc); -BOOLEAN control_configDataPathRsp(Control_t *pControl, - struct Inic_RecvPoolConfig *pHost, - struct Inic_RecvPoolConfig *pEioc, - struct Inic_RecvPoolConfig *pMaxHost, - struct Inic_RecvPoolConfig *pMaxEioc, - struct Inic_RecvPoolConfig *pMinHost, - struct Inic_RecvPoolConfig *pMinEioc); -ib_api_status_t control_exchangePoolsReq(Control_t *pControl, uint64_t addr, uint32_t rkey); -BOOLEAN control_exchangePoolsRsp(Control_t *pControl, uint64_t *pAddr, - uint32_t *pRkey); -ib_api_status_t control_configLinkReq(Control_t *pControl, uint8_t flags, uint16_t mtu); -BOOLEAN control_configLinkRsp(Control_t *pControl, uint8_t *pFlags, uint16_t *pMtu); -ib_api_status_t control_configAddrsReq(Control_t *pControl, Inic_AddressOp_t *pAddrs, - uint16_t num, int32_t *pAddrQueryDone); -BOOLEAN control_configAddrsRsp(Control_t *pControl); -ib_api_status_t control_reportStatisticsReq(Control_t *pControl); -BOOLEAN control_reportStatisticsRsp(Control_t *pControl, - struct Inic_CmdReportStatisticsRsp *pStats); -ib_api_status_t control_resetReq( Control_t *pControl ); -BOOLEAN control_resetRsp(Control_t *pControl); -ib_api_status_t control_heartbeatReq(Control_t *pControl, uint32_t hbInterval); -BOOLEAN control_heartbeatRsp(Control_t *pControl); - -#define control_packet(pIo) (Inic_ControlPacket_t *)(LONG_PTR)((pIo)->dsList.vaddr ) -#define control_lastReq(pControl) control_packet(&(pControl)->sendIo) -#define control_features(pControl) (pControl)->featuresSupported -#define control_getMacAddress(pControl,addr) \ - memcpy(addr,(pControl)->lanSwitch.hwMacAddress,MAC_ADDR_LEN) - -#endif /* _VNIC_CONTROL_H_ */ diff --git a/trunk/ulp/qlc_vnic/kernel/vnic_controlpkt.h b/trunk/ulp/qlc_vnic/kernel/vnic_controlpkt.h deleted file mode 100644 index 12427267..00000000 --- a/trunk/ulp/qlc_vnic/kernel/vnic_controlpkt.h +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Copyright (c) 2007 QLogic Corporation. All rights reserved. - * - * This software is available to you under the OpenIB.org BSD license - * below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * $Id$ - */ - -#ifndef _VNIC_CONTROLPKT_H_ -#define _VNIC_CONTROLPKT_H_ - -#include -#define MAX_HOST_NAME_SIZE 64 - -typedef struct Inic_ConnectionData { - uint64_t pathId; - uint8_t inicInstance; - uint8_t pathNum; - uint8_t nodename[MAX_HOST_NAME_SIZE+1]; - uint8_t reserved; - uint32_t featuresSupported; -} Inic_ConnectionData_t; - -typedef struct Inic_ControlHeader { - uint8_t pktType; - uint8_t pktCmd; - uint8_t pktSeqNum; - uint8_t pktRetryCount; - uint32_t reserved; /* for 64-bit alignmnet */ -} Inic_ControlHeader_t; - -/* ptkType values */ -#define TYPE_INFO 0 -#define TYPE_REQ 1 -#define TYPE_RSP 2 -#define TYPE_ERR 3 - -/* ptkCmd values */ -#define CMD_INIT_INIC 1 -#define CMD_CONFIG_DATA_PATH 2 -#define CMD_EXCHANGE_POOLS 3 -#define CMD_CONFIG_ADDRESSES 4 -#define CMD_CONFIG_LINK 5 -#define CMD_REPORT_STATISTICS 6 -#define CMD_CLEAR_STATISTICS 7 -#define CMD_REPORT_STATUS 8 -#define CMD_RESET 9 -#define CMD_HEARTBEAT 10 - -#define MAC_ADDR_LEN HW_ADDR_LEN - -/* pktCmd CMD_INIT_INIC, pktType TYPE_REQ data format */ -typedef struct Inic_CmdInitInicReq { - uint16_t inicMajorVersion; - uint16_t inicMinorVersion; - uint8_t inicInstance; - uint8_t numDataPaths; - uint16_t numAddressEntries; -} Inic_CmdInitInicReq_t; - -/* pktCmd CMD_INIT_INIC, pktType TYPE_RSP subdata format */ -typedef struct Inic_LanSwitchAttributes { - uint8_t lanSwitchNum; - uint8_t numEnetPorts; - uint16_t defaultVlan; - uint8_t hwMacAddress[MAC_ADDR_LEN]; -} Inic_LanSwitchAttributes_t; - -/* pktCmd CMD_INIT_INIC, pktType TYPE_RSP data format */ -typedef struct Inic_CmdInitInicRsp { - uint16_t inicMajorVersion; - uint16_t inicMinorVersion; - uint8_t numLanSwitches; - uint8_t numDataPaths; - uint16_t numAddressEntries; - uint32_t featuresSupported; - Inic_LanSwitchAttributes_t lanSwitch[1]; -} Inic_CmdInitInicRsp_t; - -/* featuresSupported values */ -#define INIC_FEAT_IPV4_HEADERS 0x00000001 -#define INIC_FEAT_IPV6_HEADERS 0x00000002 -#define INIC_FEAT_IPV4_CSUM_RX 0x00000004 -#define INIC_FEAT_IPV4_CSUM_TX 0x00000008 -#define INIC_FEAT_TCP_CSUM_RX 0x00000010 -#define INIC_FEAT_TCP_CSUM_TX 0x00000020 -#define INIC_FEAT_UDP_CSUM_RX 0x00000040 -#define INIC_FEAT_UDP_CSUM_TX 0x00000080 -#define INIC_FEAT_TCP_SEGMENT 0x00000100 -#define INIC_FEAT_IPV4_IPSEC_OFFLOAD 0x00000200 -#define INIC_FEAT_IPV6_IPSEC_OFFLOAD 0x00000400 -#define INIC_FEAT_FCS_PROPAGATE 0x00000800 -#define INIC_FEAT_PF_KICK 0x00001000 -#define INIC_FEAT_PF_FORCE_ROUTE 0x00002000 -#define INIC_FEAT_CHASH_OFFLOAD 0x00004000 -#define INIC_FEAT_RDMA_IMMED 0x00008000 -#define INIC_FEAT_IGNORE_VLAN 0x00010000 -#define INIC_FEAT_INBOUND_IB_MC 0x00200000 - -/* pktCmd CMD_CONFIG_DATA_PATH subdata format */ -typedef struct Inic_RecvPoolConfig { - uint32_t sizeRecvPoolEntry; - uint32_t numRecvPoolEntries; - uint32_t timeoutBeforeKick; - uint32_t numRecvPoolEntriesBeforeKick; - uint32_t numRecvPoolBytesBeforeKick; - uint32_t freeRecvPoolEntriesPerUpdate; -} Inic_RecvPoolConfig_t; - -/* pktCmd CMD_CONFIG_DATA_PATH data format */ -typedef struct Inic_CmdConfigDataPath { - uint64_t pathIdentifier; - uint8_t dataPath; - uint8_t reserved[3]; - Inic_RecvPoolConfig_t hostRecvPoolConfig; - Inic_RecvPoolConfig_t eiocRecvPoolConfig; -} Inic_CmdConfigDataPath_t; - -/* pktCmd CMD_EXCHANGE_POOLS data format */ -typedef struct Inic_CmdExchangePools { - uint8_t dataPath; - uint8_t reserved[3]; - uint32_t poolRKey; - uint64_t poolAddr; -} Inic_CmdExchangePools_t; - -/* pktCmd CMD_CONFIG_ADDRESSES subdata format */ -typedef struct Inic_AddressOp { - uint16_t index; - uint8_t operation; - uint8_t valid; - uint8_t address[6]; - uint16_t vlan; -} Inic_AddressOp_t; - -/* operation values */ -#define INIC_OP_SET_ENTRY 0x01 -#define INIC_OP_GET_ENTRY 0x02 - -/* pktCmd CMD_CONFIG_ADDRESSES data format */ -typedef struct Inic_CmdConfigAddresses { - uint8_t numAddressOps; - uint8_t lanSwitchNum; - Inic_AddressOp_t listAddressOps[1]; -} Inic_CmdConfigAddresses_t; - -/* CMD_CONFIG_LINK data format */ -typedef struct Inic_CmdConfigLink { - uint8_t cmdFlags; - uint8_t lanSwitchNum; - uint16_t mtuSize; - uint16_t defaultVlan; - uint8_t hwMacAddress[6]; -} Inic_CmdConfigLink_t; - -/* cmdFlags values */ -#define INIC_FLAG_ENABLE_NIC 0x01 -#define INIC_FLAG_DISABLE_NIC 0x02 -#define INIC_FLAG_ENABLE_MCAST_ALL 0x04 -#define INIC_FLAG_DISABLE_MCAST_ALL 0x08 -#define INIC_FLAG_ENABLE_PROMISC 0x10 -#define INIC_FLAG_DISABLE_PROMISC 0x20 -#define INIC_FLAG_SET_MTU 0x40 - -/* pktCmd CMD_REPORT_STATISTICS, pktType TYPE_REQ data format */ -typedef struct Inic_CmdReportStatisticsReq { - uint8_t lanSwitchNum; -} Inic_CmdReportStatisticsReq_t; - -/* pktCmd CMD_REPORT_STATISTICS, pktType TYPE_RSP data format */ -typedef struct Inic_CmdReportStatisticsRsp { - uint8_t lanSwitchNum; - uint8_t reserved[7]; /* for 64-bit alignment */ - uint64_t ifInBroadcastPkts; - uint64_t ifInMulticastPkts; - uint64_t ifInOctets; - uint64_t ifInUcastPkts; - uint64_t ifInNUcastPkts; /* ifInBroadcastPkts + ifInMulticastPkts */ - uint64_t ifInUnderrun; /* (OID_GEN_RCV_NO_BUFFER) */ - uint64_t ifInErrors; /* (OID_GEN_RCV_ERROR) */ - uint64_t ifOutErrors; /* (OID_GEN_XMIT_ERROR) */ - uint64_t ifOutOctets; - uint64_t ifOutUcastPkts; - uint64_t ifOutMulticastPkts; - uint64_t ifOutBroadcastPkts; - uint64_t ifOutNUcastPkts; /* ifOutBroadcastPkts + ifOutMulticastPkts */ - uint64_t ifOutOk; /* ifOutNUcastPkts + ifOutUcastPkts (OID_GEN_XMIT_OK)*/ - uint64_t ifInOk; /* ifInNUcastPkts + ifInUcastPkts (OID_GEN_RCV_OK) */ - uint64_t ifOutUcastBytes; /* (OID_GEN_DIRECTED_BYTES_XMT) */ - uint64_t ifOutMulticastBytes; /* (OID_GEN_MULTICAST_BYTES_XMT) */ - uint64_t ifOutBroadcastBytes; /* (OID_GEN_BROADCAST_BYTES_XMT) */ - uint64_t ifInUcastBytes; /* (OID_GEN_DIRECTED_BYTES_RCV) */ - uint64_t ifInMulticastBytes; /* (OID_GEN_MULTICAST_BYTES_RCV) */ - uint64_t ifInBroadcastBytes; /* (OID_GEN_BROADCAST_BYTES_RCV) */ - uint64_t ethernetStatus; /* OID_GEN_MEDIA_CONNECT_STATUS) */ -} Inic_CmdReportStatisticsRsp_t; - -/* pktCmd CMD_CLEAR_STATISTICS data format */ -typedef struct Inic_CmdClearStatistics { - uint8_t lanSwitchNum; -} Inic_CmdClearStatistics_t; - -/* pktCmd CMD_REPORT_STATUS data format */ -typedef struct Inic_CmdReportStatus { - uint8_t lanSwitchNum; - uint8_t isFatal; - uint8_t reserved[2]; /* for 32-bit alignment */ - uint32_t statusNumber; - uint32_t statusInfo; - uint8_t fileName[32]; - uint8_t routine[32]; - uint32_t lineNum; - uint32_t errorParameter; - uint8_t descText[128]; -} Inic_CmdReportStatus_t; - -/* pktCmd CMD_HEARTBEAT data format */ -typedef struct Inic_CmdHeartbeat { - uint32_t hbInterval; -} Inic_CmdHeartbeat_t; - -#define INIC_STATUS_LINK_UP 1 -#define INIC_STATUS_LINK_DOWN 2 -#define INIC_STATUS_ENET_AGGREGATION_CHANGE 3 -#define INIC_STATUS_EIOC_SHUTDOWN 4 -#define INIC_STATUS_CONTROL_ERROR 5 -#define INIC_STATUS_EIOC_ERROR 6 - -#define INIC_MAX_CONTROLPKTSZ 256 -#define INIC_MAX_CONTROLDATASZ \ - (INIC_MAX_CONTROLPKTSZ - sizeof(Inic_ControlHeader_t)) - -typedef struct Inic_ControlPacket { - Inic_ControlHeader_t hdr; - union { - Inic_CmdInitInicReq_t initInicReq; - Inic_CmdInitInicRsp_t initInicRsp; - Inic_CmdConfigDataPath_t configDataPathReq; - Inic_CmdConfigDataPath_t configDataPathRsp; - Inic_CmdExchangePools_t exchangePoolsReq; - Inic_CmdExchangePools_t exchangePoolsRsp; - Inic_CmdConfigAddresses_t configAddressesReq; - Inic_CmdConfigAddresses_t configAddressesRsp; - Inic_CmdConfigLink_t configLinkReq; - Inic_CmdConfigLink_t configLinkRsp; - Inic_CmdReportStatisticsReq_t reportStatisticsReq; - Inic_CmdReportStatisticsRsp_t reportStatisticsRsp; - Inic_CmdClearStatistics_t clearStatisticsReq; - Inic_CmdClearStatistics_t clearStatisticsRsp; - Inic_CmdReportStatus_t reportStatus; - Inic_CmdHeartbeat_t heartbeatReq; - Inic_CmdHeartbeat_t heartbeatRsp; - char cmdData[INIC_MAX_CONTROLDATASZ]; - } cmd; -} Inic_ControlPacket_t; -/* -typedef struct _mac_addr -{ - uint8_t addr[MAC_ADDR_LEN]; -} PACK_SUFFIX mac_addr_t; -*/ -#include - -#endif /* _VNIC_CONTROLPKT_H_ */ diff --git a/trunk/ulp/qlc_vnic/kernel/vnic_data.c b/trunk/ulp/qlc_vnic/kernel/vnic_data.c deleted file mode 100644 index 4f39a643..00000000 --- a/trunk/ulp/qlc_vnic/kernel/vnic_data.c +++ /dev/null @@ -1,1459 +0,0 @@ -/* - * Copyright (c) 2007 QLogic Corporation. All rights reserved. - * - * This software is available to you under the OpenIB.org BSD license - * below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * $Id$ - */ -#include -#include "vnic_driver.h" - -static void data_postRecvs(Data_t *pData); -static void _data_receivedKick(Io_t *pIo); -static void _data_xmitComplete(Io_t *pIo); -static void data_sendKickMessage(Data_t *pData); -static void _data_kickTimeoutHandler( void *context ); -static BOOLEAN data_allocXmitBuffer(Data_t *pData, - BufferPoolEntry_t **ppBpe, RdmaIo_t **ppRdmaIo, BOOLEAN *pLast); -static void data_checkXmitBuffers(Data_t *pData); - -static -ib_api_status_t -data_rdmaPacket( - Data_t *pData, - BufferPoolEntry_t *pBpe, - RdmaIo_t *pRdmaIo ); -static -BOOLEAN -_data_recv_to_ndis_pkt( - Data_t *pData, - RdmaDest_t *pRdmaDest ); - -static void -_data_allocBuffers( - Data_t *pData, - BOOLEAN initialAllocation ); - -static void -_data_addFreeBuffer( - Data_t *pData, - int index, - RdmaDest_t *pRdmaDest ); - -static uint32_t -_data_incomingRecv( - Data_t *pData ); - -static void -_data_sendFreeRecvBuffers( - Data_t *pData ); - -static uint8_t -_tx_chksum_flags( - IN NDIS_PACKET* const p_packet ); - -static void -_data_return_recv( - IN NDIS_PACKET *p_packet ); - -static void -_data_kickTimer_start( - IN Data_t *pData, - IN uint32_t microseconds ); - -static void -_data_kickTimer_stop( - IN Data_t *pData ); - -#define LOCAL_IO(x) PTR64((x)) - -#define INBOUND_COPY - -#ifdef VNIC_STATISTIC -int64_t recvRef; -#endif /* VNIC_STATISTIC */ - -void -data_construct( - IN Data_t *pData, - IN viport_t *pViport ) -{ - VNIC_ENTER( VNIC_DBG_DATA ); - - RtlZeroMemory( pData, sizeof(*pData) ); - - pData->p_viport = pViport; - pData->p_phy_region = &pViport->p_adapter->ca.region; - InitializeListHead( &pData->recvIos ); - KeInitializeSpinLock( &pData->recvListLock ); - NdisAllocateSpinLock( &pData->recvIosLock ); - NdisAllocateSpinLock( &pData->xmitBufLock ); - cl_timer_construct( &pData->kickTimer ); - - ibqp_construct( &pData->qp, pViport ); - - VNIC_EXIT( VNIC_DBG_DATA ); -} - - -ib_api_status_t -data_init( - IN Data_t *pData, - IN DataConfig_t *p_conf, - IN uint64_t guid ) -{ - ib_api_status_t ib_status; - - VNIC_ENTER( VNIC_DBG_DATA ); - - ASSERT( pData->p_viport != NULL ); - pData->p_conf = p_conf; - - cl_timer_init( &pData->kickTimer, _data_kickTimeoutHandler, pData ); - - ib_status = ibqp_init(&pData->qp, guid, &p_conf->ibConfig ); - if( ib_status != IB_SUCCESS ) - VNIC_TRACE( VNIC_DBG_ERROR, ("data ibqp_init failed\n") ); - - VNIC_EXIT( VNIC_DBG_DATA ); - return ib_status; -} - - -ib_api_status_t -data_connect( - IN Data_t *pData ) -{ - NDIS_STATUS status; - ib_api_status_t ib_status; - XmitPool_t *pXmitPool = &pData->xmitPool; - RecvPool_t *pRecvPool = &pData->recvPool; - RecvIo_t *pRecvIo; - SendIo_t *pSendIo; - RdmaIo_t *pRdmaIo; - RdmaDest_t *pRdmaDest; - uint8_t *pRegionData; - int sz, regionSz; - unsigned int i, j; - - VNIC_ENTER( VNIC_DBG_DATA ); - - pRecvPool->poolSz = pData->p_conf->hostRecvPoolEntries; - pRecvPool->eiocPoolSz = pData->hostPoolParms.numRecvPoolEntries; - - if ( pRecvPool->poolSz > pRecvPool->eiocPoolSz ) - { - pRecvPool->poolSz = pData->hostPoolParms.numRecvPoolEntries; - } - pRecvPool->szFreeBundle = - pData->hostPoolParms.freeRecvPoolEntriesPerUpdate; - pRecvPool->numFreeBufs = 0; - pRecvPool->numPostedBufs = 0; - pRecvPool->nextFullBuf = 0; - pRecvPool->nextFreeBuf = 0; - pRecvPool->kickOnFree = FALSE; - pRecvPool->bufferSz = pData->hostPoolParms.sizeRecvPoolEntry; - - pXmitPool->bufferSz = pData->eiocPoolParms.sizeRecvPoolEntry; - pXmitPool->poolSz = pData->eiocPoolParms.numRecvPoolEntries; - pXmitPool->notifyCount = 0; - pXmitPool->notifyBundle = pData->p_conf->notifyBundle; - pXmitPool->nextXmitPool = 0; - -#if LIMIT_OUTSTANDING_SENDS - pXmitPool->numXmitBufs = pXmitPool->notifyBundle * 2; -#else /* !LIMIT_OUTSTANDING_SENDS */ - pXmitPool->numXmitBufs = pXmitPool->poolSz; -#endif /* LIMIT_OUTSTANDING_SENDS */ - - pXmitPool->nextXmitBuf = 0; - pXmitPool->lastCompBuf = pXmitPool->numXmitBufs - 1; - pXmitPool->kickCount = 0; - pXmitPool->kickByteCount = 0; - pXmitPool->sendKicks = - (BOOLEAN)(( pData->eiocPoolParms.numRecvPoolEntriesBeforeKick != 0 ) - || ( pData->eiocPoolParms.numRecvPoolBytesBeforeKick != 0 )); - pXmitPool->kickBundle = - pData->eiocPoolParms.numRecvPoolEntriesBeforeKick; - pXmitPool->kickByteBundle = - pData->eiocPoolParms.numRecvPoolBytesBeforeKick; - pXmitPool->needBuffers = TRUE; - - sz = sizeof(RdmaDest_t) * pRecvPool->poolSz; - sz += sizeof(RecvIo_t) * pData->p_conf->numRecvs; - sz += sizeof(RdmaIo_t) * pXmitPool->numXmitBufs; - - regionSz = 4 * pData->p_conf->numRecvs; - regionSz += sizeof(BufferPoolEntry_t) * pRecvPool->eiocPoolSz; - regionSz += sizeof(BufferPoolEntry_t) * pXmitPool->poolSz; - sz += regionSz; - - status = NdisAllocateMemoryWithTag( &pData->pLocalStorage, - (UINT)sz, - 'grtS' ); - if ( status != NDIS_STATUS_SUCCESS ) - { - VNIC_TRACE_EXIT( VNIC_DBG_ERROR, - ("Failed allocating %d bytes local storage\n", sz ) ); - ib_status = IB_INSUFFICIENT_MEMORY; - goto err1; - } - - NdisZeroMemory( pData->pLocalStorage, sz ); - pData->localStorageSz = sz; - - pRecvPool->pRecvBufs = (RdmaDest_t *)pData->pLocalStorage; - sz = sizeof(RdmaDest_t) * pRecvPool->poolSz; - pRecvIo = (RecvIo_t *)(pData->pLocalStorage + sz); - sz += sizeof(RecvIo_t) * pData->p_conf->numRecvs; - - pXmitPool->pXmitBufs = (RdmaIo_t *)(pData->pLocalStorage + sz); - sz += sizeof(RdmaIo_t) * pXmitPool->numXmitBufs; - - pRegionData = pData->pLocalStorage + sz; - sz += 4 * pData->p_conf->numRecvs; - - pRecvPool->bufPool = (BufferPoolEntry_t *)(pData->pLocalStorage + sz); - sz += sizeof(BufferPoolEntry_t) * pRecvPool->eiocPoolSz; - pXmitPool->bufPool = (BufferPoolEntry_t *)(pData->pLocalStorage + sz); - - ib_status = ibregion_init( pData->p_viport, &pData->region, - pData->p_viport->p_adapter->ca.hPd, pRegionData, regionSz, - ( IB_AC_LOCAL_WRITE | IB_AC_RDMA_WRITE ) ); - if( ib_status != IB_SUCCESS ) - { - VNIC_TRACE_EXIT( VNIC_DBG_ERROR, ("ib_region_init failed\n") ); - goto err2; - } - - pRdmaIo = &pData->freeBufsIo; - pRdmaIo->io.pViport = pData->p_viport; - pRdmaIo->io.pRoutine = NULL; - pRdmaIo->io.wrq.p_next = NULL; - pRdmaIo->io.wrq.wr_type = WR_RDMA_WRITE; - pRdmaIo->io.wrq.wr_id = PTR64( pRdmaIo ); - pRdmaIo->io.wrq.num_ds = 1; - pRdmaIo->io.wrq.ds_array = pRdmaIo->dsList; - pRdmaIo->dsList[0].lkey = pData->region.lkey; - pRdmaIo->io.wrq.send_opt = IB_SEND_OPT_SIGNALED; - - pSendIo = &pData->kickIo; - pSendIo->io.pViport = pData->p_viport; - pSendIo->io.pRoutine = NULL; - pSendIo->io.wrq.p_next = NULL; - pSendIo->io.wrq.wr_type = WR_SEND; - pSendIo->io.wrq.wr_id = PTR64( pSendIo ); - pSendIo->io.wrq.num_ds = 1; - pSendIo->io.wrq.ds_array = &pSendIo->dsList; - - pSendIo->io.wrq.send_opt = IB_SEND_OPT_SIGNALED; - - pSendIo->dsList.length = 0; - pSendIo->dsList.vaddr = PTR64( pRegionData ); - pSendIo->dsList.lkey = pData->region.lkey; - - for ( i = 0; i < pData->p_conf->numRecvs; i++ ) - { - pRecvIo[i].io.pViport = pData->p_viport; - pRecvIo[i].io.pRoutine = _data_receivedKick; - pRecvIo[i].io.r_wrq.wr_id = PTR64( &pRecvIo[i].io ); - pRecvIo[i].io.r_wrq.p_next = NULL; - pRecvIo[i].io.r_wrq.num_ds = 1; - pRecvIo[i].io.r_wrq.ds_array = &pRecvIo[i].dsList; - pRecvIo[i].dsList.length = 4; - pRecvIo[i].dsList.vaddr = PTR64( pRegionData ); - pRecvIo[i].dsList.lkey = pData->region.lkey; - - InitializeListHead( &pRecvIo[i].io.listPtrs ); - ExInterlockedInsertTailList( &pData->recvIos, &pRecvIo[i].io.listPtrs, &pData->recvListLock ); - /* Do not need to move pointer since the receive info - * is not read. Note, we could reduce the amount - * of memory allocated and the size of the region. - * pRegionData += 4; - * */ - } - - sz = pRecvPool->poolSz * pRecvPool->bufferSz; - status = NdisAllocateMemoryWithTag(&pData->p_recv_bufs, - sz, 'fubr'); - if( status != NDIS_STATUS_SUCCESS ) - { - VNIC_TRACE_EXIT( VNIC_DBG_ERROR, - ("Allocate recv buffers failed\n")); - ib_status = IB_INSUFFICIENT_MEMORY; - goto err3; - } - NdisZeroMemory( pData->p_recv_bufs, sz ); - - pData->recv_bufs_sz = sz; - - ib_status = ibregion_init( pData->p_viport, &pData->rbuf_region, - pData->p_viport->p_adapter->ca.hPd, pData->p_recv_bufs, sz, - (IB_AC_LOCAL_WRITE | IB_AC_RDMA_WRITE) ); - if( ib_status != IB_SUCCESS ) - { - goto err4; - } - - NdisAllocatePacketPool( &status, - &pData->h_recv_pkt_pool, - pRecvPool->poolSz, - PROTOCOL_RESERVED_SIZE_IN_PACKET ); - - if( status != NDIS_STATUS_SUCCESS ) - { - VNIC_TRACE_EXIT( VNIC_DBG_ERROR, - ("Allocate packet pool failed status %#x\n", status )); - ib_status = IB_INSUFFICIENT_MEMORY; - goto err5; - } - - NdisAllocateBufferPool( - &status, &pData->h_recv_buf_pool, pRecvPool->poolSz ); - - if( status != NDIS_STATUS_SUCCESS ) - { - VNIC_TRACE_EXIT( VNIC_DBG_ERROR, - ("Allocate packet pool failed status %#x\n", status )); - ib_status = IB_INSUFFICIENT_MEMORY; - goto err6; - } - pData->recvPool.recv_pkt_array = - cl_zalloc( sizeof(NDIS_PACKET*)* pRecvPool->poolSz ); - if( !pData->recvPool.recv_pkt_array ) - { - VNIC_TRACE_EXIT( VNIC_DBG_ERROR, - ("Allocate packet array failed\n" ) ); - ib_status = IB_INSUFFICIENT_MEMORY; - goto err7; - } - - InitializeListHead( &pRecvPool->availRecvBufs ); - - for ( i = 0; i < pRecvPool->poolSz; i++ ) - { - pRdmaDest = &pRecvPool->pRecvBufs[i]; - pRdmaDest->p_viport = pData->p_viport; - pRdmaDest->data = pData->p_recv_bufs + (i * pRecvPool->bufferSz ); - pRdmaDest->region = pData->rbuf_region; - InsertTailList( &pRecvPool->availRecvBufs, &pRdmaDest->listPtrs ); - } - - for ( i = 0; i < pXmitPool->numXmitBufs; i++ ) - { - pRdmaIo = &pXmitPool->pXmitBufs[i]; - pRdmaIo->index = (uint16_t)i; - pRdmaIo->io.pViport = pData->p_viport; - pRdmaIo->io.pRoutine = _data_xmitComplete; - pRdmaIo->io.wrq.p_next = NULL; - pRdmaIo->io.wrq.wr_type = WR_RDMA_WRITE; - pRdmaIo->io.wrq.wr_id = PTR64(pRdmaIo); - pRdmaIo->io.wrq.num_ds = MAX_NUM_SGE; // will set actual number when transmit - pRdmaIo->io.wrq.ds_array = pRdmaIo->dsList; - pRdmaIo->p_trailer = (ViportTrailer_t *)&pRdmaIo->data[0]; - for( j = 0; j < MAX_NUM_SGE; j++ ) - { - pRdmaIo->dsList[j].lkey = pData->p_phy_region->lkey; - } - } - - pXmitPool->rdmaRKey = pData->region.rkey; - pXmitPool->rdmaAddr = PTR64( pXmitPool->bufPool ); - - data_postRecvs( pData ); - - ib_status = ibqp_connect( &pData->qp ); - if( ib_status != IB_SUCCESS ) - { - VNIC_TRACE( VNIC_DBG_ERROR, ("ibqp_connect returned %s\n", - pData->p_viport->p_adapter->ifc.get_err_str( ib_status )) ); -err7: - NdisFreeBufferPool( pData->h_recv_buf_pool ); - pData->h_recv_buf_pool = NULL; -err6: - NdisFreePacketPool( pData->h_recv_pkt_pool ); - pData->h_recv_pkt_pool = NULL; -err5: - ibregion_cleanup( pData->p_viport, &pData->rbuf_region ); -err4: - NdisFreeMemory( pData->p_recv_bufs, pData->recv_bufs_sz, 0 ); - pData->p_recv_bufs = NULL; -err3: - ibregion_cleanup(pData->p_viport, &pData->region ); -err2: - NdisFreeMemory( pData->pLocalStorage, pData->localStorageSz, 0 ); - pData->pLocalStorage = NULL; -err1: - pRecvPool->poolSz = 0; - } - - VNIC_EXIT( VNIC_DBG_DATA ); - return ib_status; -} - - -ib_api_status_t -data_connected( - IN Data_t *pData ) -{ - VNIC_ENTER( VNIC_DBG_DATA ); - - pData->freeBufsIo.io.wrq.remote_ops.rkey = - pData->recvPool.eiocRdmaRkey; - - _data_allocBuffers(pData, TRUE); - _data_sendFreeRecvBuffers(pData); - - if( pData->p_viport->errored ) - { - return IB_ERROR; - } - - pData->connected = TRUE; - - VNIC_EXIT( VNIC_DBG_DATA ); - return IB_SUCCESS; -} - -void -data_disconnect( - IN Data_t *pData ) -{ - RecvPool_t *pRecvPool = &pData->recvPool; - viport_t *p_viport = pData->p_viport; - NDIS_PACKET *p_packet; - NDIS_BUFFER *p_buf; - unsigned int i; - - VNIC_ENTER( VNIC_DBG_DATA ); - - _data_kickTimer_stop ( pData ); - - pData->connected = FALSE; - - ibqp_detach( &pData->qp ); - - ibregion_cleanup( p_viport, &pData->rbuf_region ); - ibregion_cleanup( p_viport, &pData->region ); - - for ( i = 0; i < pRecvPool->poolSz; i++ ) - { - p_packet = pRecvPool->pRecvBufs[i].p_packet; - if ( p_packet != NULL ) - { - pRecvPool->pRecvBufs[i].p_packet = NULL; - NdisUnchainBufferAtFront( p_packet, &p_buf ); - if( p_buf ) - { - /* Return the NDIS packet and NDIS buffer to their pools. */ - NdisFreeBuffer( p_buf ); - } - NdisFreePacket( p_packet ); - } - } - - VNIC_EXIT( VNIC_DBG_DATA ); - return; -} - -BOOLEAN -data_xmitPacket( - IN Data_t *pData, - IN NDIS_PACKET* const p_packet ) -{ - XmitPool_t *p_xmitPool; - RdmaIo_t *pRdmaIo; - BufferPoolEntry_t *pBpe; - BOOLEAN last; - uint8_t *p_buf; - uint32_t buf_len; - uint32_t pkt_size; - NDIS_BUFFER *p_buf_desc; - eth_hdr_t* p_eth_hdr; - int pad; - SCATTER_GATHER_LIST *p_sgl; - uint32_t i; - PHYSICAL_ADDRESS phy_addr; - NDIS_PACKET_8021Q_INFO vlanInfo; - net16_t pri_vlan = 0; - - VNIC_ENTER( VNIC_DBG_DATA ); - - p_sgl = NDIS_PER_PACKET_INFO_FROM_PACKET( p_packet, - ScatterGatherListPacketInfo ); - if ( p_sgl == NULL ) - { - return FALSE; - } - - NdisGetFirstBufferFromPacketSafe( p_packet, - &p_buf_desc, - &p_buf, - &buf_len, - &pkt_size, - NormalPagePriority ); - - if( pkt_size > pData->xmitPool.bufferSz ) - { - VNIC_TRACE_EXIT( VNIC_DBG_ERROR, - ("Outbound packet too large, size = %d\n", pkt_size ) ); - return FALSE; - } - - if ( p_sgl->NumberOfElements > (ULONG)MAX_NUM_SGE - 1 ) - { - VNIC_TRACE( VNIC_DBG_DATA, - (" Xmit packet exceeded SGE limit - %d\n", - p_sgl->NumberOfElements ) ); - return FALSE; - } - - vlanInfo.Value = NDIS_PER_PACKET_INFO_FROM_PACKET( p_packet, Ieee8021QInfo ); - p_eth_hdr = (eth_hdr_t *)p_buf; - - if( vlanInfo.Value ) /* there is VLAN_ID specified the packet */ - { - if( vlanInfo.TagHeader.VlanId != 0 ) - { - /* packet vlanId does not match */ - if( pData->p_viport->p_adapter->vlan_info && - ( pData->p_viport->p_adapter->vlan_info & 0x00000fff ) != vlanInfo.TagHeader.VlanId ) - { - return FALSE; - } - pri_vlan = (uint16_t)vlanInfo.TagHeader.VlanId; - pri_vlan |= (uint16_t)( vlanInfo.TagHeader.UserPriority << 13 ); - } - else if( pData->p_viport->p_adapter->vlan_info ) - { - pri_vlan = (uint16_t)( pData->p_viport->p_adapter->vlan_info ); - } - } - else /* no VLAN_ID info in a packet */ - { - if( pData->p_viport->p_adapter->vlan_info ) - { - pri_vlan = (uint16_t)( pData->p_viport->p_adapter->vlan_info ); - } - } - - if( !data_allocXmitBuffer( pData, &pBpe, &pRdmaIo, &last ) ) - { - return FALSE; - } - - pRdmaIo->p_packet = p_packet; - pRdmaIo->packet_sz = pkt_size; - - pRdmaIo->len = (uint32_t)ROUNDUPP2( - max(MIN_PACKET_LEN, pRdmaIo->packet_sz), VIPORT_TRAILER_ALIGNMENT ); - pad = pRdmaIo->len - pRdmaIo->packet_sz; - - pRdmaIo->p_trailer = (ViportTrailer_t *)&pRdmaIo->data[pad]; - - cl_memclr( pRdmaIo->data, pad + sizeof( ViportTrailer_t ) ); - cl_memcpy( pRdmaIo->p_trailer->destMacAddr, p_eth_hdr->dst.addr, MAC_ADDR_LEN ); - - pRdmaIo->p_trailer->dataLength = - cl_hton16( (uint16_t)max( MIN_PACKET_LEN, pRdmaIo->packet_sz ) ); - - if( pri_vlan ) - { - /* if tagged frame */ - if( *(uint16_t *)(p_buf + 12 ) == ETH_PROT_VLAN_TAG ) - { - /* strip vlan tag from header */ - RtlMoveMemory( p_buf + 4, p_buf, 12 ); - /* adjust data length */ - pRdmaIo->p_trailer->dataLength = - cl_hton16( (uint16_t)max( MIN_PACKET_LEN, pRdmaIo->packet_sz ) - 4 ); - } - pRdmaIo->p_trailer->vLan = cl_hton16( pri_vlan ); - pRdmaIo->p_trailer->pktFlags |= PF_VLAN_INSERT; - } - - for( i=0; i < p_sgl->NumberOfElements; i++ ) - { - pRdmaIo->dsList[i].vaddr = p_sgl->Elements[i].Address.QuadPart; - pRdmaIo->dsList[i].length = p_sgl->Elements[i].Length; - } - if( viport_canTxCsum( pData->p_viport ) && - pData->p_viport->p_adapter->params.UseTxCsum ) - { - pRdmaIo->p_trailer->txChksumFlags = _tx_chksum_flags( p_packet ); - } - else - { - pRdmaIo->p_trailer->txChksumFlags = 0; - } - pRdmaIo->p_trailer->connectionHashAndValid = CHV_VALID; - - if( last ) - pRdmaIo->p_trailer->pktFlags |= PF_KICK; - - /* fill last data segment with trailer and pad */ - phy_addr = MmGetPhysicalAddress( pRdmaIo->data ); - - pRdmaIo->dsList[p_sgl->NumberOfElements].vaddr = phy_addr.QuadPart; - pRdmaIo->dsList[p_sgl->NumberOfElements].length = pRdmaIo->len - - pRdmaIo->packet_sz + - sizeof( ViportTrailer_t ); - - pRdmaIo->io.wrq.num_ds =p_sgl->NumberOfElements + 1; - - if( data_rdmaPacket( pData, pBpe, pRdmaIo ) != IB_SUCCESS ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("RDMA WRITE Failed\n")); - return FALSE; - } - p_xmitPool = &pData->xmitPool; - if( p_xmitPool->sendKicks ) - { - /* EIOC needs kicks to inform it of sent packets */ - - p_xmitPool->kickCount++; - p_xmitPool->kickByteCount += pRdmaIo->packet_sz; - if( ( p_xmitPool->kickCount >= p_xmitPool->kickBundle ) - || ( p_xmitPool->kickByteCount >= p_xmitPool->kickByteBundle ) ) - { - data_sendKickMessage( pData ); - } - else if( p_xmitPool->kickCount == 1 ) - { - _data_kickTimer_start( pData, pData->eiocPoolParms.timeoutBeforeKick ); - } - } - return TRUE; -} - -static uint8_t -_tx_chksum_flags( - IN NDIS_PACKET* const p_packet ) - -{ - NDIS_TCP_IP_CHECKSUM_PACKET_INFO *p_packet_info; - ULONG packet_info; - uint8_t txChksumFlags = 0; - - if( NDIS_PROTOCOL_ID_TCP_IP == NDIS_GET_PACKET_PROTOCOL_TYPE(p_packet) ) - { - packet_info = PtrToUlong( NDIS_PER_PACKET_INFO_FROM_PACKET( p_packet, TcpIpChecksumPacketInfo)); - p_packet_info = ( NDIS_TCP_IP_CHECKSUM_PACKET_INFO *)&packet_info; - - if( p_packet_info ) - { - if( p_packet_info->Transmit.NdisPacketChecksumV4 ) - { - txChksumFlags = TX_CHKSUM_FLAGS_CHECKSUM_V4 - | ( p_packet_info->Transmit.NdisPacketIpChecksum ? TX_CHKSUM_FLAGS_IP_CHECKSUM: 0 ) - | ( p_packet_info->Transmit.NdisPacketTcpChecksum ? TX_CHKSUM_FLAGS_TCP_CHECKSUM: 0 ) - | ( p_packet_info->Transmit.NdisPacketUdpChecksum ? TX_CHKSUM_FLAGS_UDP_CHECKSUM: 0 ); - } - else if( p_packet_info->Transmit.NdisPacketChecksumV6 ) - { - txChksumFlags = TX_CHKSUM_FLAGS_CHECKSUM_V6 - | ( p_packet_info->Transmit.NdisPacketIpChecksum ? TX_CHKSUM_FLAGS_IP_CHECKSUM: 0 ) - | ( p_packet_info->Transmit.NdisPacketTcpChecksum ? TX_CHKSUM_FLAGS_TCP_CHECKSUM: 0 ) - | ( p_packet_info->Transmit.NdisPacketUdpChecksum ? TX_CHKSUM_FLAGS_UDP_CHECKSUM: 0 ); - } - } - } - - VNIC_TRACE( VNIC_DBG_DATA , - ("txChksumFlags = %#x: V4 %c, V6 %c, IP %c, TCP %c, UDP %c\n", - txChksumFlags, - ((txChksumFlags & TX_CHKSUM_FLAGS_CHECKSUM_V4 )? '+': '-'), - ((txChksumFlags & TX_CHKSUM_FLAGS_CHECKSUM_V6 )? '+': '-'), - ((txChksumFlags & TX_CHKSUM_FLAGS_IP_CHECKSUM )? '+': '-'), - ((txChksumFlags & TX_CHKSUM_FLAGS_TCP_CHECKSUM )? '+': '-'), - ((txChksumFlags & TX_CHKSUM_FLAGS_UDP_CHECKSUM )? '+': '-') )); - - return txChksumFlags; -} - -static void -data_postRecvs( - IN Data_t *pData ) -{ - RecvIo_t *pRecvIo; - LIST_ENTRY *p_list_entry; - ib_api_status_t ib_status; - - VNIC_ENTER ( VNIC_DBG_DATA ); - - if( pData->p_viport->errored ) - return; - - while( ( p_list_entry = ExInterlockedRemoveHeadList( &pData->recvIos, &pData->recvListLock ) ) != NULL ) - { - pRecvIo = (RecvIo_t *)p_list_entry; - - ib_status = ibqp_postRecv( &pData->qp, &pRecvIo->io ); - if( ib_status != IB_SUCCESS ) - { - VNIC_TRACE_EXIT( VNIC_DBG_ERROR, ("ibqp_postRecv returned %s\n", - pData->p_viport->p_adapter->ifc.get_err_str( ib_status )) ); - viport_failure( pData->p_viport ); - return; - } - } - - VNIC_EXIT( VNIC_DBG_DATA ); - return; -} - -static void -_data_receivedKick( - IN Io_t *pIo ) -{ - - uint32_t num_pkts = 0; - - VNIC_ENTER( VNIC_DBG_DATA ); - - NdisAcquireSpinLock( &pIo->pViport->data.recvIosLock ); - -#ifdef VNIC_STATISTIC - recvRef = cl_get_tick_count(); -#endif /* VNIC_STATISTIC */ - - ExInterlockedInsertTailList( &pIo->pViport->data.recvIos, - &pIo->listPtrs, - &pIo->pViport->data.recvListLock ); - - data_postRecvs( &pIo->pViport->data ); - -#ifdef VNIC_STATISTIC - pIo->pViport->data.statistics.kickRecvs++; -#endif /* VNIC_STATISTIC */ - - data_checkXmitBuffers( &pIo->pViport->data ); - - num_pkts = _data_incomingRecv( &pIo->pViport->data ); - - NdisReleaseSpinLock(&pIo->pViport->data.recvIosLock ); - - if( num_pkts ) - { - viport_recvPacket( pIo->pViport, - pIo->pViport->data.recvPool.recv_pkt_array, - num_pkts ); - - pIo->pViport->stats.ifInOk += num_pkts; - } - - VNIC_EXIT( VNIC_DBG_DATA ); - return; -} - -static void -_data_xmitComplete( - IN Io_t *pIo ) -{ - - Data_t *pData; - XmitPool_t *p_xmitPool; - NDIS_PACKET *p_packet; - NDIS_STATUS ndis_status; - uint32_t io_index; - - VNIC_ENTER( VNIC_DBG_DATA ); - - NdisAcquireSpinLock( &pIo->pViport->data.xmitBufLock ); - - io_index = ((RdmaIo_t *)pIo)->index; - pData = &pIo->pViport->data; - p_xmitPool = &pData->xmitPool; - - while ( p_xmitPool->lastCompBuf != io_index ) - { - INC(p_xmitPool->lastCompBuf, 1, p_xmitPool->numXmitBufs); - - p_packet = p_xmitPool->pXmitBufs[p_xmitPool->lastCompBuf].p_packet; - - p_xmitPool->pXmitBufs[p_xmitPool->lastCompBuf].p_packet = NULL; - - if( p_packet != NULL ) - { - if( pIo->wc_status != IB_WCS_SUCCESS ) - { - ndis_status = NDIS_STATUS_FAILURE; - pIo->pViport->stats.ifOutErrors++; - pIo->wc_status = IB_WCS_SUCCESS; - } - else - { - ndis_status = NDIS_STATUS_SUCCESS; - pIo->pViport->stats.ifOutOk++; - } - NDIS_SET_PACKET_STATUS( p_packet, ndis_status ); - NdisMSendComplete( pIo->pViport->p_adapter->h_handle, - p_packet, ndis_status ); - } - } - NdisReleaseSpinLock( &pData->xmitBufLock ); - - if( !pData->p_viport->errored ) - { - data_checkXmitBuffers( pData ); - } - VNIC_EXIT( VNIC_DBG_DATA ); - return; -} - -static void -data_sendKickMessage( - IN Data_t *pData ) -{ - XmitPool_t *pPool = &pData->xmitPool; - - VNIC_ENTER( VNIC_DBG_DATA ); - - /* stop timer for BundleTimeout */ - _data_kickTimer_stop( pData ); - - pPool->kickCount = 0; - pPool->kickByteCount = 0; - - /* TBD: Keep track of when kick is outstanding, and - * don't reuse until complete - */ - if ( ibqp_postSend( &pData->qp, &pData->kickIo.io ) != IB_SUCCESS ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("Unable to send kick to EIOC\n") ); - viport_failure( pData->p_viport ); - } - - VNIC_EXIT( VNIC_DBG_DATA ); -} - -static void -_data_kickTimeoutHandler( void * context ) -{ - Data_t* pData = (Data_t *)context; - - VNIC_ENTER( VNIC_DBG_DATA ); - - InterlockedExchange( &pData->kickTimerOn, FALSE ); - data_sendKickMessage( pData ); - - VNIC_EXIT( VNIC_DBG_DATA ); - - return; -} - -static BOOLEAN -data_allocXmitBuffer( - IN Data_t *pData, - OUT BufferPoolEntry_t **ppBpe, - OUT RdmaIo_t **ppRdmaIo, - OUT BOOLEAN *pLast ) -{ - XmitPool_t *p_xmitPool; - - VNIC_ENTER( VNIC_DBG_DATA ); - - NdisAcquireSpinLock( &pData->xmitBufLock ); - - p_xmitPool = &pData->xmitPool; - *pLast = FALSE; - *ppRdmaIo = &p_xmitPool->pXmitBufs[p_xmitPool->nextXmitBuf]; - *ppBpe = &p_xmitPool->bufPool[p_xmitPool->nextXmitPool]; - - if ( (*ppBpe)->valid && p_xmitPool->nextXmitBuf != p_xmitPool->lastCompBuf ) - { - INC(p_xmitPool->nextXmitBuf, 1, p_xmitPool->numXmitBufs); - INC(p_xmitPool->nextXmitPool, 1, p_xmitPool->poolSz); - - if ( !p_xmitPool->bufPool[p_xmitPool->nextXmitPool].valid ) - { - VNIC_TRACE( VNIC_DBG_DATA, - ("Just used the last EIOU receive buffer\n") ); - - *pLast = TRUE; - p_xmitPool->needBuffers = TRUE; - viport_stopXmit( pData->p_viport ); -#ifdef VNIC_STATISTIC - pData->statistics.kickReqs++; -#endif /* VNIC_STATISTIC */ - } - else if ( p_xmitPool->nextXmitBuf == p_xmitPool->lastCompBuf ) - { - VNIC_TRACE( VNIC_DBG_DATA, - ("Just used our last xmit buffer\n") ); - - p_xmitPool->needBuffers = TRUE; - viport_stopXmit( pData->p_viport ); - } - - (*ppBpe)->valid = 0; - - NdisReleaseSpinLock( &pData->xmitBufLock ); - return TRUE; - } - else - { -#ifdef VNIC_STATISTIC - pData->statistics.noXmitBufs++; -#endif /* VNIC_STATISTIC */ - - VNIC_TRACE( VNIC_DBG_ERROR, - ("Out of xmit buffers\n") ); - - viport_stopXmit( pData->p_viport ); - - NdisReleaseSpinLock( &pData->xmitBufLock ); - return FALSE; - } -} - -static void -data_checkXmitBuffers( - IN Data_t *pData ) -{ - VNIC_ENTER( VNIC_DBG_DATA ); - - NdisAcquireSpinLock( &pData->xmitBufLock ); - - if ( pData->xmitPool.needBuffers - && pData->xmitPool.bufPool[pData->xmitPool.nextXmitPool].valid - && pData->xmitPool.nextXmitBuf != pData->xmitPool.lastCompBuf ) - { - pData->xmitPool.needBuffers = FALSE; - viport_restartXmit( pData->p_viport ); - - VNIC_TRACE( VNIC_DBG_DATA, - ("There are free xmit buffers\n") ); - } - - NdisReleaseSpinLock( &pData->xmitBufLock ); - - VNIC_EXIT( VNIC_DBG_DATA ); - return; -} - -static -ib_api_status_t -data_rdmaPacket( - IN Data_t *pData, - IN BufferPoolEntry_t *pBpe, - IN RdmaIo_t *pRdmaIo ) -{ - ib_send_wr_t *pWrq; - uint64_t remote_addr; - - VNIC_ENTER( VNIC_DBG_DATA ); - - pWrq = &pRdmaIo->io.wrq; - - remote_addr = ntoh64( pBpe->remoteAddr ); - remote_addr += pData->xmitPool.bufferSz; - remote_addr -= ( pRdmaIo->len + sizeof(ViportTrailer_t) ); - - pWrq->remote_ops.vaddr = remote_addr; - pWrq->remote_ops.rkey = pBpe->rKey; - - pData->xmitPool.notifyCount++; - - if( pData->xmitPool.notifyCount >= pData->xmitPool.notifyBundle ) - { - pData->xmitPool.notifyCount = 0; - pWrq->send_opt = IB_SEND_OPT_SIGNALED; - } - else - { - pWrq->send_opt &= ~IB_SEND_OPT_SIGNALED; - } - pWrq->send_opt = IB_SEND_OPT_SIGNALED; - - if( pData->p_viport->featuresSupported & INIC_FEAT_RDMA_IMMED ) - { - pWrq->send_opt |= IB_SEND_OPT_IMMEDIATE; - pWrq->immediate_data = 0; - } - - if( ibqp_postSend( &pData->qp, &pRdmaIo->io ) != IB_SUCCESS ) - { - VNIC_TRACE(VNIC_DBG_ERROR, - ("Failed sending data to EIOC\n") ); - return IB_ERROR; - } -#ifdef VNIC_STATISTIC - pData->statistics.xmitNum++; -#endif /* VNIC_STATISTIC */ - - VNIC_EXIT( VNIC_DBG_DATA ); - return IB_SUCCESS; -} - -static BOOLEAN -_data_recv_to_ndis_pkt( - IN Data_t *pData, - IN RdmaDest_t *pRdmaDest ) -{ - struct ViportTrailer *pTrailer; - NDIS_PACKET *p_packet; - NDIS_STATUS ndis_status; - int start; - unsigned int len; - NDIS_TCP_IP_CHECKSUM_PACKET_INFO packet_info; - NDIS_PACKET_8021Q_INFO vlan_info; - uint16_t vlanId; - uint8_t rxChksumFlags; - - VNIC_ENTER( VNIC_DBG_DATA ); - - pTrailer = pRdmaDest->pTrailer; - p_packet = pRdmaDest->p_packet; - - start = (int)data_offset(pData, pTrailer); - len = data_len(pData, pTrailer); - - NdisAllocateBuffer( &ndis_status, - &pRdmaDest->p_buf, - pData->h_recv_buf_pool, - pRdmaDest->data + start, - len ); - - if ( ndis_status != NDIS_STATUS_SUCCESS ) - { - VNIC_TRACE_EXIT( VNIC_DBG_ERROR, - ( "NdisAllocateBuffer failed %#x\n", ndis_status ) ); - return FALSE; - } - - NdisChainBufferAtFront( p_packet, pRdmaDest->p_buf ); - pRdmaDest->buf_sz = len; - - if ( pTrailer->pktFlags & PF_VLAN_INSERT && - !( pData->p_viport->featuresSupported & INIC_FEAT_IGNORE_VLAN ) ) - { - /* handle VLAN tag insertion */ - vlan_info.Value = NDIS_PER_PACKET_INFO_FROM_PACKET( p_packet, Ieee8021QInfo ); - vlanId = cl_ntoh16( pTrailer->vLan ); - - if( !( vlanId & 0xfff ) || - ( ( (vlanId & 0xfff ) != 0 ) && - (vlanId & 0xfff ) == ((uint16_t)pData->p_viport->p_adapter->vlan_info & 0xfff ) )) - { - if( pTrailer->pktFlags & PF_PVID_OVERRIDDEN ) - { - vlan_info.TagHeader.VlanId = 0; - } - else - { - vlan_info.TagHeader.VlanId = vlanId & 0xfff; - } - vlan_info.TagHeader.UserPriority = vlanId & 0xe000; - vlan_info.TagHeader.CanonicalFormatId = 0; - vlan_info.TagHeader.Reserved = 0; - NDIS_PER_PACKET_INFO_FROM_PACKET( p_packet, Ieee8021QInfo ) = vlan_info.Value; - } - } - - if( viport_canRxCsum( pData->p_viport ) && - pData->p_viport->p_adapter->params.UseRxCsum ) - { - rxChksumFlags = pTrailer->rxChksumFlags; - - VNIC_TRACE( VNIC_DBG_DATA, - ("rxChksumFlags = %#x, LOOP = %c, IP = %c, TCP = %c, UDP = %c\n", - rxChksumFlags, - (rxChksumFlags & RX_CHKSUM_FLAGS_LOOPBACK)? 'Y': 'N', - (rxChksumFlags & RX_CHKSUM_FLAGS_IP_CHECKSUM_SUCCEEDED)? 'Y': - (rxChksumFlags & RX_CHKSUM_FLAGS_IP_CHECKSUM_FAILED)? 'N': '-', - (rxChksumFlags & RX_CHKSUM_FLAGS_TCP_CHECKSUM_SUCCEEDED)? 'Y': - (rxChksumFlags & RX_CHKSUM_FLAGS_TCP_CHECKSUM_FAILED)? 'N': '-', - (rxChksumFlags & RX_CHKSUM_FLAGS_UDP_CHECKSUM_SUCCEEDED)? 'Y': - (rxChksumFlags & RX_CHKSUM_FLAGS_UDP_CHECKSUM_FAILED)? 'N': '-') ); - - packet_info.Value = 0; - - if( rxChksumFlags & RX_CHKSUM_FLAGS_IP_CHECKSUM_SUCCEEDED ) - packet_info.Receive.NdisPacketIpChecksumSucceeded = TRUE; - else if( rxChksumFlags & RX_CHKSUM_FLAGS_IP_CHECKSUM_FAILED ) - packet_info.Receive.NdisPacketIpChecksumFailed = TRUE; - - if( rxChksumFlags & RX_CHKSUM_FLAGS_TCP_CHECKSUM_SUCCEEDED ) - packet_info.Receive.NdisPacketTcpChecksumSucceeded = TRUE; - else if( rxChksumFlags & RX_CHKSUM_FLAGS_TCP_CHECKSUM_FAILED ) - packet_info.Receive.NdisPacketTcpChecksumFailed = TRUE; - - if( rxChksumFlags & RX_CHKSUM_FLAGS_TCP_CHECKSUM_SUCCEEDED ) - packet_info.Receive.NdisPacketUdpChecksumSucceeded = TRUE; - else if( rxChksumFlags & RX_CHKSUM_FLAGS_TCP_CHECKSUM_FAILED ) - packet_info.Receive.NdisPacketUdpChecksumFailed = TRUE; - - NDIS_PER_PACKET_INFO_FROM_PACKET( p_packet, TcpIpChecksumPacketInfo )= - (void *)(uintn_t)packet_info.Value; - } - - NDIS_SET_PACKET_STATUS( p_packet, NDIS_STATUS_SUCCESS ); - NDIS_SET_PACKET_HEADER_SIZE( p_packet, sizeof(eth_hdr_t) ); - VNIC_RECV_FROM_PACKET( p_packet ) = pRdmaDest; - - VNIC_EXIT( VNIC_DBG_DATA ); - return TRUE; -} - -/* NOTE: This routine is not reentrant */ -static void -_data_allocBuffers( - IN Data_t *pData, - IN BOOLEAN initialAllocation ) -{ - NDIS_STATUS ndis_status; - RecvPool_t *p_recvPool = &pData->recvPool; - RdmaDest_t *pRdmaDest; - LIST_ENTRY *p_list_entry; - int index; - - VNIC_ENTER( VNIC_DBG_DATA ); - - index = ADD(p_recvPool->nextFreeBuf, p_recvPool->numFreeBufs, p_recvPool->eiocPoolSz); - - while ( !IsListEmpty( &p_recvPool->availRecvBufs ) ) - { - p_list_entry = RemoveHeadList( &p_recvPool->availRecvBufs ); - pRdmaDest = (RdmaDest_t*)p_list_entry; - - if( initialAllocation ) - { - pRdmaDest->buf_sz = p_recvPool->bufferSz; - pRdmaDest->pTrailer = - (struct ViportTrailer*)(pRdmaDest->data + pRdmaDest->buf_sz - - sizeof(struct ViportTrailer)); - pRdmaDest->pTrailer->connectionHashAndValid = 0; - - NdisAllocatePacket( &ndis_status, - &pRdmaDest->p_packet, - pData->h_recv_pkt_pool ); - - if ( ndis_status != NDIS_STATUS_SUCCESS ) - { - VNIC_TRACE_EXIT( VNIC_DBG_ERROR, - ( "NdisAllocatePacket failed %#x\n", ndis_status ) ); - return; - } - } - - _data_addFreeBuffer( pData, index, pRdmaDest ); - index = NEXT(index,p_recvPool->eiocPoolSz); - } - - VNIC_EXIT( VNIC_DBG_DATA ); - return; -} - -static void -_data_addFreeBuffer( - IN Data_t *pData, - IN int index, - IN RdmaDest_t *pRdmaDest ) -{ - RecvPool_t *p_recvPool = &pData->recvPool; - BufferPoolEntry_t *pBpe; - - pRdmaDest->pTrailer->connectionHashAndValid = 0; - pBpe = &p_recvPool->bufPool[index]; - - pBpe->rKey = pRdmaDest->region.rkey; - pBpe->remoteAddr = hton64( PTR64( pRdmaDest->data ) ); - pBpe->valid = (uint32_t)(pRdmaDest - &p_recvPool->pRecvBufs[0]) + 1; - ++p_recvPool->numFreeBufs; - - return; -} - -static uint32_t -_data_incomingRecv( - IN Data_t *pData ) -{ - RecvPool_t *p_recvPool = &pData->recvPool; - RdmaDest_t *pRdmaDest; - ViportTrailer_t *pTrailer; - BufferPoolEntry_t *pBpe; - uint32_t idx = 0; - BOOLEAN status = FALSE; - - VNIC_ENTER( VNIC_DBG_DATA ); - - while( !status ) - { - if ( p_recvPool->nextFullBuf == p_recvPool->nextFreeBuf ) - return idx; - - pBpe = &p_recvPool->bufPool[p_recvPool->nextFullBuf]; - - CL_ASSERT(pBpe->valid != 0 ); - - pRdmaDest = &p_recvPool->pRecvBufs[pBpe->valid - 1]; - pTrailer = pRdmaDest->pTrailer; - - if ( ( pTrailer != NULL ) && - ( pTrailer->connectionHashAndValid & CHV_VALID ) ) - { - /* received a packet */ - if ( pTrailer->pktFlags & PF_KICK ) - { - p_recvPool->kickOnFree = TRUE; - } - /* we do not want to indicate packet if filter is not set */ - if( pData->p_viport->p_adapter->xmitStarted && - pData->p_viport->p_adapter->packet_filter && - p_recvPool->numPostedBufs > 0 ) - { - if ( _data_recv_to_ndis_pkt( pData, pRdmaDest ) ) - { - p_recvPool->recv_pkt_array[idx++] = pRdmaDest->p_packet; - } - } - else - { /* put back to free buffers pool */ - InsertTailList( &p_recvPool->availRecvBufs, - &pRdmaDest->listPtrs ); - } - pBpe->valid = 0; - INC( p_recvPool->nextFullBuf, 1, p_recvPool->eiocPoolSz ); - p_recvPool->numPostedBufs--; -#ifdef VNIC_STATISTIC - pData->statistics.recvNum++; -#endif /* VNIC_STATISTIC */ - } - else - break; - } - return idx; -} - - -void -vnic_return_packet( - IN NDIS_HANDLE adapter_context, - IN NDIS_PACKET * const p_packet ) -{ - - RdmaDest_t *p_rdma_dest; - viport_t *p_viport; - - VNIC_ENTER( VNIC_DBG_DATA ); - - UNREFERENCED_PARAMETER( adapter_context ); - - p_rdma_dest = VNIC_RECV_FROM_PACKET( p_packet ); - p_viport = p_rdma_dest->p_viport; - - ASSERT( p_rdma_dest->p_packet == p_packet ); - - NdisAcquireSpinLock( &p_viport->data.recvIosLock ); - - _data_return_recv( p_packet ); - - NdisReinitializePacket( p_packet ); - - InsertTailList( &p_viport->data.recvPool.availRecvBufs, - &p_rdma_dest->listPtrs ); - _data_allocBuffers( &p_viport->data, FALSE ); - _data_sendFreeRecvBuffers( &p_viport->data ); - - NdisReleaseSpinLock(&p_viport->data.recvIosLock ); - - VNIC_EXIT( VNIC_DBG_DATA ); -} -static void -_data_return_recv( - IN NDIS_PACKET *p_packet ) -{ - NDIS_BUFFER *p_buf; - PNDIS_PACKET_OOB_DATA p_oob_data; - - /* Unchain the NDIS buffer. */ - NdisUnchainBufferAtFront( p_packet, &p_buf ); - if( p_buf ) - { - /* Return the NDIS packet and NDIS buffer to their pools. */ - NdisFreeBuffer( p_buf ); - } - /* take care of OOB_DATA block since NdisReinitializePacket doesn't */ - p_oob_data = NDIS_OOB_DATA_FROM_PACKET( p_packet ); - NdisZeroMemory( p_oob_data, sizeof( NDIS_PACKET_OOB_DATA )); -} - -static void -_data_sendFreeRecvBuffers( - IN Data_t *pData ) -{ - RecvPool_t *p_recvPool = &pData->recvPool; - ib_send_wr_t *pWrq = &pData->freeBufsIo.io.wrq; - BOOLEAN bufsSent = FALSE; - uint64_t rdmaAddr; - uint32_t offset; - uint32_t sz; - unsigned int numToSend, - nextIncrement; - - VNIC_ENTER( VNIC_DBG_DATA ); - - for ( numToSend = p_recvPool->szFreeBundle; - numToSend <= p_recvPool->numFreeBufs; - numToSend += p_recvPool->szFreeBundle ) - { - - /* Handle multiple bundles as one when possible. */ - nextIncrement = numToSend + p_recvPool->szFreeBundle; - if (( nextIncrement <= p_recvPool->numFreeBufs ) - && ( p_recvPool->nextFreeBuf + nextIncrement <= p_recvPool->eiocPoolSz ) ) - { - continue; - } - - offset = p_recvPool->nextFreeBuf * sizeof(BufferPoolEntry_t); - sz = numToSend * sizeof(BufferPoolEntry_t); - rdmaAddr = p_recvPool->eiocRdmaAddr + offset; - - pWrq->ds_array->length = sz; - pWrq->ds_array->vaddr = PTR64((uint8_t *)p_recvPool->bufPool + offset); - pWrq->remote_ops.vaddr = rdmaAddr; - - if ( ibqp_postSend( &pData->qp, &pData->freeBufsIo.io ) != IB_SUCCESS ) - { - VNIC_TRACE(VNIC_DBG_ERROR, - ("Unable to rdma free buffers to EIOC\n") ); - - viport_failure( pData->p_viport ); - break; - } - - INC( p_recvPool->nextFreeBuf, numToSend, p_recvPool->eiocPoolSz ); - p_recvPool->numFreeBufs -= numToSend; - p_recvPool->numPostedBufs += numToSend; - bufsSent = TRUE; - } - - if( bufsSent ) - { - if( p_recvPool->kickOnFree ) - { - data_sendKickMessage( pData ); - } - } - if( p_recvPool->numPostedBufs == 0 ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("IOC %d: Unable to allocate receive buffers NumFreeBufs: %d nextFreeBuf: %d nextFullBuf %d eiocPoolSz: %d\n", - pData->p_viport->ioc_num, p_recvPool->numFreeBufs, - p_recvPool->nextFreeBuf, p_recvPool->nextFullBuf, - p_recvPool->eiocPoolSz ) ); - - //viport_failure( pData->p_viport ); - } - VNIC_EXIT( VNIC_DBG_DATA ); -} - - -void -data_cleanup( - IN Data_t *pData ) -{ - VNIC_ENTER( VNIC_DBG_DATA ); - - VNIC_TRACE(VNIC_DBG_DATA, - ("IOC[%d]data cleanup\n", pData->p_viport->ioc_num )); - - if( pData->p_recv_bufs ) - { - NdisFreeMemory( pData->p_recv_bufs, pData->recv_bufs_sz, 0 ); - pData->p_recv_bufs = NULL; - } - - if( pData->recvPool.recv_pkt_array ) - { - cl_free( pData->recvPool.recv_pkt_array ); - pData->recvPool.recv_pkt_array = NULL; - pData->recvPool.poolSz = 0; - } - - if ( pData->pLocalStorage ) - { - NdisFreeMemory( pData->pLocalStorage, pData->localStorageSz, 0 ); - pData->pLocalStorage = NULL; - } - - if( pData->h_recv_buf_pool ) - { - NdisFreeBufferPool( pData->h_recv_buf_pool ); - pData->h_recv_buf_pool = NULL; - } - - if ( pData->h_recv_pkt_pool ) - { - if( NdisPacketPoolUsage(pData->h_recv_pkt_pool) != 0) - { - VNIC_TRACE( VNIC_DBG_WARN, - ("Recv packet pool is not empty!!!\n") ); - } - NdisFreePacketPool( pData->h_recv_pkt_pool ); - pData->h_recv_pkt_pool = NULL; - } - // clear Qp struct for reuse - cl_memclr( &pData->qp, sizeof( IbQp_t) ); - - cl_timer_destroy( &pData->kickTimer ); - - VNIC_EXIT( VNIC_DBG_DATA ); -} - - -static void -_data_kickTimer_start( - IN Data_t *pData, - IN uint32_t microseconds ) -{ - VNIC_ENTER( VNIC_DBG_DATA ); - - InterlockedExchange( (LONG *)&pData->kickTimerOn, TRUE ); - - usec_timer_start(&pData->kickTimer, microseconds ); - - VNIC_EXIT( VNIC_DBG_DATA ); - return; -} - -static void -_data_kickTimer_stop( - IN Data_t *pData ) -{ - VNIC_ENTER( VNIC_DBG_DATA ); - - if( InterlockedExchange( &pData->kickTimerOn, FALSE ) == TRUE ) - { - cl_timer_stop( &pData->kickTimer ); - } - - VNIC_EXIT( VNIC_DBG_DATA ); -} diff --git a/trunk/ulp/qlc_vnic/kernel/vnic_data.h b/trunk/ulp/qlc_vnic/kernel/vnic_data.h deleted file mode 100644 index 14bc0c1b..00000000 --- a/trunk/ulp/qlc_vnic/kernel/vnic_data.h +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (c) 2007 QLogic Corporation. All rights reserved. - * - * This software is available to you under the OpenIB.org BSD license - * below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * $Id$ - */ - -#ifndef _VNIC_DATA_H_ -#define _VNIC_DATA_H_ - -#include "vnic_trailer.h" - -typedef struct RdmaDest { - LIST_ENTRY listPtrs; - IbRegion_t region; - struct _viport *p_viport; - NDIS_PACKET *p_packet; - NDIS_BUFFER *p_buf; - uint32_t buf_sz; - uint8_t *data; - struct ViportTrailer *pTrailer; -} RdmaDest_t; - -typedef struct BufferPoolEntry { - uint64_t remoteAddr; - net32_t rKey; - uint32_t valid; -} BufferPoolEntry_t; - -typedef struct RecvPool { - uint32_t bufferSz; - uint32_t poolSz; - uint32_t eiocPoolSz; - uint32_t eiocRdmaRkey; - uint64_t eiocRdmaAddr; - uint32_t nextFullBuf; - uint32_t nextFreeBuf; - uint32_t numFreeBufs; - uint32_t numPostedBufs; - uint32_t szFreeBundle; - BOOLEAN kickOnFree; - BufferPoolEntry_t *bufPool; - RdmaDest_t *pRecvBufs; - LIST_ENTRY availRecvBufs; - NDIS_PACKET **recv_pkt_array; -} RecvPool_t; - -typedef struct XmitPool { - uint32_t bufferSz; - uint32_t poolSz; - uint32_t notifyCount; - uint32_t notifyBundle; - uint32_t nextXmitBuf; - uint32_t lastCompBuf; - uint32_t numXmitBufs; - uint32_t nextXmitPool; - uint32_t kickCount; - uint32_t kickByteCount; - uint32_t kickBundle; - uint32_t kickByteBundle; - BOOLEAN needBuffers; - BOOLEAN sendKicks; - uint32_t rdmaRKey; - uint64_t rdmaAddr; - BufferPoolEntry_t *bufPool; - RdmaIo_t *pXmitBufs; -} XmitPool_t; - -typedef struct Data { - struct _viport *p_viport; - DataConfig_t *p_conf; - IbRegion_t *p_phy_region; - IbRegion_t region; - IbRegion_t rbuf_region; - IbQp_t qp; - uint8_t *pLocalStorage; - uint32_t localStorageSz; - uint8_t *p_recv_bufs; - uint32_t recv_bufs_sz; - Inic_RecvPoolConfig_t hostPoolParms; - Inic_RecvPoolConfig_t eiocPoolParms; - RecvPool_t recvPool; - XmitPool_t xmitPool; - RdmaIo_t freeBufsIo; - SendIo_t kickIo; - LIST_ENTRY recvIos; - KSPIN_LOCK recvListLock; - NDIS_SPIN_LOCK recvIosLock; - NDIS_SPIN_LOCK xmitBufLock; - volatile LONG kickTimerOn; - BOOLEAN connected; - cl_timer_t kickTimer; - NDIS_HANDLE h_recv_pkt_pool; - NDIS_HANDLE h_recv_buf_pool; -#ifdef VNIC_STATISTIC - struct { - uint32_t xmitNum; - uint32_t recvNum; - uint32_t freeBufSends; - uint32_t freeBufNum; - uint32_t freeBufMin; - uint32_t kickRecvs; - uint32_t kickReqs; - uint32_t noXmitBufs; - uint64_t noXmitBufTime; - } statistics; -#endif /* VNIC_STATISTIC */ -} Data_t; - -void -vnic_return_packet( - IN NDIS_HANDLE adapter_context, - IN NDIS_PACKET* const p_packet ); - -void -data_construct( - IN Data_t *pData, - IN struct _viport *pViport ); - -ib_api_status_t -data_init( - Data_t *pData, - DataConfig_t *p_conf, - uint64_t guid ); - -ib_api_status_t -data_connect( - Data_t *pData ); - -ib_api_status_t -data_connected( - Data_t *pData ); - -void -data_disconnect( - Data_t *pData ); - -BOOLEAN -data_xmitPacket( - Data_t *pData, - NDIS_PACKET* const p_pkt ); - -void -data_cleanup( - Data_t *pData ); - -#define data_pathId(pData) (pData)->p_conf->pathId -#define data_eiocPool(pData) &(pData)->eiocPoolParms -#define data_hostPool(pData) &(pData)->hostPoolParms -#define data_eiocPoolMin(pData) &(pData)->p_conf->eiocMin -#define data_hostPoolMin(pData) &(pData)->p_conf->hostMin -#define data_eiocPoolMax(pData) &(pData)->p_conf->eiocMax -#define data_hostPoolMax(pData) &(pData)->p_conf->hostMax -#define data_localPoolAddr(pData) (pData)->xmitPool.rdmaAddr -#define data_localPoolRkey(pData) (pData)->xmitPool.rdmaRKey -#define data_remotePoolAddr(pData) &(pData)->recvPool.eiocRdmaAddr -#define data_remotePoolRkey(pData) &(pData)->recvPool.eiocRdmaRkey -#define data_maxMtu(pData) MAX_PAYLOAD(min((pData)->recvPool.bufferSz, (pData)->xmitPool.bufferSz)) - ETH_VLAN_HLEN -#define data_len(pData, pTrailer) ntoh16(pTrailer->dataLength) -#define data_offset(pData, pTrailer) \ - pData->recvPool.bufferSz - sizeof(struct ViportTrailer) \ - - (uint32_t)ROUNDUPP2(data_len(pData, pTrailer), VIPORT_TRAILER_ALIGNMENT) \ - + pTrailer->dataAlignmentOffset - - -/* The following macros manipulate ring buffer indexes. - * The ring buffer size must be a power of 2. - */ -#define ADD(index, increment, size) (((index) + (increment))&((size) - 1)) -#define NEXT(index, size) ADD(index, 1, size) -#define INC(index, increment, size) (index) = ADD(index, increment, size) - -#define VNIC_RECV_FROM_PACKET( P ) \ - (((RdmaDest_t **)P->MiniportReservedEx)[1]) - -#define VNIC_LIST_ITEM_FROM_PACKET( P ) \ - ((LIST_ENTRY *)P->MiniportReservedEx) - -#define VNIC_PACKET_FROM_LIST_ITEM( I ) \ - (PARENT_STRUCT( I, NDIS_PACKET, MiniportReservedEx )) - -#endif /* _VNIC_DATA_H_ */ diff --git a/trunk/ulp/qlc_vnic/kernel/vnic_debug.h b/trunk/ulp/qlc_vnic/kernel/vnic_debug.h deleted file mode 100644 index a5df64f3..00000000 --- a/trunk/ulp/qlc_vnic/kernel/vnic_debug.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (c) 2007 QLogic Corporation. All rights reserved. - * - * This software is available to you under the OpenIB.org BSD license - * below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * $Id$ - */ - - -#ifndef _VNIC_DEBUG_H_ -#define _VNIC_DEBUG_H_ - - -#include - -/* - * Debug macros - */ -extern uint32_t g_vnic_dbg_lvl; - - -#define VNIC_DBG_INIT ( ( VNIC_DBG_INFO ) | 0x00000001 ) -#define VNIC_DBG_PNP ( ( VNIC_DBG_INFO ) | 0x00000002 ) -#define VNIC_DBG_SEND ( ( VNIC_DBG_INFO ) | 0x00000004 ) -#define VNIC_DBG_RECV ( ( VNIC_DBG_INFO ) | 0x00000008 ) -#define VNIC_DBG_STATUS ( ( VNIC_DBG_INFO ) | 0x00000010 ) -#define VNIC_DBG_IB ( ( VNIC_DBG_INFO ) | 0x00000020 ) -#define VNIC_DBG_BUF ( ( VNIC_DBG_INFO ) | 0x00000040 ) -#define VNIC_DBG_MCAST ( ( VNIC_DBG_INFO ) | 0x00000080 ) -#define VNIC_DBG_ALLOC ( ( VNIC_DBG_INFO ) | 0x00000100 ) -#define VNIC_DBG_OID ( ( VNIC_DBG_INFO ) | 0x00000200 ) -#define VNIC_DBG_DATA ( ( VNIC_DBG_INFO ) | 0x00000400 ) -#define VNIC_DBG_CTRL ( ( VNIC_DBG_INFO ) | 0x00000800 ) -#define VNIC_DBG_CTRL_PKT ( ( VNIC_DBG_INFO ) | 0x00001000 ) -#define VNIC_DBG_CONF ( ( VNIC_DBG_INFO ) | 0x00002000 ) -#define VNIC_DBG_VIPORT ( ( VNIC_DBG_INFO ) | 0x00004000 ) -#define VNIC_DBG_ADAPTER ( ( VNIC_DBG_INFO ) | 0x00008000 ) -#define VNIC_DBG_NETPATH ( ( VNIC_DBG_INFO ) | 0x00010000 ) - -#define VNIC_DBG_FUNC (0x10000000) /* For function entry/exit */ -#define VNIC_DBG_INFO (0x20000000) /* For verbose information */ -#define VNIC_DBG_WARN (0x40000000) /* For warnings. */ -#define VNIC_DBG_ERROR CL_DBG_ERROR -#define VNIC_DBG_ALL CL_DBG_ALL - -#define VNIC_DEBUG_FLAGS ( VNIC_DBG_ERROR | VNIC_DBG_WARN | VNIC_DBG_INFO ) -/* Enter and exit macros automatically add VNIC_DBG_FUNC bit */ -#define VNIC_ENTER( lvl ) \ - CL_ENTER( (lvl | VNIC_DBG_FUNC), g_vnic_dbg_lvl ) - -#define VNIC_EXIT( lvl ) \ - CL_EXIT( (lvl | VNIC_DBG_FUNC), g_vnic_dbg_lvl ) - -#if defined FREE_BUILD_DBG -#define VNIC_TRACE( lvl, msg ) \ - { \ - switch( (lvl) & VNIC_DBG_ERROR ) \ - { \ - case VNIC_DBG_ERROR: \ - cl_msg_out msg; \ - default: \ - CL_TRACE( (lvl), g_vnic_dbg_lvl, msg ); \ - } \ - } - -#define VNIC_TRACE_EXIT( lvl, msg ) \ - { \ - switch( (lvl) & VNIC_DBG_ERROR ) \ - { \ - case VNIC_DBG_ERROR: \ - cl_msg_out msg; \ - default: \ - CL_TRACE_EXIT( (lvl), g_vnic_dbg_lvl, msg ); \ - } \ - } - -#else // ! FREE_BUILD_DBG - -#define VNIC_TRACE( lvl, msg ) \ - CL_TRACE( (lvl), g_vnic_dbg_lvl, msg ) - -#define VNIC_TRACE_EXIT( lvl, msg ) \ - CL_TRACE_EXIT( (lvl), g_vnic_dbg_lvl, msg ) - -#endif // FREE_BUILD_DBG - -#define VNIC_PRINT( lvl, msg ) \ - CL_PRINT ( (lvl), g_vnic_dbg_lvl, msg ) - -#define VNIC_TRACE_BYTES( lvl, ptr, len ) \ - { \ - size_t _loop_; \ - for (_loop_ = 0; _loop_ < (len); ++_loop_) \ - { \ - CL_PRINT( (lvl), g_vnic_dbg_lvl, ("0x%.2X ", ((uint8_t*)(ptr))[_loop_])); \ - if ((_loop_ + 1)% 16 == 0) \ - { \ - CL_PRINT( (lvl), g_vnic_dbg_lvl, ("\n") ); \ - } \ - else if ((_loop_ % 4 + 1) == 0) \ - { \ - CL_PRINT( (lvl), g_vnic_dbg_lvl, (" ") ); \ - } \ - } \ - CL_PRINT( (lvl), g_vnic_dbg_lvl, ("\n") ); \ - } - - -#endif /* _VNIC_DEBUG_H_ */ diff --git a/trunk/ulp/qlc_vnic/kernel/vnic_driver.c b/trunk/ulp/qlc_vnic/kernel/vnic_driver.c deleted file mode 100644 index 942fa571..00000000 --- a/trunk/ulp/qlc_vnic/kernel/vnic_driver.c +++ /dev/null @@ -1,2156 +0,0 @@ -/* - * Copyright (c) 2007 QLogic Corporation. All rights reserved. - * - * This software is available to you under the OpenIB.org BSD license - * below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * $Id$ - */ - - - -#include -#include "vnic_driver.h" - - -vnic_globals_t g_vnic; - -g_registry_params_t reg_array[VNIC_REGISTRY_TBL_SIZE] = { - {L"", 0}, - {L"MinHostPoolSz", ENTRY_INIT_VALUE}, - {L"HostRecvPoolEntries", ENTRY_INIT_VALUE}, - {L"MinEiocPoolSz", ENTRY_INIT_VALUE}, - {L"MaxEiocPoolSz", ENTRY_INIT_VALUE}, - {L"MinHostKickTimeout", ENTRY_INIT_VALUE}, - {L"MaxHostKickTimeout", ENTRY_INIT_VALUE}, - {L"MinHostKickEntries", ENTRY_INIT_VALUE}, - {L"MaxHostKickEntries", ENTRY_INIT_VALUE}, - {L"MinHostKickBytes", ENTRY_INIT_VALUE}, - {L"MaxHostKickBytes", ENTRY_INIT_VALUE}, - {L"MinHostUpdateSz", ENTRY_INIT_VALUE}, - {L"MaxHostUpdateSz", ENTRY_INIT_VALUE}, - {L"MinEiocUpdateSz", ENTRY_INIT_VALUE}, - {L"MaxEiocUpdateSz", ENTRY_INIT_VALUE}, - {L"HeartbeatTimeout", ENTRY_INIT_VALUE}, -}; - -#define DEFAULT_HOST_NAME "VNIC Host" - -uint32_t g_vnic_dbg_lvl = VNIC_DEBUG_FLAGS; - -static void -_vnic_complete_query( - IN vnic_adapter_t* const p_adapter, - IN pending_oid_t* const p_oid_info, - IN const NDIS_STATUS status, - IN const void* const p_buf, - IN const ULONG buf_len ); - -static NDIS_STATUS -__vnic_get_tcp_task_offload( - IN vnic_adapter_t* p_adapter, - IN pending_oid_t* const p_oid_info ); - -static NDIS_STATUS -__vnic_set_tcp_task_offload( - IN vnic_adapter_t* p_adapter, - IN void* const p_info_buf, - IN ULONG* const p_info_len ); - -static NDIS_STATUS -_vnic_process_packet_filter( - IN vnic_adapter_t* const p_adapter, - IN ULONG pkt_filter ); - -static void -__vnic_read_machine_name( void ); - -static NTSTATUS -__vnic_read_service_registry( - IN UNICODE_STRING* const p_registry_path ); - -static NDIS_STATUS -__vnic_set_machine_name( - IN VOID *p_uni_array, - IN USHORT buf_size ); - -/* -p_drv_obj - Pointer to Driver Object for this device driver -p_registry_path - Pointer to unicode string containing path to this driver's registry area -return - STATUS_SUCCESS, NDIS_STATUS_BAD_CHARACTERISTICS, NDIS_STATUS_BAD_VERSION, - NDIS_STATUS_RESOURCES, or NDIS_STATUS_FAILURE -IRQL = PASSIVE_LEVEL -*/ -NTSTATUS -DriverEntry( - IN PDRIVER_OBJECT p_drv_obj, - IN PUNICODE_STRING p_registry_path ) -{ - NDIS_STATUS status; - NDIS_MINIPORT_CHARACTERISTICS characteristics; - - VNIC_ENTER( VNIC_DBG_INIT ); - -#ifdef _DEBUG_ - PAGED_CODE(); -#endif -/* - status = CL_INIT; - - if( !NT_SUCCESS( status ) ) - { - VNIC_TRACE_EXIT( VNIC_DBG_ERROR, - ("cl_init failed.\n") ); - return status; - } -*/ - status = NDIS_STATUS_SUCCESS; - - g_vnic.ndis_handle = NULL; - g_vnic.shutdown = 0; - g_vnic.p_params = NULL; - - NdisMInitializeWrapper( &g_vnic.ndis_handle, p_drv_obj, p_registry_path, NULL ); - - if ( g_vnic.ndis_handle == NULL ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("NdisMInitializeWrapper failed\n")); - CL_DEINIT; - return NDIS_STATUS_FAILURE; - } - - cl_memclr( &characteristics, sizeof(characteristics) ); - - characteristics.MajorNdisVersion = MAJOR_NDIS_VERSION; - characteristics.MinorNdisVersion = MINOR_NDIS_VERSION; - characteristics.CheckForHangHandler = vnic_check_for_hang; - characteristics.HaltHandler = vnic_halt; - characteristics.InitializeHandler = vnic_initialize; - characteristics.QueryInformationHandler = vnic_oid_query_info; - characteristics.ResetHandler = vnic_reset; - characteristics.SetInformationHandler = vnic_oid_set_info; - characteristics.ReturnPacketHandler = vnic_return_packet; - characteristics.SendPacketsHandler = vnic_send_packets; - -#ifdef NDIS51_MINIPORT - characteristics.CancelSendPacketsHandler = vnic_cancel_xmit; - characteristics.PnPEventNotifyHandler = vnic_pnp_notify; - characteristics.AdapterShutdownHandler = vnic_shutdown; -#endif - - status = NdisMRegisterMiniport( - g_vnic.ndis_handle, &characteristics, sizeof(characteristics) ); - - if( status != NDIS_STATUS_SUCCESS ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("NdisMRegisterMiniport failed with status of %d\n", status) ); - NdisTerminateWrapper( g_vnic.ndis_handle, NULL ); - CL_DEINIT; - } - else - { - NdisMRegisterUnloadHandler( g_vnic.ndis_handle, vnic_unload ); - - __vnic_read_machine_name(); - __vnic_read_service_registry( p_registry_path ); - -#if ( LBFO_ENABLED ) - cl_qlist_init( &g_vnic.primary_list ); - cl_qlist_init( &g_vnic.secondary_list ); -#endif - } - - VNIC_EXIT( VNIC_DBG_INIT ); - return status; -} - - -VOID -vnic_unload( - IN PDRIVER_OBJECT p_drv_obj ) -{ - VNIC_ENTER( VNIC_DBG_INIT ); - - UNREFERENCED_PARAMETER( p_drv_obj ); - - VNIC_TRACE_EXIT( VNIC_DBG_INFO, - (" Driver Unloaded....\n")); - //CL_DEINIT; -} - - -//! Initialization function called for each IOC discovered -/* The MiniportInitialize function is a required function that sets up a -NIC (or virtual NIC) for network I/O operations, claims all hardware -resources necessary to the NIC in the registry, and allocates resources -the driver needs to carry out network I/O operations. -IRQL = PASSIVE_LEVEL - -@param p_open_status Pointer to a status field set if this function returns NDIS_STATUS_OPEN_ERROR -@param p_selected_medium_index Pointer to unsigned integer noting index into medium_array for this NIC -@param medium_array Array of mediums for this NIC -@param medium_array_size Number of elements in medium_array -@param h_handle Handle assigned by NDIS for this NIC -@param wrapper_config_context Handle used for Ndis initialization functions -@return NDIS_STATUS_SUCCESS, NDIS_STATUS_UNSUPPORTED_MEDIA, NDIS_STATUS_RESOURCES, -NDIS_STATUS_NOT_SUPPORTED -*/ -NDIS_STATUS -vnic_initialize( - OUT PNDIS_STATUS p_open_status, - OUT PUINT p_selected_medium_index, - IN PNDIS_MEDIUM medium_array, - IN UINT medium_array_size, - IN NDIS_HANDLE h_handle, - IN NDIS_HANDLE wrapper_config_context ) -{ - NDIS_STATUS status = NDIS_STATUS_SUCCESS; - ib_api_status_t ib_status; - ib_pnp_req_t pnp_req; - UINT medium_index; - vnic_adapter_t *p_adapter; - - VNIC_ENTER( VNIC_DBG_INIT ); - -#ifdef _DEBUG_ - PAGED_CODE(); -#endif - - UNUSED_PARAM( p_open_status ); - - /* Search for our medium */ - for( medium_index = 0; medium_index < medium_array_size; ++medium_index ) - { - /* Check to see if we found our medium */ - if( medium_array[medium_index] == NdisMedium802_3 ) - break; - } - - if( medium_index == medium_array_size ) /* Never found it */ - { - VNIC_TRACE_EXIT( VNIC_DBG_ERROR, ("No supported media.\n") ); - return NDIS_STATUS_UNSUPPORTED_MEDIA; - } - - *p_selected_medium_index = medium_index; - - /* Create the adapter */ - ib_status = vnic_create_adapter( h_handle, wrapper_config_context, &p_adapter ); - if( ib_status != IB_SUCCESS ) - { - VNIC_TRACE_EXIT( VNIC_DBG_ERROR, - ("returned status %x\n", ib_status ) ); - return NDIS_STATUS_FAILURE; - } - - /* set NDIS features we support */ - NdisMSetAttributesEx( h_handle, - (NDIS_HANDLE)p_adapter, - 0, /*check for hung timeout, 2 sec */ - NDIS_ATTRIBUTE_BUS_MASTER | - NDIS_ATTRIBUTE_DESERIALIZE | - NDIS_ATTRIBUTE_SURPRISE_REMOVE_OK | - NDIS_ATTRIBUTE_USES_SAFE_BUFFER_APIS, - NdisInterfacePNPBus ); - - /* Register for IOC events */ - pnp_req.pfn_pnp_cb = __vnic_pnp_cb; - pnp_req.pnp_class = IB_PNP_IOC | IB_PNP_FLAG_REG_SYNC; - pnp_req.pnp_context = (const void *)p_adapter; - - ib_status = p_adapter->ifc.reg_pnp( p_adapter->h_al, &pnp_req, &p_adapter->h_pnp ); - - if( ib_status != IB_SUCCESS ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("ib_reg_pnp returned %s\n", p_adapter->ifc.get_err_str( ib_status )) ); - NdisWriteErrorLogEntry( h_handle, - NDIS_ERROR_CODE_OUT_OF_RESOURCES, 0); - status = NDIS_STATUS_FAILURE; - } - else if( p_adapter->state != INIC_REGISTERED ) - { - status = NDIS_STATUS_OPEN_FAILED; - *p_open_status = NDIS_STATUS_DEVICE_FAILED; - - VNIC_TRACE( VNIC_DBG_ERROR, - ("IOC[%d] ADAPTER Initialization Failed\n", p_adapter->ioc_num ) ); - NdisWriteErrorLogEntry( h_handle, - NDIS_ERROR_CODE_HARDWARE_FAILURE, 1, p_adapter->ioc_num ); - } - - if( status != NDIS_STATUS_SUCCESS ) - { - vnic_destroy_adapter( p_adapter ); - } - - VNIC_EXIT( VNIC_DBG_INIT ); - return status; - -} - - -//! Deallocates resources when the NIC is removed and halts the NIC.. -/* IRQL = DISPATCH_LEVEL - -@param adapter_context The adapter context allocated at start -*/ -void -vnic_halt( - IN NDIS_HANDLE adapter_context ) -{ - VNIC_ENTER( VNIC_DBG_INIT ); - CL_ASSERT( adapter_context ); - - vnic_destroy_adapter( (vnic_adapter_t*)adapter_context ); - - VNIC_EXIT( VNIC_DBG_INIT ); -} - - -//! Reports the state of the NIC, or monitors the responsiveness of an underlying device driver. -/* IRQL = DISPATCH_LEVEL - -@param adapter_context The adapter context allocated at start -@return TRUE if the driver determines that its NIC is not operating -*/ - -BOOLEAN -vnic_check_for_hang( - IN NDIS_HANDLE adapter_context ) -{ - vnic_adapter_t *p_adapter; - - CL_ASSERT( adapter_context ); - p_adapter = (vnic_adapter_t*)adapter_context; - - /* current path is Ok */ - if( netpath_is_connected( p_adapter->p_currentPath ) ) - { - return FALSE; - } - - if( p_adapter->hung != 0 && - p_adapter->hung >= p_adapter->num_paths ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("IOC[%d] Adapter Hung: %d NumPath: %d\n", - p_adapter->ioc_num, p_adapter->hung, p_adapter->num_paths ) ); - return TRUE; - } - - return FALSE; -} - - -//! Returns information about the capabilities and status of the driver and/or its NIC. -/* IRQL = DISPATCH_LEVEL - -@param adapter_context The adapter context allocated at start -@param oid Object ID representing the query operation to be carried out -@param info_buf Buffer containing any input for this query and location for output -@param info_buf_len Number of bytes available in info_buf -@param p_bytes_written Pointer to number of bytes written into info_buf -@param p_bytes_needed Pointer to number of bytes needed to satisfy this oid -@return NDIS_STATUS_SUCCESS, NDIS_STATUS_PENDING, NDIS_STATUS_INVALID_OID, -NDIS_STATUS_INVALID_LENGTH, NDIS_STATUS_NOT_ACCEPTED, NDIS_STATUS_NOT_SUPPORTED, -NDIS_STATUS_RESOURCES -*/ -NDIS_STATUS -vnic_oid_query_info( - IN NDIS_HANDLE adapter_context, - IN NDIS_OID oid, - IN PVOID info_buf, - IN ULONG info_buf_len, - OUT PULONG p_bytes_written, - OUT PULONG p_bytes_needed ) -{ - vnic_adapter_t *p_adapter; - Netpath_t *p_netpath; - - NDIS_STATUS status; - USHORT version; - uint32_t info32 = 0; - uint64_t info64 = 0; - PVOID src_buf; - ULONG buf_len; - pending_oid_t oid_info; - - VNIC_ENTER( VNIC_DBG_OID ); - - oid_info.oid = oid; - oid_info.p_buf = info_buf; - oid_info.buf_len = info_buf_len; - oid_info.p_bytes_used = p_bytes_written; - oid_info.p_bytes_needed = p_bytes_needed; - - CL_ASSERT( adapter_context ); - p_adapter = (vnic_adapter_t *)adapter_context; - - CL_ASSERT( p_bytes_written ); - CL_ASSERT( p_bytes_needed ); - - status = NDIS_STATUS_SUCCESS; - src_buf = &info32; - buf_len = sizeof(info32); - - if( g_vnic.shutdown != 0 ) - { - *p_bytes_written = 0; - return NDIS_STATUS_NOT_ACCEPTED; - } - - p_netpath = p_adapter->p_currentPath; - if( !p_netpath || !p_netpath->carrier ) - { - status = NDIS_STATUS_NOT_ACCEPTED; - goto complete; - } - - switch( oid ) - { - /* Required General */ - case OID_GEN_SUPPORTED_LIST: - VNIC_TRACE( VNIC_DBG_OID, - ("received query for OID_GEN_SUPPORTED_LIST\n") ); - src_buf = (PVOID)SUPPORTED_OIDS; - buf_len = sizeof(SUPPORTED_OIDS); - break; - - case OID_GEN_HARDWARE_STATUS: - VNIC_TRACE( VNIC_DBG_OID, - ("received query for OID_GEN_HARDWARE_STATUS\n") ); - - if( p_netpath->carrier ) - { - VNIC_TRACE( VNIC_DBG_OID, - ("returning NdisHardwareStatusReady\n") ); - info32 = NdisHardwareStatusReady; - } - else - { - VNIC_TRACE( VNIC_DBG_OID, - ("returning NdisHardwareStatusInitializing\n") ); - info32 = NdisHardwareStatusNotReady; - } - break; - - case OID_GEN_MEDIA_SUPPORTED: - case OID_GEN_MEDIA_IN_USE: - VNIC_TRACE( VNIC_DBG_OID, - ("received query for OID_GEN_MEDIA_SUPPORTED " - "or OID_GEN_MEDIA_IN_USE\n") ); - info32 = NdisMedium802_3; - break; - - case OID_GEN_MAXIMUM_TOTAL_SIZE: /* frame size inlcuding header */ - info32 = sizeof( eth_hdr_t ); - case OID_GEN_MAXIMUM_FRAME_SIZE: /* wihout header */ - VNIC_TRACE( VNIC_DBG_OID, - ("received query for OID_GEN_MAXIMUM_FRAME_SIZE\n") ); - if( !p_netpath->carrier ) - { - info32 += MIN_MTU; - } - else - { - info32 += p_adapter->p_currentPath->pViport->mtu; - } - break; - - case OID_GEN_LINK_SPEED: - VNIC_TRACE( VNIC_DBG_OID, - ("received query for OID_GEN_LINK_SPEED\n") ); - - if( p_netpath->carrier ) - { - /* if we get link speed value - it is in Mbps units - have to convert to 100bps*/ - info32 = ( p_adapter->link_speed )? - ( p_adapter->link_speed * LINK_SPEED_1MBIT_x100BPS ): - DEFAULT_LINK_SPEED_x100BPS; - } - else - { - status = NDIS_STATUS_NOT_ACCEPTED; - } - break; - - case OID_GEN_TRANSMIT_BUFFER_SPACE: - VNIC_TRACE( VNIC_DBG_OID, - ("received query for OID_GEN_TRANSMIT_BUFFER_SPACE\n") ); - if ( !p_netpath->carrier ) - { - status= NDIS_STATUS_NOT_ACCEPTED; - } - else - { - info32 = p_netpath->pViport->data.xmitPool.bufferSz * - p_netpath->pViport->data.xmitPool.poolSz; - } - break; - - case OID_GEN_RECEIVE_BUFFER_SPACE: - VNIC_TRACE( VNIC_DBG_OID, - ("received query for OID_GEN_RECEIVE_BUFFER_SPACE " - "or OID_GEN_RECEIVE_BUFFER_SPACE\n") ); - if ( !p_netpath->carrier ) - { - status = NDIS_STATUS_NOT_ACCEPTED; - } - else - { - info32 = p_netpath->pViport->data.recvPool.bufferSz * - p_netpath->pViport->data.recvPool.poolSz; - } - break; - case OID_GEN_MAXIMUM_LOOKAHEAD: - case OID_GEN_CURRENT_LOOKAHEAD: - case OID_GEN_TRANSMIT_BLOCK_SIZE: - case OID_GEN_RECEIVE_BLOCK_SIZE: - VNIC_TRACE( VNIC_DBG_OID, - ("received query for OID_GEN_MAXIMUM_LOOKAHEAD " - "or OID_GEN_CURRENT_LOOKAHEAD or " - "OID_GEN_TRANSMIT_BLOCK_SIZE or " - "OID_GEN_RECEIVE_BLOCK_SIZE\n") ); - if( !p_netpath->carrier ) - { - info32 = MIN_MTU; - } - else - { - info32 = p_adapter->p_currentPath->pViport->mtu; - } - /*TODO: add VLAN tag size if support requested */ - info32 += sizeof(eth_hdr_t); - break; - - case OID_GEN_VENDOR_ID: - VNIC_TRACE( VNIC_DBG_OID, - ("received query for OID_GEN_VENDOR_ID\n") ); - - src_buf = (void*)VENDOR_ID; - buf_len = sizeof(VENDOR_ID); - break; - - case OID_GEN_VENDOR_DESCRIPTION: - VNIC_TRACE( VNIC_DBG_OID, - ("received query for OID_GEN_VENDOR_DESCRIPTION\n") ); - src_buf = VENDOR_DESCRIPTION; - buf_len = sizeof(VENDOR_DESCRIPTION); - break; - - case OID_GEN_VENDOR_DRIVER_VERSION: - VNIC_TRACE( VNIC_DBG_OID, - (" received query for OID_GEN_VENDOR_DRIVER_VERSION\n" ) ); - src_buf = &version; - buf_len = sizeof(version); - //TODO: Figure out what the right version is. - version = INIC_MAJORVERSION << 8 | INIC_MINORVERSION; - break; - - case OID_GEN_PHYSICAL_MEDIUM: - VNIC_TRACE( VNIC_DBG_OID, - (" received query for OID_GEN_PHYSICAL_MEDIUM\n" ) ); - info32 = NdisPhysicalMediumUnspecified; - break; - - case OID_GEN_CURRENT_PACKET_FILTER: - VNIC_TRACE( VNIC_DBG_OID, - (" received query for OID_GEN_CURRENT_PACKET_FILTER\n" ) ); - info32 = p_adapter->packet_filter; - break; - - case OID_GEN_DRIVER_VERSION: - VNIC_TRACE( VNIC_DBG_OID, - (" received query for OID_GEN_DRIVER_VERSION\n" ) ); - src_buf = &version; - buf_len = sizeof(version); - version = MAJOR_NDIS_VERSION << 8 | MINOR_NDIS_VERSION; - break; - - case OID_GEN_MAC_OPTIONS: - VNIC_TRACE( VNIC_DBG_OID, - (" received query for OID_GEN_MAC_OPTIONS\n" ) ); - info32 = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | - NDIS_MAC_OPTION_TRANSFERS_NOT_PEND | - NDIS_MAC_OPTION_NO_LOOPBACK | - NDIS_MAC_OPTION_FULL_DUPLEX | - NDIS_MAC_OPTION_8021P_PRIORITY | - NDIS_MAC_OPTION_8021Q_VLAN; - - break; - - case OID_GEN_MEDIA_CONNECT_STATUS: - VNIC_TRACE( VNIC_DBG_OID, - (" received query for OID_GEN_MEDIA_CONNECT_STATUS\n" ) ); - - info32 = ( p_adapter->carrier )? - NdisMediaStateConnected : - NdisMediaStateDisconnected; - break; - - case OID_GEN_MAXIMUM_SEND_PACKETS: - VNIC_TRACE( VNIC_DBG_OID, - (" received query for OID_GEN_MAXIMUM_SEND_PACKETS\n" ) ); - info32 = MAXLONG; // NDIS ignored it anyway - break; - - /* Required General Statistics */ - case OID_GEN_XMIT_OK: - VNIC_TRACE( VNIC_DBG_OID, - (" received query for OID_GEN_XMIT_OK\n" ) ); - if ( !p_netpath->carrier ) - { - info32 = 0; - } - else - { - info64 = p_netpath->pViport->stats.ifOutOk; - src_buf = &info64; - buf_len = sizeof(info64); - } - break; - - case OID_GEN_RCV_OK: - VNIC_TRACE( VNIC_DBG_OID, - (" received query for OID_GEN_RCV_OK\n" ) ); - if ( !p_netpath->carrier) - { - info32 = 0; - break; - } - if ( info_buf_len == sizeof(info32) ) - { - info32 = (uint32_t)p_netpath->pViport->stats.ifInOk; - } - else - { - info64 = p_netpath->pViport->stats.ifInOk; - src_buf = &info64; - buf_len = sizeof(info64); - } - break; - - case OID_GEN_XMIT_ERROR: - VNIC_TRACE( VNIC_DBG_OID, - (" received query for OID_GEN_XMIT_ERROR\n" ) ); - if ( !p_netpath->carrier ) - { - info32 = 0; - } - else - { - info64 = p_netpath->pViport->stats.ifOutErrors; - src_buf = &info64; - buf_len = sizeof(info64); - } - break; - - case OID_GEN_RCV_ERROR: - VNIC_TRACE( VNIC_DBG_OID, - (" received query for OID_GEN_RCV_ERROR\n" ) ); - if ( !p_netpath->carrier ) - { - info32 = 0; - } - else - { - info64 = p_netpath->pViport->stats.ifInErrors; - src_buf = &info64; - buf_len = sizeof(info64); - } - break; - - case OID_GEN_RCV_NO_BUFFER: - VNIC_TRACE( VNIC_DBG_OID, - (" received query for OID_GEN_RCV_NO_BUFFER\n" ) ); - info32 = 0; - break; - - case OID_GEN_DIRECTED_BYTES_XMIT: - VNIC_TRACE( VNIC_DBG_OID, - (" received query for OID_GEN_DIRECTED_BYTES_XMIT\n" ) ); - if ( !p_netpath->carrier ) - { - info32 = 0; - } - else - { - info64 = p_netpath->pViport->stats.ifOutUcastBytes; - src_buf = &info64; - buf_len = sizeof(info64); - } - break; - - case OID_GEN_DIRECTED_FRAMES_XMIT: - VNIC_TRACE( VNIC_DBG_OID, - (" received query for OID_GEN_DIRECTED_FRAMES_XMIT\n" ) ); - if ( !p_netpath->carrier ) - { - info32 = 0; - } - else - { - info64 = p_netpath->pViport->stats.ifOutNUcastPkts; - src_buf = &info64; - buf_len = sizeof(info64); - } - break; - - case OID_GEN_MULTICAST_BYTES_XMIT: - VNIC_TRACE( VNIC_DBG_OID, - (" received query for OID_GEN_MULTICAST_BYTES_XMIT\n" ) ); - if ( !p_netpath->carrier ) - { - info32 = 0; - } - else - { - info64 = p_netpath->pViport->stats.ifOutMulticastBytes; - src_buf = &info64; - buf_len = sizeof(info64); - } - break; - - case OID_GEN_MULTICAST_FRAMES_XMIT: - VNIC_TRACE( VNIC_DBG_OID, - (" received query for OID_GEN_MULTICAST_FRAMES_XMIT\n" ) ); - if ( !p_netpath->carrier ) - { - info32 = 0; - } - else - { - info64 = p_netpath->pViport->stats.ifOutMulticastPkts; - src_buf = &info64; - buf_len = sizeof(info64); - } - break; - - case OID_GEN_BROADCAST_BYTES_XMIT: - VNIC_TRACE( VNIC_DBG_OID, - (" received query for OID_GEN_BROADCAST_BYTES_XMIT\n" ) ); - if ( !p_netpath->carrier ) - { - info32 = 0; - } - else - { - info64 = p_netpath->pViport->stats.ifOutBroadcastBytes; - src_buf = &info64; - buf_len = sizeof(info64); - } - break; - - case OID_GEN_BROADCAST_FRAMES_XMIT: - VNIC_TRACE( VNIC_DBG_OID, - (" received query for OID_GEN_BROADCAST_FRAMES_XMIT\n" ) ); - if ( !p_netpath->carrier ) - { - info32 = 0; - } - else - { - info64 = p_netpath->pViport->stats.ifOutBroadcastPkts; - src_buf = &info64; - buf_len = sizeof(info64); - } - break; - case OID_GEN_DIRECTED_BYTES_RCV: - VNIC_TRACE( VNIC_DBG_OID, - (" received query for OID_GEN_DIRECTED_BYTES_RCV\n" ) ); - if ( !p_netpath->carrier ) - { - info32 = 0; - } - else - { - info64 = p_netpath->pViport->stats.ifInUcastBytes; - src_buf = &info64; - buf_len = sizeof(info64); - } - break; - - case OID_GEN_DIRECTED_FRAMES_RCV: - VNIC_TRACE( VNIC_DBG_OID, - (" received query for OID_GEN_DIRECTED_FRAMES_RCV\n" ) ); - if ( !p_netpath->carrier ) - { - info32 = 0; - } - else - { - info64 = p_netpath->pViport->stats.ifInNUcastPkts; - src_buf = &info64; - buf_len = sizeof(info64); - } - break; - - case OID_GEN_MULTICAST_BYTES_RCV: - VNIC_TRACE( VNIC_DBG_OID, - (" received query for OID_GEN_MULTICAST_BYTES_RCV\n" ) ); - if ( !p_netpath->carrier ) - { - info32 = 0; - } - else - { - info64 = p_netpath->pViport->stats.ifInMulticastBytes; - src_buf = &info64; - buf_len = sizeof(info64); - } - break; - - case OID_GEN_MULTICAST_FRAMES_RCV: - VNIC_TRACE( VNIC_DBG_OID, - (" received query for OID_GEN_MULTICAST_FRAMES_RCV\n" ) ); - if ( !p_netpath->carrier ) - { - info32 = 0; - } - else - { - info64 = p_netpath->pViport->stats.ifInMulticastPkts; - src_buf = &info64; - buf_len = sizeof(info64); - } - break; - - case OID_GEN_BROADCAST_BYTES_RCV: - VNIC_TRACE( VNIC_DBG_OID, - (" received query for OID_GEN_BROADCAST_BYTES_RCV\n" ) ); - if ( !p_netpath->carrier ) - { - info32 = 0; - } - else - { - info64 = p_netpath->pViport->stats.ifInBroadcastBytes; - src_buf = &info64; - buf_len = sizeof(info64); - } - break; - - case OID_GEN_BROADCAST_FRAMES_RCV: - VNIC_TRACE( VNIC_DBG_OID, - (" received query for OID_GEN_BROADCAST_FRAMES_RCV\n" ) ); - if ( !p_netpath->carrier ) - { - info32 = 0; - } - else - { - info64 = p_netpath->pViport->stats.ifInBroadcastPkts; - src_buf = &info64; - buf_len = sizeof(info64); - } - break; - - /* Required Ethernet operational characteristics */ - case OID_802_3_PERMANENT_ADDRESS: - case OID_802_3_CURRENT_ADDRESS: -#if defined( _DEBUG_ ) - if( oid == OID_802_3_PERMANENT_ADDRESS ) - { - VNIC_TRACE( VNIC_DBG_OID, - (" received query for OID_802_3_PERMANENT_ADDRESS\n" ) ); - } - else - { - VNIC_TRACE( VNIC_DBG_OID, - (" received query for OID_802_3_CURRENT_ADDRESS\n" ) ); - } -#endif /* defined( _DEBUG_ )*/ - if( !p_netpath->pViport || - p_netpath->pViport->errored || - p_netpath->pViport->disconnect ) - { - status = NDIS_STATUS_NOT_ACCEPTED; - break; - } - if ( !p_adapter->macSet ) - { - p_adapter->pending_query = TRUE; - p_adapter->query_oid = oid_info; - - VNIC_TRACE( VNIC_DBG_OID, - ("returning NDIS_STATUS_PENDING\n") ); - status = NDIS_STATUS_PENDING; - } - else - { - src_buf = &p_netpath->pViport->hwMacAddress; - buf_len = HW_ADDR_LEN; - } - break; - - case OID_802_3_MULTICAST_LIST: - VNIC_TRACE( VNIC_DBG_OID, - (" received query for OID_802_3_MULTICAST_LIST\n" ) ); - - if( !p_netpath->carrier || - !(p_netpath->pViport->flags & INIC_FLAG_ENABLE_NIC) ) - { -/* p_adapter->pending_query = TRUE; - p_adapter->query_oid = oid_info; - - VNIC_TRACE( VNIC_DBG_OID, - ("returning NDIS_STATUS_PENDING\n") ); - status = NDIS_STATUS_PENDING; -*/ - status = NDIS_STATUS_NOT_ACCEPTED; - break; - } - if( p_adapter->mc_count > 0 ) - { - buf_len = p_adapter->mc_count * sizeof( mac_addr_t ); - src_buf = &p_adapter->mcast_array; - } - else - { - info32 = 0; - } - break; - - case OID_802_3_MAXIMUM_LIST_SIZE: - VNIC_TRACE( VNIC_DBG_OID, - (" received query for OID_802_3_MAXIMUM_LIST_SIZE\n" ) ); - if ( !p_adapter->macSet ) - { - info32 = MAX_MCAST; - } - else - { - info32 = p_netpath->pViport->numMacAddresses - MCAST_ADDR_START; - } - break; - case OID_802_3_MAC_OPTIONS: - VNIC_TRACE( VNIC_DBG_OID, - (" received query for OID_802_3_MAC_OPTIONS\n" ) ); - info32 = 0; - break; - - /* Required Ethernet stats */ - case OID_802_3_RCV_ERROR_ALIGNMENT: - case OID_802_3_XMIT_ONE_COLLISION: - case OID_802_3_XMIT_MORE_COLLISIONS: - VNIC_TRACE( VNIC_DBG_OID, - (" received query for OID_802_3_RCV_ERROR_ALIGNMENT or " - "OID_802_3_XMIT_ONE_COLLISION or " - "OID_802_3_XMIT_MORE_COLLISIONS\n" ) ); - info32 = 0; - break; - - case OID_TCP_TASK_OFFLOAD: - VNIC_TRACE( VNIC_DBG_OID, - (" received query for OID_TCP_TASK_OFFLOAD\n" ) ); - - src_buf = NULL; - status = __vnic_get_tcp_task_offload( p_adapter, &oid_info ); - break; - - case OID_GEN_VLAN_ID: - /* return current vlan info */ - info32 =( p_adapter->vlan_info & 0x00000fff ); - break; - /* Optional General */ - case OID_GEN_SUPPORTED_GUIDS: - /* Optional General Stats */ - case OID_GEN_RCV_CRC_ERROR: - case OID_GEN_TRANSMIT_QUEUE_LENGTH: - - /* Optional Ethernet Stats */ - case OID_802_3_XMIT_DEFERRED: - case OID_802_3_XMIT_MAX_COLLISIONS: - case OID_802_3_RCV_OVERRUN: - case OID_802_3_XMIT_UNDERRUN: - case OID_802_3_XMIT_HEARTBEAT_FAILURE: - case OID_802_3_XMIT_TIMES_CRS_LOST: - case OID_802_3_XMIT_LATE_COLLISIONS: - case OID_PNP_CAPABILITIES: - status = NDIS_STATUS_NOT_SUPPORTED; - VNIC_TRACE( VNIC_DBG_OID, - (" received an unsupported oid of 0x%.8X!\n" , oid) ); - break; - - case OID_GEN_PROTOCOL_OPTIONS: - case OID_GEN_TRANSPORT_HEADER_OFFSET: -#ifdef NDIS51_MINIPORT - case OID_GEN_MACHINE_NAME: - case OID_GEN_RNDIS_CONFIG_PARAMETER: -#endif - default: - status = NDIS_STATUS_INVALID_OID; - VNIC_TRACE( VNIC_DBG_OID, - (" received an invalid oid of 0x%.8X!\n" , oid) ); - break; - } - - /* - * Complete the request as if it was handled asynchronously to maximize - * code reuse for when we really handle the requests asynchronously. - * Note that this requires the QueryInformation entry point to always - * return NDIS_STATUS_PENDING - */ -complete: - if( status != NDIS_STATUS_PENDING ) - { - _vnic_complete_query( - p_adapter, &oid_info, status, src_buf, buf_len ); - } - - VNIC_EXIT( VNIC_DBG_OID ); - return NDIS_STATUS_PENDING; -} - - -static void -_vnic_complete_query( - IN vnic_adapter_t* const p_adapter, - IN pending_oid_t* const p_oid_info, - IN const NDIS_STATUS status, - IN const void* const p_buf, - IN const ULONG buf_len ) -{ - NDIS_STATUS oid_status = status; - - VNIC_ENTER( VNIC_DBG_OID ); - - CL_ASSERT( status != NDIS_STATUS_PENDING ); - - if( status == NDIS_STATUS_SUCCESS ) - { - if( p_oid_info->buf_len < buf_len ) - { - VNIC_TRACE( VNIC_DBG_OID, - ("Insufficient buffer space. " - "Returning NDIS_STATUS_INVALID_LENGTH.\n") ); - oid_status = NDIS_STATUS_INVALID_LENGTH; - *p_oid_info->p_bytes_needed = buf_len; - *p_oid_info->p_bytes_used = 0; - } - else if( p_oid_info->p_buf ) - { - /* Only copy if we have a distinct source buffer. */ - if( p_buf ) - { - NdisMoveMemory( p_oid_info->p_buf, p_buf, buf_len ); - *p_oid_info->p_bytes_used = buf_len; - } - } - else - { - VNIC_TRACE( VNIC_DBG_OID, - ("Returning NDIS_NOT_ACCEPTED") ); - oid_status = NDIS_STATUS_NOT_ACCEPTED; - } - } - else - { - *p_oid_info->p_bytes_used = 0; - } - - p_adapter->pending_query = FALSE; - - NdisMQueryInformationComplete( p_adapter->h_handle, oid_status ); - - VNIC_EXIT( VNIC_DBG_OID ); -} - - -static NDIS_STATUS -__vnic_get_tcp_task_offload( - IN vnic_adapter_t* p_adapter, - IN pending_oid_t* const p_oid_info ) -{ - NDIS_TASK_OFFLOAD_HEADER *p_offload_hdr; - NDIS_TASK_OFFLOAD *p_offload_task; - NDIS_TASK_TCP_IP_CHECKSUM *p_offload_chksum; - - ULONG buf_len; - uint32_t enabled_TxCsum; - uint32_t enabled_RxCsum; - - buf_len = sizeof(NDIS_TASK_OFFLOAD_HEADER) + - sizeof(NDIS_TASK_OFFLOAD) + - sizeof(NDIS_TASK_TCP_IP_CHECKSUM) - 1; - - *(p_oid_info->p_bytes_needed) = buf_len; - - if( p_oid_info->buf_len < buf_len ) - return NDIS_STATUS_INVALID_LENGTH; - - p_offload_hdr = (NDIS_TASK_OFFLOAD_HEADER*)p_oid_info->p_buf; - if( p_offload_hdr->Version != NDIS_TASK_OFFLOAD_VERSION ) - return NDIS_STATUS_INVALID_DATA; - - if( p_offload_hdr->EncapsulationFormat.Encapsulation != - IEEE_802_3_Encapsulation ) - { - return NDIS_STATUS_INVALID_DATA; - } - /* too early, we didn't get response on CMD_INIT_INIC yet */ - if( !netpath_is_connected( p_adapter->p_currentPath ) ) - { - return NDIS_STATUS_NOT_ACCEPTED; - } - enabled_RxCsum = - (uint32_t)( p_adapter->params.UseRxCsum && - netpath_canRxCsum( p_adapter->p_currentPath ) ); - - enabled_TxCsum = - (uint32_t)( p_adapter->params.UseTxCsum && - netpath_canTxCsum( p_adapter->p_currentPath ) ); - - p_offload_hdr->OffsetFirstTask = sizeof(NDIS_TASK_OFFLOAD_HEADER); - p_offload_task = (NDIS_TASK_OFFLOAD*)(p_offload_hdr + 1); - p_offload_task->Version = NDIS_TASK_OFFLOAD_VERSION; - p_offload_task->Size = sizeof(NDIS_TASK_OFFLOAD); - p_offload_task->Task = TcpIpChecksumNdisTask; - p_offload_task->OffsetNextTask = 0; - p_offload_task->TaskBufferLength = sizeof(NDIS_TASK_TCP_IP_CHECKSUM); - p_offload_chksum = - (NDIS_TASK_TCP_IP_CHECKSUM*)p_offload_task->TaskBuffer; - - p_offload_chksum->V4Transmit.IpOptionsSupported = enabled_TxCsum; - p_offload_chksum->V4Transmit.TcpOptionsSupported = enabled_TxCsum; - p_offload_chksum->V4Transmit.TcpChecksum = enabled_TxCsum; - p_offload_chksum->V4Transmit.UdpChecksum = enabled_TxCsum; - p_offload_chksum->V4Transmit.IpChecksum = enabled_TxCsum; - - p_offload_chksum->V4Receive.IpOptionsSupported = enabled_RxCsum; - p_offload_chksum->V4Receive.TcpOptionsSupported = enabled_RxCsum; - p_offload_chksum->V4Receive.TcpChecksum = enabled_RxCsum; - p_offload_chksum->V4Receive.UdpChecksum = enabled_RxCsum; - p_offload_chksum->V4Receive.IpChecksum = enabled_RxCsum; - - p_offload_chksum->V6Transmit.IpOptionsSupported = enabled_TxCsum; - p_offload_chksum->V6Transmit.TcpOptionsSupported = enabled_TxCsum; - p_offload_chksum->V6Transmit.TcpChecksum = enabled_TxCsum; - p_offload_chksum->V6Transmit.UdpChecksum = enabled_TxCsum; - - p_offload_chksum->V6Receive.IpOptionsSupported = enabled_RxCsum; - p_offload_chksum->V6Receive.TcpOptionsSupported = enabled_RxCsum; - p_offload_chksum->V6Receive.TcpChecksum = enabled_RxCsum; - p_offload_chksum->V6Receive.UdpChecksum = enabled_RxCsum; - - *(p_oid_info->p_bytes_used) = buf_len; - - return NDIS_STATUS_SUCCESS; -} - -static NDIS_STATUS -__vnic_set_tcp_task_offload( - IN vnic_adapter_t* p_adapter, - IN void* const p_info_buf, - IN ULONG* const p_info_len ) -{ - NDIS_TASK_OFFLOAD_HEADER *p_offload_hdr; - NDIS_TASK_OFFLOAD *p_offload_task; - NDIS_TASK_TCP_IP_CHECKSUM *p_offload_chksum; - - ULONG enabled_TxCsum; - ULONG enabled_RxCsum; - - VNIC_ENTER( VNIC_DBG_OID ); - - if( !netpath_is_connected( p_adapter->p_currentPath ) ) - { - return NDIS_STATUS_NOT_ACCEPTED; - } - - p_offload_hdr = (NDIS_TASK_OFFLOAD_HEADER*)p_info_buf; - - if( *p_info_len < sizeof(NDIS_TASK_OFFLOAD_HEADER) ) - return NDIS_STATUS_INVALID_LENGTH; - - if( p_offload_hdr->Version != NDIS_TASK_OFFLOAD_VERSION ) - return NDIS_STATUS_INVALID_DATA; - - if( p_offload_hdr->Size != sizeof(NDIS_TASK_OFFLOAD_HEADER) ) - return NDIS_STATUS_INVALID_LENGTH; - - if( !p_offload_hdr->OffsetFirstTask ) - return NDIS_STATUS_SUCCESS; - - if( p_offload_hdr->EncapsulationFormat.Encapsulation != - IEEE_802_3_Encapsulation ) - { - return NDIS_STATUS_INVALID_DATA; - } - - p_offload_task = (NDIS_TASK_OFFLOAD*) - (((UCHAR*)p_offload_hdr) + p_offload_hdr->OffsetFirstTask); - - if( *p_info_len < sizeof(NDIS_TASK_OFFLOAD_HEADER) + - offsetof( NDIS_TASK_OFFLOAD, TaskBuffer ) + - sizeof(NDIS_TASK_TCP_IP_CHECKSUM) ) - { - return NDIS_STATUS_INVALID_LENGTH; - } - - if( p_offload_task->Version != NDIS_TASK_OFFLOAD_VERSION ) - return NDIS_STATUS_INVALID_DATA; - p_offload_chksum = - (NDIS_TASK_TCP_IP_CHECKSUM*)p_offload_task->TaskBuffer; - - enabled_TxCsum = - ( p_adapter->params.UseTxCsum && - netpath_canTxCsum( p_adapter->p_currentPath ) ); - enabled_RxCsum = - ( p_adapter->params.UseRxCsum && - netpath_canRxCsum( p_adapter->p_currentPath ) ); - - if( !enabled_TxCsum && - (p_offload_chksum->V4Transmit.IpOptionsSupported || - p_offload_chksum->V4Transmit.TcpOptionsSupported || - p_offload_chksum->V4Transmit.TcpChecksum || - p_offload_chksum->V4Transmit.UdpChecksum || - p_offload_chksum->V4Transmit.IpChecksum || - p_offload_chksum->V6Transmit.IpOptionsSupported || - p_offload_chksum->V6Transmit.TcpOptionsSupported || - p_offload_chksum->V6Transmit.TcpChecksum || - p_offload_chksum->V6Transmit.UdpChecksum ) ) - { - return NDIS_STATUS_NOT_SUPPORTED; - } - - if( !enabled_RxCsum && - (p_offload_chksum->V4Receive.IpOptionsSupported || - p_offload_chksum->V4Receive.TcpOptionsSupported || - p_offload_chksum->V4Receive.TcpChecksum || - p_offload_chksum->V4Receive.UdpChecksum || - p_offload_chksum->V4Receive.IpChecksum || - p_offload_chksum->V6Receive.IpOptionsSupported || - p_offload_chksum->V6Receive.TcpOptionsSupported || - p_offload_chksum->V6Receive.TcpChecksum || - p_offload_chksum->V6Receive.UdpChecksum ) ) - { - return NDIS_STATUS_NOT_SUPPORTED; - } - - VNIC_EXIT( VNIC_DBG_OID ); - - return NDIS_STATUS_SUCCESS; -} - - -//! Issues a hardware reset to the NIC and/or resets the driver's software state. -/* Tear down the connection and start over again. This is only called when there is a problem. -For example, if a send, query info, or set info had a time out. MiniportCheckForHang will -be called first. -IRQL = DISPATCH_LEVEL - -@param p_addr_resetPointer to BOOLLEAN that is set to TRUE if the NDIS -library should call MiniportSetInformation to restore addressing information to the current values. -@param adapter_context The adapter context allocated at start -@return NDIS_STATUS_SUCCESS, NDIS_STATUS_PENDING, NDIS_STATUS_NOT_RESETTABLE, -NDIS_STATUS_RESET_IN_PROGRESS, NDIS_STATUS_SOFT_ERRORS, NDIS_STATUS_HARD_ERRORS -*/ -NDIS_STATUS -vnic_reset( - OUT PBOOLEAN p_addr_reset, - IN NDIS_HANDLE adapter_context) -{ - vnic_adapter_t* p_adapter; - ib_api_status_t status; - - VNIC_ENTER( VNIC_DBG_INIT ); - - CL_ASSERT( p_addr_reset ); - CL_ASSERT( adapter_context ); - - p_adapter = (vnic_adapter_t*)adapter_context; - - status = adapter_reset( p_adapter ); - VNIC_EXIT( VNIC_DBG_INIT ); - switch( status ) - { - case IB_SUCCESS: - *p_addr_reset = TRUE; - return NDIS_STATUS_SUCCESS; - - case IB_NOT_DONE: - return NDIS_STATUS_PENDING; - - case IB_INVALID_STATE: - return NDIS_STATUS_RESET_IN_PROGRESS; - - default: - return NDIS_STATUS_HARD_ERRORS; - } -} - -//! Request changes in the state information that the miniport driver maintains -/* For example, this is used to set multicast addresses and the packet filter. -IRQL = DISPATCH_LEVEL - -@param adapter_context The adapter context allocated at start -@param oid Object ID representing the set operation to be carried out -@param info_buf Buffer containing input for this set and location for any output -@param info_buf_len Number of bytes available in info_buf -@param p_bytes_read Pointer to number of bytes read from info_buf -@param p_bytes_needed Pointer to number of bytes needed to satisfy this oid -@return NDIS_STATUS_SUCCESS, NDIS_STATUS_PENDING, NDIS_STATUS_INVALID_OID, -NDIS_STATUS_INVALID_LENGTH, NDIS_STATUS_INVALID_DATA, NDIS_STATUS_NOT_ACCEPTED, -NDIS_STATUS_NOT_SUPPORTED, NDIS_STATUS_RESOURCES -*/ -NDIS_STATUS -vnic_oid_set_info( - IN NDIS_HANDLE adapter_context, - IN NDIS_OID oid, - IN PVOID info_buf, - IN ULONG info_buf_len, - OUT PULONG p_bytes_read, - OUT PULONG p_bytes_needed ) -{ - vnic_adapter_t* p_adapter; - Netpath_t* p_netpath; - NDIS_STATUS status; - ULONG buf_len; - pending_oid_t oid_info; - - VNIC_ENTER( VNIC_DBG_OID ); - - CL_ASSERT( adapter_context ); - p_adapter = (vnic_adapter_t*)adapter_context; - p_netpath= p_adapter->p_currentPath; - - CL_ASSERT( p_bytes_read ); - CL_ASSERT( p_bytes_needed ); - CL_ASSERT( !p_adapter->pending_set ); - - status = NDIS_STATUS_SUCCESS; - *p_bytes_needed = 0; - buf_len = sizeof(ULONG); - - oid_info.oid = oid; - oid_info.p_buf = info_buf; - oid_info.buf_len = info_buf_len; - oid_info.p_bytes_used = p_bytes_read; - oid_info.p_bytes_needed = p_bytes_needed; - - /* do not set anything until IB path initialized and NIC is enabled */ - if( !p_adapter->p_currentPath->carrier ) - { - *p_bytes_read = 0; - return NDIS_STATUS_NOT_ACCEPTED; - } - - switch( oid ) - { - /* Required General */ - case OID_GEN_CURRENT_PACKET_FILTER: - VNIC_TRACE( VNIC_DBG_OID, - (" IOC %d received set for OID_GEN_CURRENT_PACKET_FILTER, %#x\n", - p_adapter->p_currentPath->pViport->ioc_num, - *(uint32_t*)info_buf )); -// if ( !p_adapter->p_currentPath->carrier ) -// { -// status = NDIS_STATUS_NOT_ACCEPTED; -// break; -// } - if( info_buf_len < sizeof( p_adapter->packet_filter ) ) - { - status = NDIS_STATUS_INVALID_LENGTH; - } - else if( !info_buf ) - { - status = NDIS_STATUS_INVALID_DATA; - } - else - { - p_adapter->set_oid = oid_info; - status = _vnic_process_packet_filter( p_adapter, *((ULONG*)info_buf) ); - } - break; - - case OID_GEN_CURRENT_LOOKAHEAD: - VNIC_TRACE( VNIC_DBG_OID, - (" received set for OID_GEN_CURRENT_LOOKAHEAD\n" )); - if( info_buf_len < buf_len ) - status = NDIS_STATUS_INVALID_LENGTH; - break; - - case OID_GEN_PROTOCOL_OPTIONS: - VNIC_TRACE( VNIC_DBG_OID, - (" received set for OID_GEN_PROTOCOL_OPTIONS\n" )); - if( info_buf_len < buf_len ) - status = NDIS_STATUS_INVALID_LENGTH; - break; - -#ifdef NDIS51_MINIPORT - case OID_GEN_MACHINE_NAME: - VNIC_TRACE( VNIC_DBG_OID, - (" received set for OID_GEN_MACHINE_NAME\n" ) ); - if( info_buf_len < buf_len ) - status = NDIS_STATUS_INVALID_LENGTH; - // else - // status = __vnic_set_machine_name( info_buf, - // (USHORT)info_buf_len ); - break; -#endif - - /* Required Ethernet operational characteristics */ - case OID_802_3_MULTICAST_LIST: - if( !p_adapter->p_currentPath->carrier ) - { - status = NDIS_STATUS_NOT_ACCEPTED; - break; - } - VNIC_TRACE( VNIC_DBG_OID, - (" IOC %d received set for OID_802_3_MULTICAST_LIST\n", - p_adapter->p_currentPath->pViport->ioc_num ) ); - if( info_buf_len > MAX_MCAST * sizeof(mac_addr_t) ) - { - VNIC_TRACE( VNIC_DBG_OID, - (" OID_802_3_MULTICAST_LIST - Multicast list full.\n" ) ); - status = NDIS_STATUS_MULTICAST_FULL; - *p_bytes_needed = MAX_MCAST * sizeof(mac_addr_t); - } - else if( info_buf_len % sizeof(mac_addr_t) ) - { - VNIC_TRACE( VNIC_DBG_OID, - (" OID_802_3_MULTICAST_LIST - Invalid input buffer length.\n" ) ); - status = NDIS_STATUS_INVALID_DATA; - } - else if( info_buf == NULL && info_buf_len != 0 ) - { - VNIC_TRACE( VNIC_DBG_OID, - (" OID_802_3_MULTICAST_LIST - Invalid input buffer.\n" ) ); - status = NDIS_STATUS_INVALID_DATA; - } - else - { - p_adapter->set_oid = oid_info; - status = adapter_set_mcast( p_adapter, (mac_addr_t*)info_buf, - (uint8_t)(info_buf_len / sizeof(mac_addr_t)) ); - } - break; - - case OID_TCP_TASK_OFFLOAD: - VNIC_TRACE( VNIC_DBG_OID, - (" received set for OID_TCP_TASK_OFFLOAD\n" ) ); - buf_len = info_buf_len; - status = __vnic_set_tcp_task_offload( p_adapter, info_buf, &buf_len ); - break; - - /* Optional General */ - case OID_GEN_TRANSPORT_HEADER_OFFSET: - VNIC_TRACE( VNIC_DBG_OID, - ("Set for OID_GEN_TRANSPORT_HEADER_OFFSET\n") ); - break; - case OID_GEN_VLAN_ID: - if( info_buf_len != 4 ) - { - status = NDIS_STATUS_INVALID_LENGTH; - break; - } - if( *(( uint32_t *)info_buf) < 4095 ) - { - p_adapter->vlan_info = *((uint32_t*)info_buf ); - } - else - { - status = NDIS_STATUS_INVALID_DATA; - } - break; - - case OID_GEN_SUPPORTED_LIST: - case OID_GEN_HARDWARE_STATUS: - case OID_GEN_MEDIA_SUPPORTED: - case OID_GEN_MEDIA_IN_USE: - case OID_GEN_MAXIMUM_FRAME_SIZE: - case OID_GEN_LINK_SPEED: - case OID_GEN_TRANSMIT_BUFFER_SPACE: - case OID_GEN_RECEIVE_BUFFER_SPACE: - case OID_GEN_MAXIMUM_LOOKAHEAD: - case OID_GEN_TRANSMIT_BLOCK_SIZE: - case OID_GEN_RECEIVE_BLOCK_SIZE: - case OID_GEN_MAXIMUM_TOTAL_SIZE: - case OID_GEN_VENDOR_ID: - case OID_GEN_VENDOR_DESCRIPTION: - case OID_GEN_VENDOR_DRIVER_VERSION: - case OID_GEN_DRIVER_VERSION: - case OID_GEN_MAC_OPTIONS: - case OID_GEN_MEDIA_CONNECT_STATUS: - case OID_GEN_MAXIMUM_SEND_PACKETS: - case OID_GEN_SUPPORTED_GUIDS: - case OID_GEN_PHYSICAL_MEDIUM: - default: - status = NDIS_STATUS_INVALID_OID; - VNIC_TRACE( VNIC_DBG_OID, - (" received an invalid oid of 0x%.8X!\n" , oid)); - break; - } - - if( status == NDIS_STATUS_SUCCESS ) - { - *p_bytes_read = buf_len; - } - else - { - if( status == NDIS_STATUS_INVALID_LENGTH ) - { - if ( !*p_bytes_needed ) - { - *p_bytes_needed = buf_len; - } - } - - *p_bytes_read = 0; - } - - VNIC_EXIT( VNIC_DBG_OID ); - return status; -} - - -//! Transfers some number of packets, specified as an array of packet pointers, over the network. -/* For a deserialized driver, these packets are completed asynchronously -using NdisMSendComplete. -IRQL <= DISPATCH_LEVEL - -@param adapter_context Pointer to vnic_adapter_t structure with per NIC state -@param packet_array Array of packets to send -@param numPackets Number of packets in the array -*/ -void -vnic_send_packets( - IN NDIS_HANDLE adapter_context, - IN PPNDIS_PACKET packet_array, - IN UINT num_packets ) -{ - vnic_adapter_t* const p_adapter =(vnic_adapter_t* const )adapter_context; - UINT packet_num; - - VNIC_ENTER( VNIC_DBG_SEND ); - - CL_ASSERT( adapter_context ); - - for( packet_num = 0; packet_num < num_packets; ++packet_num ) - { - netpath_xmitPacket( p_adapter->p_currentPath, - packet_array[packet_num] ); - } - VNIC_EXIT( VNIC_DBG_SEND ); -} - -void vnic_cancel_xmit( - IN NDIS_HANDLE adapter_context, - IN PVOID cancel_id ) -{ - vnic_adapter_t* const p_adapter =(vnic_adapter_t* const )adapter_context; - - if( p_adapter && - p_adapter->p_currentPath ) - { - netpath_cancel_xmit( p_adapter->p_currentPath, cancel_id ); - } -} - -void -vnic_pnp_notify( - IN NDIS_HANDLE adapter_context, - IN NDIS_DEVICE_PNP_EVENT pnp_event, - IN PVOID info_buf, - IN ULONG info_buf_len ) -{ - vnic_adapter_t *p_adapter; - - VNIC_ENTER( VNIC_DBG_PNP ); - - UNUSED_PARAM( info_buf ); - UNUSED_PARAM( info_buf_len ); - - p_adapter = (vnic_adapter_t*)adapter_context; - - CL_ASSERT( p_adapter ); - - VNIC_TRACE( VNIC_DBG_PNP, ("Event %d for IOC[%d] in state %#x\n", - pnp_event, p_adapter->ioc_num, p_adapter->pnp_state ) ); - - switch ( pnp_event ) - { - case NdisDevicePnPEventPowerProfileChanged: - break; - case NdisDevicePnPEventQueryRemoved: - case NdisDevicePnPEventRemoved: - case NdisDevicePnPEventSurpriseRemoved: - case NdisDevicePnPEventQueryStopped: - case NdisDevicePnPEventStopped: - case NdisDevicePnPEventMaximum: - - if( InterlockedExchange( (volatile LONG*)&p_adapter->pnp_state, IB_PNP_IOC_REMOVE ) == IB_PNP_IOC_ADD ) - { - if( netpath_is_valid( p_adapter->p_currentPath ) ) - { - netpath_stopXmit( p_adapter->p_currentPath ); - InterlockedExchange( &p_adapter->p_currentPath->carrier, (LONG)FALSE ); - netpath_linkDown( p_adapter->p_currentPath ); - __pending_queue_cleanup( p_adapter ); - } - } - vnic_resume_oids( p_adapter ); - break; - } - - VNIC_EXIT( VNIC_DBG_PNP ); -} - - -void -vnic_shutdown( - IN PVOID adapter_context ) -{ - vnic_adapter_t *p_adapter; - Netpath_t *p_netpath; - - VNIC_ENTER( VNIC_DBG_INIT ); - p_adapter = (vnic_adapter_t *)adapter_context; - - if( p_adapter ) - { - g_vnic.shutdown = p_adapter->ioc_num; - VNIC_TRACE( VNIC_DBG_INIT, - ("IOC[%d] going to Shutdown\n", p_adapter->ioc_num )); - p_netpath = p_adapter->p_currentPath; - - if( p_netpath && p_netpath->pViport ) - { - netpath_stopXmit( p_netpath ); - InterlockedExchange( &p_netpath->carrier, (LONG)FALSE ); - netpath_linkDown( p_netpath ); - } - - vnic_destroy_adapter( p_adapter ); - } - - VNIC_EXIT( VNIC_DBG_INIT ); -} - - -void -vnic_resume_set_oids( - IN vnic_adapter_t* const p_adapter ) -{ - NDIS_STATUS status = NDIS_STATUS_SUCCESS; - BOOLEAN pending_set; - pending_oid_t set_oid = {0}; - - Netpath_t* p_netpath; - VNIC_ENTER( VNIC_DBG_OID ); - - if( !p_adapter->pending_set ) - { - VNIC_EXIT( VNIC_DBG_OID ); - return; - } - NdisAcquireSpinLock( &p_adapter->lock ); - p_netpath = p_adapter->p_currentPath; - VNIC_TRACE( VNIC_DBG_OID, - ("IOC[%d]Resume Set OID %#x\n", - p_adapter->ioc_num, p_adapter->set_oid.oid )); - /* - * Set the status depending on our state. Fail OID requests that - * are pending while we reset the adapter. - */ - if( p_adapter->pnp_state != IB_PNP_IOC_REMOVE && - netpath_is_connected( p_netpath ) ) - { - status = NDIS_STATUS_SUCCESS; - } - else - { - status = NDIS_STATUS_NOT_ACCEPTED; - if( p_adapter->pending_set ) - { - VNIC_TRACE( VNIC_DBG_PNP, - ("IOC[%d]Pending set OID %#x while removing \n", - p_adapter->ioc_num, p_adapter->set_oid.oid )); - } - } - - pending_set = p_adapter->pending_set; - if( pending_set ) - { - set_oid = p_adapter->set_oid; - p_adapter->pending_set = FALSE; - } - NdisReleaseSpinLock( &p_adapter->lock ); - - ASSERT( KeGetCurrentIrql() == DISPATCH_LEVEL ); - - if( pending_set && status == NDIS_STATUS_SUCCESS ) - { - switch( set_oid.oid ) - { - case OID_GEN_CURRENT_PACKET_FILTER: - VNIC_TRACE( VNIC_DBG_OID, - (" IOC %d resume PACKET_FILTER set \n", - p_netpath->pViport->ioc_num ) ); - /* Validation already performed in the SetInformation path. */ - p_adapter->packet_filter = *(PULONG)set_oid.p_buf; - break; - - case OID_GEN_MACHINE_NAME: - status = __vnic_set_machine_name ( p_adapter->set_oid.p_buf, (USHORT)p_adapter->set_oid.buf_len ); - break; - - case OID_802_3_MULTICAST_LIST: - VNIC_TRACE( VNIC_DBG_OID, - (" IOC %d resume MULTICAST_LIST\n", - p_netpath->pViport->ioc_num ) ); - break; - - default: - CL_ASSERT( set_oid.oid && 0 ); - break; - } - } - - if( !netpath_is_connected( p_netpath ) ) - { - NdisMSetInformationComplete( p_adapter->h_handle, - NDIS_STATUS_NOT_ACCEPTED ); - } - else - NdisMSetInformationComplete( p_adapter->h_handle, status ); - - VNIC_EXIT( VNIC_DBG_OID ); -} - - -void -vnic_resume_oids( - IN vnic_adapter_t* const p_adapter ) -{ - ULONG info; - NDIS_STATUS status = NDIS_STATUS_SUCCESS; - BOOLEAN pending_query; - pending_oid_t query_oid = {0}; - KIRQL irql; - - Netpath_t* p_netpath = p_adapter->p_currentPath; - - uint8_t mac[HW_ADDR_LEN]; - - VNIC_ENTER( VNIC_DBG_OID ); - - NdisAcquireSpinLock( &p_adapter->lock ); - /* - * Set the status depending on our state. Fail OID requests that - * are pending while we reset the adapter. - */ - if( !netpath_is_connected( p_netpath ) ) - { - status = NDIS_STATUS_NOT_ACCEPTED; - } - - switch( p_adapter->pnp_state ) - { - case IB_PNP_IOC_ADD: - break; - - case IB_PNP_IOC_REMOVE: - default: - status = NDIS_STATUS_NOT_ACCEPTED; - break; - } - - pending_query = p_adapter->pending_query; - - if( pending_query ) - { - query_oid = p_adapter->query_oid; - p_adapter->pending_query = FALSE; - } - NdisReleaseSpinLock( &p_adapter->lock ); - - KeRaiseIrql( DISPATCH_LEVEL, &irql ); - - /* - * If we had a pending OID request for OID_GEN_LINK_SPEED, - * complete it now. Note that we hold the object lock since - * NdisMQueryInformationComplete is called at DISPATCH_LEVEL. - */ - if( pending_query ) - { - switch( query_oid.oid ) - { - case OID_802_3_CURRENT_ADDRESS: - case OID_802_3_PERMANENT_ADDRESS: - if ( status == NDIS_STATUS_SUCCESS ) - { - cl_memcpy( mac, p_netpath->pViport->hwMacAddress, HW_ADDR_LEN ); - } - _vnic_complete_query( p_adapter, - &query_oid, - status, - mac, - HW_ADDR_LEN ); - break; - case OID_GEN_LINK_SPEED: - info = DEFAULT_LINK_SPEED_x100BPS; - _vnic_complete_query( p_adapter, - &query_oid, - status, - &info, - sizeof( info ) ); - break; - - case OID_GEN_MEDIA_CONNECT_STATUS: - info = ( p_adapter->carrier )? NdisMediaStateConnected : - NdisMediaStateDisconnected; - _vnic_complete_query( p_adapter, - &query_oid, - status, - &info, - sizeof( info ) ); - break; - case OID_802_3_MULTICAST_LIST: - _vnic_complete_query( p_adapter, - &query_oid, - status, - p_netpath->p_adapter->mcast_array, - p_adapter->mc_count * sizeof( mac_addr_t ) ); - break; - case OID_GEN_TRANSMIT_BUFFER_SPACE: - if( status == NDIS_STATUS_SUCCESS ) - { - info = p_netpath->pViport->data.xmitPool.bufferSz * - p_netpath->pViport->data.xmitPool.numXmitBufs; - } - else - { - info = 0; - } - _vnic_complete_query( p_adapter, - &query_oid, - status, - &info, - sizeof( info ) ); - break; - case OID_GEN_RECEIVE_BUFFER_SPACE: - if( status == NDIS_STATUS_SUCCESS ) - { - info = p_netpath->pViport->data.recvPool.bufferSz * - p_netpath->pViport->data.recvPool.poolSz; - } - else - { - info = 0; - } - _vnic_complete_query( p_adapter, - &query_oid, - status, - &info, - sizeof( info ) ); - break; - default: - CL_ASSERT( query_oid.oid == OID_GEN_LINK_SPEED || - query_oid.oid == OID_GEN_MEDIA_CONNECT_STATUS || - query_oid.oid == OID_802_3_MULTICAST_LIST || - query_oid.oid == OID_802_3_CURRENT_ADDRESS || - query_oid.oid == OID_802_3_PERMANENT_ADDRESS || - query_oid.oid == OID_GEN_RECEIVE_BUFFER_SPACE || - query_oid.oid == OID_GEN_TRANSMIT_BUFFER_SPACE ); - break; - } - } - - vnic_resume_set_oids( p_adapter ); - - KeLowerIrql( irql ); - - VNIC_EXIT( VNIC_DBG_OID ); -} - -static NDIS_STATUS -__vnic_set_machine_name( - IN VOID *p_uni_array, - IN USHORT buf_size ) -{ - NDIS_STATUS status = NDIS_STATUS_SUCCESS; - uint8_t *p_src_buf = (uint8_t *)p_uni_array; - uint32_t i; - - VNIC_ENTER( VNIC_DBG_OID ); - - if( buf_size > 0 ) - { - cl_memclr(g_vnic.host_name, sizeof( g_vnic.host_name ) ); - for( i = 0; i < min( ( buf_size > 1 ), sizeof( g_vnic.host_name ) ); i++ ) - { - g_vnic.host_name[i] = *(p_src_buf + i*2); - } - } - - return status; -} - -static void -__vnic_read_machine_name( void ) -{ - /* this code is borrowed from the bus_driver */ - - NTSTATUS nt_status; - /* Remember the terminating entry in the table below. */ - RTL_QUERY_REGISTRY_TABLE table[2]; - UNICODE_STRING hostNamePath; - UNICODE_STRING hostNameW; - ANSI_STRING hostName; - - VNIC_ENTER( VNIC_DBG_INIT ); - - /* Get the host name. */ - RtlInitUnicodeString( &hostNamePath, L"ComputerName\\ComputerName" ); - RtlInitUnicodeString( &hostNameW, NULL ); - - /* - * Clear the table. This clears all the query callback pointers, - * and sets up the terminating table entry. - */ - cl_memclr( table, sizeof(table) ); - - /* Setup the table entries. */ - table[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; - table[0].Name = L"ComputerName"; - table[0].EntryContext = &hostNameW; - table[0].DefaultType = REG_SZ; - table[0].DefaultData = &hostNameW; - table[0].DefaultLength = 0; - - /* Have at it! */ - nt_status = RtlQueryRegistryValues( RTL_REGISTRY_CONTROL, - hostNamePath.Buffer, table, NULL, NULL ); - if( NT_SUCCESS( nt_status ) ) - { - /* Convert the UNICODE host name to UTF-8 (ASCII). */ - hostName.Length = 0; - hostName.MaximumLength = sizeof(g_vnic.host_name) - 1; - hostName.Buffer = (PCHAR)g_vnic.host_name; - nt_status = RtlUnicodeStringToAnsiString( &hostName, &hostNameW, FALSE ); - RtlFreeUnicodeString( &hostNameW ); - } - else - { - VNIC_TRACE(VNIC_DBG_ERROR , ("Failed to get host name from registry\n") ); - /* Use the default name... */ - cl_memcpy( g_vnic.host_name, - DEFAULT_HOST_NAME, - min (sizeof( g_vnic.host_name), sizeof(DEFAULT_HOST_NAME) ) ); - } - - VNIC_EXIT( VNIC_DBG_INIT ); -} - -/* function: usec_timer_start - uses cl_timer* functionality (init/destroy/stop/start ) - except it takes expiration time parameter in microseconds. -*/ -cl_status_t -usec_timer_start( - IN cl_timer_t* const p_timer, - IN const uint32_t time_usec ) -{ - LARGE_INTEGER due_time; - - CL_ASSERT( p_timer ); - CL_ASSERT( p_timer->pfn_callback ); - CL_ASSERT( KeGetCurrentIrql() <= DISPATCH_LEVEL ); - - /* Due time is in 100 ns increments. Negative for relative time. */ - due_time.QuadPart = -(int64_t)(((uint64_t)time_usec) * 10); - - /* Store the timeout time in the timer object. in microseconds */ - p_timer->timeout_time = cl_get_time_stamp() + (((uint64_t)time_usec)); - - KeSetTimer( &p_timer->timer, due_time, &p_timer->dpc ); - return( CL_SUCCESS ); -} - - -static NDIS_STATUS -_vnic_process_packet_filter( - IN vnic_adapter_t* const p_adapter, - IN ULONG pkt_filter ) -{ - NDIS_STATUS status = NDIS_STATUS_SUCCESS; - viport_t *p_viport; - ULONG need_updates = 0; - - VNIC_ENTER(VNIC_DBG_FUNC ); - - ASSERT( p_adapter ); - - p_viport = p_adapter->p_currentPath->pViport; - - ASSERT( p_viport ); - ASSERT( !( p_viport->updates & SYNC_QUERY ) ); - - if( ( InterlockedExchange( - (volatile LONG*)&p_adapter->packet_filter, pkt_filter )) == (LONG)pkt_filter ) - { - InterlockedExchange( &p_viport->updates, 0 ); - return status; - } - - ASSERT( (p_viport->updates & ~MCAST_OVERFLOW) == 0 ); - - if( pkt_filter ) - { - if( !( p_viport->flags & INIC_FLAG_ENABLE_NIC ) ) - { - p_viport->newFlags &= ~INIC_FLAG_DISABLE_NIC; - p_viport->newFlags |= INIC_FLAG_ENABLE_NIC | INIC_FLAG_SET_MTU; - p_viport->newMtu = (uint16_t)p_adapter->params.MinMtu; - InterlockedOr( (volatile LONG*)&need_updates, NEED_LINK_CONFIG ); - } - - if( pkt_filter & NDIS_PACKET_TYPE_ALL_MULTICAST ) - { - if( !( p_viport->flags & INIC_FLAG_ENABLE_MCAST_ALL ) ) - { - p_viport->newFlags &= ~INIC_FLAG_DISABLE_MCAST_ALL; - p_viport->newFlags |= INIC_FLAG_ENABLE_MCAST_ALL; - InterlockedOr( (volatile LONG*)&need_updates, - NEED_LINK_CONFIG | MCAST_OVERFLOW ); - } - } - else - { - if( p_viport->flags & NDIS_PACKET_TYPE_ALL_MULTICAST ) - { - p_viport->newFlags &= ~INIC_FLAG_ENABLE_MCAST_ALL; - p_viport->newFlags |= INIC_FLAG_DISABLE_MCAST_ALL; - InterlockedOr( (volatile LONG*)&need_updates, NEED_LINK_CONFIG ); - } - } - - if ( pkt_filter & NDIS_PACKET_TYPE_PROMISCUOUS ) - { - if( !( p_viport->flags & INIC_FLAG_ENABLE_PROMISC ) ) - { - p_viport->newFlags &= ~INIC_FLAG_DISABLE_PROMISC; - p_viport->newFlags |= INIC_FLAG_ENABLE_PROMISC; - InterlockedOr( (volatile LONG*)&need_updates, NEED_LINK_CONFIG ); - } - } - else - { - if( p_viport->flags & INIC_FLAG_ENABLE_PROMISC ) - { - p_viport->newFlags &= ~INIC_FLAG_ENABLE_PROMISC; - p_viport->newFlags |= INIC_FLAG_DISABLE_PROMISC; - InterlockedOr( (volatile LONG*)&need_updates, NEED_LINK_CONFIG ); - } - } - } - - /* ENABLE NIC, BROADCAST and MULTICAST flags set on start */ - if( need_updates ) - { - p_adapter->pending_set = TRUE; - InterlockedOr( &p_viport->updates, need_updates ); - - status = _viport_process_query( p_viport, FALSE ); - VNIC_TRACE( VNIC_DBG_OID, - ("LINK CONFIG status %x\n", status )); - if( status != NDIS_STATUS_PENDING ) - { - p_adapter->pending_set = FALSE; - } - } - - VNIC_EXIT( VNIC_DBG_FUNC ); - return status; -} - -static NTSTATUS -__vnic_read_service_registry( - IN UNICODE_STRING* const p_registry_path ) -{ - NTSTATUS status; - RTL_QUERY_REGISTRY_TABLE table[VNIC_REGISTRY_TBL_SIZE + 1]; - UNICODE_STRING param_path; - ULONG _reg_dbg_lvl = 0; - int i; - - RtlInitUnicodeString( ¶m_path, NULL ); - param_path.MaximumLength = - p_registry_path->Length + sizeof(L"\\Parameters"); - - param_path.Buffer = cl_zalloc( param_path.MaximumLength ); - if( !param_path.Buffer ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("Failed to allocate parameters path buffer.\n") ); - return STATUS_INSUFFICIENT_RESOURCES; - } - - RtlAppendUnicodeStringToString( ¶m_path, p_registry_path ); - RtlAppendUnicodeToString( ¶m_path, L"\\Parameters" ); - - cl_memclr( table, sizeof(table) ); - - /* init debug flags entry */ - table[0].Flags = RTL_QUERY_REGISTRY_DIRECT; - table[0].Name = L"DebugFlags"; - table[0].EntryContext = &_reg_dbg_lvl; - table[0].DefaultType = REG_DWORD; - table[0].DefaultData = &_reg_dbg_lvl; - table[0].DefaultLength = sizeof(ULONG); - - /* Setup the rest of table entries. */ - for ( i = 1; i < VNIC_REGISTRY_TBL_SIZE; i++ ) - { - table[i].Flags = RTL_QUERY_REGISTRY_DIRECT; - table[i].Name = reg_array[i].name; - table[i].EntryContext = ®_array[i].value; - table[i].DefaultType = REG_DWORD; - table[i].DefaultData = ®_array[i].value; - table[i].DefaultLength = sizeof(ULONG); - } - - status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE, - param_path.Buffer, table, NULL, NULL ); - - if( status == STATUS_SUCCESS ) - { - g_vnic_dbg_lvl |= _reg_dbg_lvl; - VNIC_TRACE(VNIC_DBG_INFO, ("DebugFlags Set %#x\n",g_vnic_dbg_lvl )); - g_vnic.p_params = reg_array; - } - - cl_free( param_path.Buffer ); - - return status; -} diff --git a/trunk/ulp/qlc_vnic/kernel/vnic_driver.h b/trunk/ulp/qlc_vnic/kernel/vnic_driver.h deleted file mode 100644 index fe1ab950..00000000 --- a/trunk/ulp/qlc_vnic/kernel/vnic_driver.h +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright (c) 2007 QLogic Corporation. All rights reserved. - * - * This software is available to you under the OpenIB.org BSD license - * below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * $Id$ - */ - -#ifndef _VNIC_DRIVER_H_ -#define _VNIC_DRIVER_H_ - -#include "vnic_adapter.h" -#include "vnic_debug.h" - - -#if defined(NDIS50_MINIPORT) -#define MAJOR_NDIS_VERSION 5 -#define MINOR_NDIS_VERSION 0 -#elif defined (NDIS51_MINIPORT) -#define MAJOR_NDIS_VERSION 5 -#define MINOR_NDIS_VERSION 1 -#else -#error NDIS Version not defined, try defining NDIS50_MINIPORT or NDIS51_MINIPORT -#endif - -#include - -static const NDIS_OID SUPPORTED_OIDS[] = -{ - OID_GEN_SUPPORTED_LIST, - OID_GEN_HARDWARE_STATUS, - OID_GEN_MEDIA_SUPPORTED, - OID_GEN_MEDIA_IN_USE, - OID_GEN_MAXIMUM_LOOKAHEAD, - OID_GEN_MAXIMUM_FRAME_SIZE, - OID_GEN_LINK_SPEED, - OID_GEN_TRANSMIT_BUFFER_SPACE, - OID_GEN_RECEIVE_BUFFER_SPACE, - OID_GEN_TRANSMIT_BLOCK_SIZE, - OID_GEN_RECEIVE_BLOCK_SIZE, - OID_GEN_VENDOR_ID, - OID_GEN_VENDOR_DESCRIPTION, - OID_GEN_CURRENT_PACKET_FILTER, - OID_GEN_CURRENT_LOOKAHEAD, - OID_GEN_DRIVER_VERSION, - OID_GEN_MAXIMUM_TOTAL_SIZE, - OID_GEN_PROTOCOL_OPTIONS, // ? - OID_GEN_MAC_OPTIONS, - OID_GEN_MEDIA_CONNECT_STATUS, - OID_GEN_MAXIMUM_SEND_PACKETS, - OID_GEN_VENDOR_DRIVER_VERSION, - OID_GEN_PHYSICAL_MEDIUM, - OID_GEN_XMIT_OK, - OID_GEN_RCV_OK, - OID_GEN_XMIT_ERROR, - OID_GEN_RCV_ERROR, - OID_GEN_RCV_NO_BUFFER, - OID_GEN_DIRECTED_BYTES_XMIT, - OID_GEN_DIRECTED_FRAMES_XMIT, - OID_GEN_MULTICAST_BYTES_XMIT, - OID_GEN_MULTICAST_FRAMES_XMIT, - OID_GEN_BROADCAST_BYTES_XMIT, - OID_GEN_BROADCAST_FRAMES_XMIT, - OID_GEN_DIRECTED_BYTES_RCV, - OID_GEN_DIRECTED_FRAMES_RCV, - OID_GEN_MULTICAST_BYTES_RCV, - OID_GEN_MULTICAST_FRAMES_RCV, - OID_GEN_BROADCAST_BYTES_RCV, - OID_GEN_BROADCAST_FRAMES_RCV, - OID_GEN_VLAN_ID, - OID_802_3_PERMANENT_ADDRESS, - OID_802_3_CURRENT_ADDRESS, - OID_802_3_MULTICAST_LIST, - OID_802_3_MAXIMUM_LIST_SIZE, - OID_802_3_MAC_OPTIONS, - OID_802_3_RCV_ERROR_ALIGNMENT, - OID_802_3_XMIT_ONE_COLLISION, - OID_802_3_XMIT_MORE_COLLISIONS, - OID_TCP_TASK_OFFLOAD -}; - -static const unsigned char VENDOR_ID[] = {0x00, 0x06, 0x6A, 0x00}; -#define VENDOR_DESCRIPTION "Virtual Ethernet over InfiniBand" -#define DEFAULT_VNIC_NAME "VNIC" - -NTSTATUS -DriverEntry( - IN PDRIVER_OBJECT p_drv_obj, - IN PUNICODE_STRING p_reg_path ); - -VOID -vnic_unload( - IN PDRIVER_OBJECT p_drv_obj ); - -NDIS_STATUS -vnic_initialize( - OUT PNDIS_STATUS p_open_err_status, - OUT PUINT p_selected_medium_index, - IN PNDIS_MEDIUM medium_array, - IN UINT medium_array_size, - IN NDIS_HANDLE h_handle, - IN NDIS_HANDLE wrapper_configuration_context ); - -BOOLEAN -vnic_check_for_hang( - IN NDIS_HANDLE adapter_context ); - -void -vnic_halt( - IN NDIS_HANDLE adapter_context ); - -NDIS_STATUS -vnic_oid_query_info( - IN NDIS_HANDLE adapter_context, - IN NDIS_OID oid, - IN PVOID info_buf, - IN ULONG info_buf_len, - OUT PULONG p_bytes_written, - OUT PULONG p_bytes_needed ); - -NDIS_STATUS -vnic_reset( - OUT PBOOLEAN p_addressing_reset, - IN NDIS_HANDLE adapter_context ); - -NDIS_STATUS -vnic_oid_set_info( - IN NDIS_HANDLE adapter_context, - IN NDIS_OID oid, - IN PVOID info_buf, - IN ULONG info_buf_length, - OUT PULONG p_bytes_read, - OUT PULONG p_bytes_needed ); - -void -vnic_send_packets( - IN NDIS_HANDLE adapter_context, - IN PPNDIS_PACKET packet_array, - IN UINT num_packets ); - -void -vnic_cancel_xmit( - IN NDIS_HANDLE adapter_context, - IN PVOID cancel_id ); -void -vnic_pnp_notify( - IN NDIS_HANDLE adapter_context, - IN NDIS_DEVICE_PNP_EVENT pnp_event, - IN PVOID info_buf, - IN ULONG info_buf_len ); - -void -vnic_shutdown( - IN PVOID adapter_context ); - -NDIS_STATUS -vnic_get_agapter_interface( - IN NDIS_HANDLE h_handle, - IN vnic_adapter_t *p_adapter); - - -/* same as cl_timer_start() except it takes timeout param in usec */ -/* need to run kicktimer */ -cl_status_t -usec_timer_start( - IN cl_timer_t* const p_timer, - IN const uint32_t time_usec ); - -#endif /* _VNIC_DRIVER_H_ */ diff --git a/trunk/ulp/qlc_vnic/kernel/vnic_ib.c b/trunk/ulp/qlc_vnic/kernel/vnic_ib.c deleted file mode 100644 index 31f2884b..00000000 --- a/trunk/ulp/qlc_vnic/kernel/vnic_ib.c +++ /dev/null @@ -1,922 +0,0 @@ -/* - * Copyright (c) 2007 QLogic Corporation. All rights reserved. - * - * This software is available to you under the OpenIB.org BSD license - * below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * $Id$ - */ -#include "vnic_adapter.h" -#include "vnic_util.h" - -#ifndef max_t -#define max_t(type,x,y) \ - ({ type __x = (x); type __y = (y); __x > __y ? __x: __y; }) -#endif - - -static int inicIbInited = 0; - -extern struct _vnic_globals g_vnic; - -void -ib_asyncEvent( - ib_async_event_rec_t *pEventRecord ); - -static void -_ib_qpCompletion( - IN IbQp_t *pQp); -static void -_ibqp_connect_cb( - IN ib_cm_rep_rec_t *p_cm_rep ); - -static void -_ibqp_detach_cb( - IN ib_cm_drep_rec_t *p_drep_rec ); - -static void -_ibqp_dreq_cb( - IN ib_cm_dreq_rec_t *p_dreq_rec ); - -static void -_ibqp_mra_cb( - IN ib_cm_mra_rec_t *p_mra_rec ); - -static void -_ibqp_rej_cb( - IN ib_cm_rej_rec_t *p_rej_rec ); -static -void ib_workCompletion( - IN ib_cq_handle_t h_cq, - IN void *cqContext ); - - -uint8_t -ibca_findPortNum( - struct _viport *p_viport, - uint64_t guid ) -{ - uint8_t port; - - for (port = 0; port < p_viport->p_adapter->ca.numPorts; port++ ) - { - if (p_viport->p_adapter->ca.portGuids[port] == guid ) - { - return port+1; - } - } - return 0; -} - -ib_api_status_t -ibregion_physInit( - IN struct _vnic_adapter* p_adapter, - IN IbRegion_t *pRegion, - IN ib_pd_handle_t hPd, - IN uint64_t *p_vaddr, - IN uint64_t len ) -{ - ib_phys_create_t phys_mem; - ib_phys_range_t phys_range; - ib_api_status_t ib_status = IB_SUCCESS; - uint64_t vaddr = 0; - VNIC_ENTER ( VNIC_DBG_IB ); - - UNUSED_PARAM( p_vaddr ); - - phys_range.base_addr = *(p_vaddr); - phys_range.size = len; - phys_mem.access_ctrl = ( IB_AC_LOCAL_WRITE | IB_AC_RDMA_WRITE ); - phys_mem.buf_offset = 0; - phys_mem.hca_page_size = PAGE_SIZE; - phys_mem.length = len; - phys_mem.num_ranges = 1; - phys_mem.range_array = &phys_range; - - ib_status = p_adapter->ifc.reg_phys( hPd, - &phys_mem, - &vaddr, - &pRegion->lkey, - &pRegion->rkey, - &pRegion->h_mr ); - - if ( ib_status != IB_SUCCESS ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("ib_reg_phys failed status %s(%d)\n", - p_adapter->ifc.get_err_str(ib_status), ib_status ) ); - pRegion->h_mr = NULL; - } - else - { - pRegion->virtAddress = vaddr; - pRegion->len = len; - } - - VNIC_EXIT( VNIC_DBG_IB ); - return ib_status; -} - -ib_api_status_t -ibregion_init ( - IN viport_t *p_viport, - IN OUT IbRegion_t *pRegion, - IN ib_pd_handle_t hPd, - IN void* __ptr64 vaddr, - IN uint64_t len, - IN ib_access_t access_ctrl ) -{ - ib_api_status_t ib_status; - ib_mr_create_t create_mem; - - VNIC_ENTER ( VNIC_DBG_IB ); - - create_mem.length = len; - create_mem.vaddr = vaddr; - create_mem.access_ctrl = access_ctrl; - - ib_status = p_viport->p_adapter->ifc.reg_mem( hPd, - &create_mem, - &pRegion->lkey, - &pRegion->rkey, - &pRegion->h_mr ); - if ( ib_status != IB_SUCCESS ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("ib_reg_mem failed status %s(%d)\n", - p_viport->p_adapter->ifc.get_err_str( ib_status ), ib_status )); - pRegion->h_mr = NULL; - } - else - { - pRegion->len = len; - pRegion->virtAddress = (uint64_t)( vaddr ); - } - VNIC_EXIT ( VNIC_DBG_IB ); - return ib_status; -} - -void -ibregion_cleanup( - IN viport_t *p_viport, - IN IbRegion_t *pRegion ) -{ - ib_api_status_t ib_status; - - VNIC_ENTER( VNIC_DBG_IB ); - - if( pRegion->h_mr != NULL ) - { - ib_status = p_viport->p_adapter->ifc.dereg_mr( pRegion->h_mr ); - if ( ib_status != IB_SUCCESS ) - { - VNIC_TRACE_EXIT( VNIC_DBG_ERROR, - ("Dereg MR failed status (%d)\n", ib_status )); - } - pRegion->h_mr = NULL; - } - - VNIC_EXIT( VNIC_DBG_IB ); -} - - -void -ibqp_construct( - IN OUT IbQp_t *pQp, - IN viport_t *pViport ) -{ - VNIC_ENTER ( VNIC_DBG_IB ); - - ASSERT( pQp->qpState == IB_UNINITTED ); - - pQp->qp = NULL; - pQp->cq = NULL; - pQp->pViport = pViport; - pQp->pCa = &pViport->p_adapter->ca; - - NdisAllocateSpinLock( &pQp->qpLock ); - - InitializeListHead( &pQp->listPtrs); -} - - -ib_api_status_t -ibqp_init( - IN OUT IbQp_t *pQp, - IN uint64_t guid, - IN IbConfig_t *p_conf ) -{ - ib_qp_create_t attribCreate; - ib_qp_mod_t attribMod; - ib_qp_attr_t qpAttribs; - - ib_cq_create_t cq_create; - ib_cq_handle_t h_cq; - - ib_api_status_t ib_status = IB_SUCCESS; - - VNIC_ENTER ( VNIC_DBG_IB ); - - if (pQp->qpState != IB_UNINITTED && pQp->qpState != IB_DETACHED ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("ibqp_init: out of state (%d)\n", pQp->qpState) ); - return IB_ERROR; - } - - InterlockedExchange( &pQp->qpState, IB_UNINITTED ); - - pQp->p_conf = p_conf; - - cq_create.size = p_conf->numSends + p_conf->numRecvs; - cq_create.pfn_comp_cb = ib_workCompletion; - cq_create.h_wait_obj = NULL; - - ib_status = pQp->pViport->p_adapter->ifc.create_cq( - pQp->pViport->p_adapter->h_ca, &cq_create, pQp, ib_asyncEvent, &h_cq ); - - if( ib_status != IB_SUCCESS ) - { - VNIC_TRACE_EXIT( VNIC_DBG_ERROR, - ("Failed allocating completion queue\n") ); - goto err1; - } - - pQp->cq = h_cq; - - cl_memclr( &attribCreate, sizeof(attribCreate) ); - - attribCreate.qp_type = IB_QPT_RELIABLE_CONN; - attribCreate.sq_depth = p_conf->numSends; - attribCreate.rq_depth = p_conf->numRecvs; - attribCreate.sq_sge = p_conf->sendGather; - attribCreate.rq_sge = p_conf->recvScatter; - attribCreate.h_sq_cq = pQp->cq; - attribCreate.h_rq_cq = pQp->cq; - attribCreate.sq_signaled = FALSE; - - ib_status = pQp->pViport->p_adapter->ifc.create_qp( - pQp->pViport->p_adapter->ca.hPd, - &attribCreate, - pQp, - ib_asyncEvent, - &pQp->qp ); - if( ib_status != IB_SUCCESS ) - { - VNIC_TRACE_EXIT( VNIC_DBG_IB, ("Create QP failed %s\n", - pQp->pViport->p_adapter->ifc.get_err_str( ib_status )) ); - goto err2; - } - ib_status = pQp->pViport->p_adapter->ifc.query_qp(pQp->qp, &qpAttribs); - if( ib_status != IB_SUCCESS ) - { - VNIC_TRACE( VNIC_DBG_ERROR, ("Query QP failed %s\n", - pQp->pViport->p_adapter->ifc.get_err_str( ib_status )) ); - goto err3; - } - pQp->qpNumber = qpAttribs.num; - pQp->portGuid = guid; - cl_memclr( &attribMod, sizeof(attribMod) ); - - attribMod.req_state = IB_QPS_INIT; - attribMod.state.init.primary_port = ibca_findPortNum( pQp->pViport, guid ); - attribMod.state.init.pkey_index = 0; - attribMod.state.init.access_ctrl = IB_AC_LOCAL_WRITE; - attribMod.state.init.access_ctrl |= (p_conf->sendGather > 1) ? IB_AC_RDMA_WRITE : 0; - - ib_status = pQp->pViport->p_adapter->ifc.modify_qp( pQp->qp, &attribMod ); - if( ib_status != IB_SUCCESS ) - { - VNIC_TRACE_EXIT( VNIC_DBG_IB, ("Init QP failed %s\n", - pQp->pViport->p_adapter->ifc.get_err_str( ib_status )) ); - -err3: - pQp->pViport->p_adapter->ifc.destroy_qp( pQp->qp, NULL ); -err2: - pQp->pViport->p_adapter->ifc.destroy_cq( pQp->cq, NULL ); - } - else - { - InterlockedExchange( &pQp->qpState, IB_INITTED ); - } - -err1: - VNIC_EXIT ( VNIC_DBG_IB ); - return ib_status; -} - - -ib_api_status_t -ibqp_connect( - IN IbQp_t *pQp) -{ - IbCa_t *pCa; - viport_t *p_viport; - IbConfig_t *p_conf; - ib_api_status_t ib_status = IB_SUCCESS; - ib_cm_req_t conn_req; - - VNIC_ENTER( VNIC_DBG_IB ); - - if ( pQp->qpState != IB_INITTED ) - { - VNIC_TRACE_EXIT( VNIC_DBG_IB, - ("ibqp_connect: out of state (%d)\n",pQp->qpState) ); - return IB_INVALID_STATE; - } - - p_viport = pQp->pViport; - pCa = pQp->pCa; - p_conf = pQp->p_conf; - -#ifdef VNIC_STATISTIC - pQp->statistics.connectionTime = cl_get_time_stamp(); -#endif - - cl_memclr( &conn_req, sizeof(conn_req)); - - conn_req.h_al = p_viport->p_adapter->h_al; - conn_req.qp_type = IB_QPT_RELIABLE_CONN; - conn_req.h_qp = pQp->qp; - conn_req.p_req_pdata = (uint8_t*)&pQp->p_conf->connData; - conn_req.req_length = sizeof( Inic_ConnectionData_t ); - conn_req.svc_id = pQp->p_conf->sid; - conn_req.pkey = pQp->p_conf->pathInfo.pkey; - - conn_req.p_primary_path = &pQp->p_conf->pathInfo; - - conn_req.retry_cnt = (uint8_t)pQp->p_conf->retryCount; - conn_req.rnr_nak_timeout = pQp->p_conf->minRnrTimer; - conn_req.rnr_retry_cnt = (uint8_t)pQp->p_conf->rnrRetryCount; - conn_req.max_cm_retries = 5; - conn_req.remote_resp_timeout = ib_path_rec_pkt_life( &pQp->p_conf->pathInfo ) + 1; - conn_req.local_resp_timeout = ib_path_rec_pkt_life( &pQp->p_conf->pathInfo ) + 1; - - conn_req.compare_length = 0; - conn_req.resp_res = 0; - - conn_req.flow_ctrl = TRUE; - - conn_req.pfn_cm_req_cb = NULL; - conn_req.pfn_cm_rep_cb = _ibqp_connect_cb; - conn_req.pfn_cm_mra_cb = _ibqp_mra_cb; - conn_req.pfn_cm_rej_cb = _ibqp_rej_cb; - - InterlockedExchange( &pQp->qpState, IB_ATTACHING ); - - ib_status = p_viport->p_adapter->ifc.cm_req ( &conn_req ); - if ( ib_status != IB_SUCCESS && ib_status != IB_PENDING ) - { - VNIC_TRACE_EXIT( VNIC_DBG_ERROR, - ("Connect request return status %s\n", - p_viport->p_adapter->ifc.get_err_str( ib_status )) ); - InterlockedExchange( &pQp->qpState, IB_DETACHED ); - return ib_status; - } - - if( cl_event_wait_on( - &p_viport->sync_event, EVENT_NO_TIMEOUT, FALSE ) != CL_SUCCESS ) - { - VNIC_TRACE_EXIT( VNIC_DBG_ERROR, ("conn event timeout!\n") ); - return IB_TIMEOUT; - } - - if( pQp->qpState != IB_ATTACHED ) - { - VNIC_TRACE( VNIC_DBG_ERROR, ("QP connect failed\n") ); - ib_status = IB_ERROR; - } - - VNIC_EXIT( VNIC_DBG_IB ); - return ib_status; -} - - -static void -_ibqp_detach_cb( - IN ib_cm_drep_rec_t *p_drep_rec ) -{ - IbQp_t *pQp = (IbQp_t * __ptr64 )p_drep_rec->qp_context; - VNIC_ENTER( VNIC_DBG_IB ); - CL_ASSERT( p_drep_rec ); - - InterlockedExchange( &pQp->qpState, IB_DETACHED ); - viport_failure( pQp->pViport ); - - VNIC_EXIT( VNIC_DBG_IB ); -} - -static void -_ibqp_rej_cb( - IN ib_cm_rej_rec_t *p_rej_rec ) -{ - IbQp_t *pQp = (IbQp_t * __ptr64 )p_rej_rec->qp_context; - CL_ASSERT(p_rej_rec ); - - InterlockedExchange( &pQp->qpState, IB_DETACHED ); - switch ( p_rej_rec->rej_status ) - { - case IB_REJ_USER_DEFINED: - - VNIC_TRACE ( VNIC_DBG_IB | VNIC_DBG_ERROR, - ("Conn req user reject status %d\nARI: %s\n", - cl_ntoh16( p_rej_rec->rej_status ), - p_rej_rec->p_ari )); - break; - default: - VNIC_TRACE( VNIC_DBG_IB | VNIC_DBG_ERROR, - ("Conn req reject status %d\n", - cl_ntoh16( p_rej_rec->rej_status )) ); - } - - pQp->pViport->p_adapter->hung++; - cl_event_signal( &pQp->pViport->sync_event ); -} - -static void -_ibqp_mra_cb( - IN ib_cm_mra_rec_t *p_mra_rec ) -{ - VNIC_ENTER( VNIC_DBG_IB ); - CL_ASSERT( p_mra_rec ); - UNREFERENCED_PARAMETER( p_mra_rec ); - VNIC_EXIT( VNIC_DBG_IB ); -} - -static void -_ibqp_dreq_cb( - IN ib_cm_dreq_rec_t *p_dreq_rec ) -{ - ib_api_status_t ib_status = IB_SUCCESS; - ib_cm_drep_t cm_drep; - IbQp_t *pQp = (IbQp_t * __ptr64 )p_dreq_rec->qp_context; - - VNIC_ENTER( VNIC_DBG_IB ); - CL_ASSERT( p_dreq_rec ); - - cm_drep.drep_length = 0; - cm_drep.p_drep_pdata = NULL; - - ib_status = pQp->pViport->p_adapter->ifc.cm_drep( - p_dreq_rec->h_cm_dreq, &cm_drep ); - if ( ib_status != IB_SUCCESS ) - { - VNIC_TRACE_EXIT( VNIC_DBG_ERROR, - ("dreq_cb failed status %s(%d)\n", - pQp->pViport->p_adapter->ifc.get_err_str( ib_status ), ib_status)); - return; - } - - InterlockedExchange (&pQp->qpState, IB_DETACHED ); - pQp->pViport->p_adapter->hung++; - viport_failure( pQp->pViport ); - - VNIC_EXIT( VNIC_DBG_IB ); -} - -void -ibqp_detach( - IN IbQp_t *pQp ) -{ - ib_cm_dreq_t cm_dreq; - ib_api_status_t ib_status = IB_SUCCESS; - - VNIC_ENTER( VNIC_DBG_IB ); - - if( InterlockedCompareExchange( &pQp->qpState, - IB_DETACHING, IB_ATTACHED ) == IB_ATTACHED ) - { - NdisAcquireSpinLock( &pQp->qpLock ); - - cm_dreq.h_qp = pQp->qp; - cm_dreq.qp_type = IB_QPT_RELIABLE_CONN; - cm_dreq.p_dreq_pdata = NULL; - cm_dreq.dreq_length = 0; - cm_dreq.pfn_cm_drep_cb = _ibqp_detach_cb; - ib_status = pQp->pViport->p_adapter->ifc.cm_dreq( &cm_dreq ); - if ( ib_status != IB_SUCCESS ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - (" cm_dreq failed status %s\n", - pQp->pViport->p_adapter->ifc.get_err_str( ib_status ))); - } - - NdisReleaseSpinLock( &pQp->qpLock ); - - ib_status = pQp->pViport->p_adapter->ifc.destroy_qp( pQp->qp, NULL ); - if ( ib_status != IB_SUCCESS ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - (" QP destroy failed status %s\n", - pQp->pViport->p_adapter->ifc.get_err_str( ib_status ))); - } - } - - VNIC_EXIT( VNIC_DBG_IB ); - return; -} - -void -ibqp_cleanup( - IN IbQp_t *pQp ) -{ - ib_api_status_t ib_status = IB_SUCCESS; - LONG qp_state; - - VNIC_ENTER( VNIC_DBG_IB ); - - qp_state = InterlockedExchange( &pQp->qpState, IB_UNINITTED ); - if ( qp_state != IB_UNINITTED && - qp_state != IB_DETACHED && - qp_state != IB_DETACHING ) - { - ib_status = pQp->pViport->p_adapter->ifc.destroy_qp( pQp->qp, NULL ); - if ( ib_status != IB_SUCCESS ) - { - VNIC_TRACE_EXIT( VNIC_DBG_ERROR, - ("destroy_qp failed status %s\n", - pQp->pViport->p_adapter->ifc.get_err_str( ib_status )) ); - } - } - - VNIC_EXIT( VNIC_DBG_IB ); - return; -} - -ib_api_status_t ibqp_postSend(IbQp_t *pQp, Io_t *pIo) -{ - ib_api_status_t ib_status; - -#ifdef VNIC_STATISTIC - int64_t postTime; -#endif /* VNIC_STATISTIC */ - - VNIC_ENTER( VNIC_DBG_IB ); - - NdisAcquireSpinLock( &pQp->qpLock ); - - if( pQp->qpState != IB_ATTACHED ) - { - ib_status = IB_INVALID_STATE; - goto failure; - } - -#ifdef VNIC_STATISTIC - pIo->time = postTime = cl_get_time_stamp(); -#endif /* VNIC_STATISTIC */ - if (pIo->wrq.wr_type == WR_RDMA_WRITE ) - pIo->type = RDMA; - else - pIo->type = SEND; - - ib_status = - pQp->pViport->p_adapter->ifc.post_send( pQp->qp, &pIo->wrq, NULL ); - -#ifdef VNIC_STATISTIC - postTime = cl_get_time_stamp() - postTime; -#endif /* VNIC_STATISTIC */ - - if( ib_status != IB_SUCCESS ) - { - VNIC_TRACE( VNIC_DBG_ERROR, ("ib_post_send returned %s\n", - pQp->pViport->p_adapter->ifc.get_err_str( ib_status )) ); - } - else - { -#ifdef VNIC_STATISTIC - if (pIo->wrq.wr_type == WR_RDMA_WRITE) - { - pQp->statistics.rdmaPostTime += postTime; - pQp->statistics.rdmaPostIos++; - } - else - { - pQp->statistics.sendPostTime += postTime; - pQp->statistics.sendPostIos++; - } -#endif /* VNIC_STATISTIC */ - } - -failure: - NdisReleaseSpinLock( &pQp->qpLock ); - VNIC_EXIT( VNIC_DBG_IB ); - return ib_status; -} - - -ib_api_status_t -ibqp_postRecv(IbQp_t *pQp, Io_t *pIo) -{ - ib_api_status_t ib_status = IB_SUCCESS; -#ifdef VNIC_STATISTIC - int64_t postTime; -#endif /* VNIC_STATISTIC */ - - NdisAcquireSpinLock( &pQp->qpLock ); - /* can post recvieves before connecting queue pair */ - if( pQp->qpState != IB_INITTED && pQp->qpState != IB_ATTACHED ) - { - NdisReleaseSpinLock( &pQp->qpLock ); - return IB_INVALID_STATE; - } - pIo->type = RECV; - -#ifdef VNIC_STATISTIC - postTime = cl_get_time_stamp(); - if (pIo->time != 0) - { - pQp->statistics.recvCompTime += postTime - pIo->time; - pQp->statistics.recvCompIos++; - } -#endif /* VNIC_STATISTIC */ - - ib_status = - pQp->pViport->p_adapter->ifc.post_recv(pQp->qp, &pIo->r_wrq, NULL ); - -#ifdef VNIC_STATISTIC - postTime = (cl_get_time_stamp()) - postTime; -#endif /* VNIC_STATISTIC */ - - if( ib_status != IB_SUCCESS ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("Post Recv failed status %s(%d)\n", - pQp->pViport->p_adapter->ifc.get_err_str(ib_status), ib_status )); - - NdisReleaseSpinLock( &pQp->qpLock ); - return ib_status; - } - else - { -#ifdef VNIC_STATISTIC - pQp->statistics.recvPostTime += postTime; - pQp->statistics.recvPostIos++; -#endif /* VNIC_STATISTIC */ - } - - NdisReleaseSpinLock( &pQp->qpLock ); - return ib_status; -} - - -static void -_ibqp_connect_cb( - IN ib_cm_rep_rec_t *p_cm_rep ) -{ - IbQp_t *pQp; - ib_api_status_t ib_status = IB_SUCCESS; - - union - { - ib_cm_rtu_t cm_rtu; - ib_cm_mra_t cm_mra; - ib_cm_rej_t cm_rej; - } u_reply; - - viport_t *p_viport; - - VNIC_ENTER( VNIC_DBG_IB ); - - pQp = (IbQp_t * __ptr64 )p_cm_rep->qp_context; - p_viport = pQp->pViport; - - ASSERT( pQp->qpState == IB_ATTACHING ); - - ib_status = p_viport->p_adapter->ifc.rearm_cq( pQp->cq, FALSE ); - if ( ib_status != IB_SUCCESS ) - { - VNIC_TRACE_EXIT( VNIC_DBG_ERROR, - ("Rearm CQ failed %s\n", - p_viport->p_adapter->ifc.get_err_str( ib_status )) ); - - cl_memclr( &u_reply.cm_rej, sizeof( u_reply.cm_rej ) ); - u_reply.cm_rej.rej_status = IB_REJ_INSUF_RESOURCES; - - p_viport->p_adapter->ifc.cm_rej( p_cm_rep->h_cm_rep, &u_reply.cm_rej ); - goto err; - } - - cl_memclr( &u_reply.cm_rtu, sizeof( u_reply.cm_rtu ) ); - u_reply.cm_rtu.access_ctrl = IB_AC_LOCAL_WRITE; - - if( pQp->p_conf->sendGather > 1 ) - u_reply.cm_rtu.access_ctrl |= ( IB_AC_RDMA_WRITE ); - - u_reply.cm_rtu.pfn_cm_dreq_cb = _ibqp_dreq_cb; - - ib_status = p_viport->p_adapter->ifc.cm_rtu ( p_cm_rep->h_cm_rep, &u_reply.cm_rtu ); - if ( ib_status != IB_SUCCESS ) - { - VNIC_TRACE_EXIT( VNIC_DBG_ERROR, - ("Send RTU failed: status %#x\n", ib_status ) ); -err: - InterlockedExchange( &pQp->qpState, IB_DETACHED ); - pQp->pViport->p_adapter->hung++; - } - else - { - InterlockedExchange ( &pQp->qpState, IB_ATTACHED ); - } - - cl_event_signal( &p_viport->sync_event ); - VNIC_EXIT( VNIC_DBG_IB ); -} - - -#define WC_LIST_SIZE_TO_POLL 32 -static void -_ib_qpCompletion( - IN IbQp_t *pQp ) -{ - Io_t *pIo; - ib_wc_t wc[WC_LIST_SIZE_TO_POLL]; - ib_wc_t *p_free_wc; - ib_wc_t *p_done_wc; - ib_api_status_t ib_status = IB_SUCCESS; - int i; - -#ifdef VNIC_STATISTIC - int64_t compTime; -#endif /* VNIC_STATISTIC */ - - VNIC_ENTER ( VNIC_DBG_IB ); - - if ( pQp->qpState != IB_ATTACHING && pQp->qpState != IB_ATTACHED ) - return; - -#ifdef VNIC_STATISTIC - compTime = cl_get_time_stamp(); - pQp->statistics.numCallbacks++; -#endif /* VNIC_STATISTIC */ - - for( i = 0; i < (WC_LIST_SIZE_TO_POLL - 1); i++ ) - { - wc[i].p_next = &wc[i + 1]; - } - wc[(WC_LIST_SIZE_TO_POLL - 1)].p_next = NULL; - - p_free_wc = wc; - p_done_wc = NULL; - - ib_status = pQp->pViport->p_adapter->ifc.poll_cq( pQp->cq, &p_free_wc, &p_done_wc ); - - if ( ib_status != IB_SUCCESS && ib_status != IB_NOT_FOUND ) - { - VNIC_TRACE ( VNIC_DBG_ERROR, - ("ib_poll_cq failed status %d(%s)\n", ib_status, - pQp->pViport->p_adapter->ifc.get_err_str( ib_status )) ); - return; - } - - while ( p_done_wc ) - { - pIo = (Io_t *)(uintn_t)p_done_wc->wr_id; - - /* keep completion status for proper ndis packet return status */ - pIo->wc_status = p_done_wc->status; - - if( p_done_wc->status != IB_WCS_SUCCESS ) - { - VNIC_TRACE( VNIC_DBG_IB, - ("Failed Completion: WcType = %d, Status = %d, Length = %d\n", - p_done_wc->wc_type, - p_done_wc->status, - ( p_done_wc->wc_type == IB_WC_RECV )? p_done_wc->length : 0 ) ); - - if( pIo && pIo->type == RDMA ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("Failed RDMA Op, WC type = %d, WC status = %d IO type %d\n", - p_done_wc->wc_type, p_done_wc->status, pIo->type )); - - /* we must complete send packets */ - (*pIo->pRoutine)( pIo ); - } - } - else if(pIo) - { - if( pIo->pRoutine ) - { - (*pIo->pRoutine)( pIo ); - } - } - - p_done_wc = p_done_wc->p_next; - } - - ib_status = pQp->pViport->p_adapter->ifc.rearm_cq( pQp->cq, FALSE ); - - if ( ib_status != IB_SUCCESS ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("Rearm CQ failed status %d(%s)\n", ib_status, - pQp->pViport->p_adapter->ifc.get_err_str( ib_status )) ); - viport_failure( pQp->pViport ); - } - return; -} - - -static -void ib_workCompletion( - IN ib_cq_handle_t h_cq, - IN void *cqContext ) -{ - IbQp_t *pQp; - - VNIC_ENTER ( VNIC_DBG_IB ); - UNREFERENCED_PARAMETER( h_cq ); - pQp = (IbQp_t *)cqContext; - _ib_qpCompletion(pQp); - - VNIC_EXIT ( VNIC_DBG_IB ); - return; -} - -void -ib_asyncEvent( - IN ib_async_event_rec_t *pEventRecord ) -{ - vnic_adapter_t *p_adapter; - viport_t *p_viport; - - VNIC_ENTER ( VNIC_DBG_IB ); - - if ( pEventRecord ) - { - - switch ( pEventRecord->code ) - { - case IB_AE_PORT_DOWN: - p_adapter = ( vnic_adapter_t * __ptr64)pEventRecord->context; - - if( p_adapter && - p_adapter->p_currentPath->pViport && - !p_adapter->p_currentPath->pViport->errored ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("Async Event Port Down for CA GUID: %#016I64x\n", - p_adapter->ifc_data.ca_guid ) ); - } - break; - - case IB_AE_CQ_ERROR: - case IB_AE_RQ_ERROR: - case IB_AE_SQ_ERROR: - case IB_AE_QP_FATAL: - case IB_AE_WQ_REQ_ERROR: - case IB_AE_WQ_ACCESS_ERROR: - - p_viport = ((IbQp_t * __ptr64 )pEventRecord->context)->pViport; - - if( p_viport && !p_viport->errored ) - { - viport_failure( p_viport ); - - VNIC_TRACE( VNIC_DBG_ERROR, - ("Async Event %s (%#x) for port GUID: %#016I64x\n", - ib_get_async_event_str( pEventRecord->code ), - pEventRecord->code, - p_viport->portGuid ) ); - - } - break; - - default: - VNIC_TRACE( VNIC_DBG_IB, - ("Async Event %d\n", pEventRecord->code )); - break; - } - } - - VNIC_EXIT ( VNIC_DBG_IB ); -} - - - - - - - diff --git a/trunk/ulp/qlc_vnic/kernel/vnic_ib.h b/trunk/ulp/qlc_vnic/kernel/vnic_ib.h deleted file mode 100644 index 8dde7deb..00000000 --- a/trunk/ulp/qlc_vnic/kernel/vnic_ib.h +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Copyright (c) 2007 QLogic Corporation. All rights reserved. - * - * This software is available to you under the OpenIB.org BSD license - * below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * $Id$ - */ -#ifndef _VNIC_IB_H_ -#define _VNIC_IB_H_ - - -#include -#include -#include "vnic_trailer.h" -struct Io; - -typedef void (CompRoutine_t)(struct Io *pIo); - -#define MAX_HCAS 4 -#define MAX_NUM_SGE 8 - -#define MAX_PHYS_MEMORY 0xFFFFFFFFFFFFFFFF -#define CONTROL_SID 0 -#define DATA_SID 1 - -#include -typedef union _vnic_sid { - uint64_t as_uint64; - struct { - uint8_t base_id; /* base id for vnic is 0x10 */ - uint8_t oui[3]; /* OUI */ - uint16_t reserved; /* should be zero */ - uint8_t type; /* control or data */ - uint8_t ioc_num; /* ioc number */ - }s; -} vnic_sid_t; - -typedef union _vnic_ioc_guid { - uint64_t as_uint64; - struct { - uint8_t oui[3]; - uint8_t ioc_num; - uint32_t counter; /* SST device type: 8 bits, counter:24 bits */ - }s; -} vnic_ioc_guid_t; -#include - -typedef enum { - IB_UNINITTED = 0, - IB_INITTED, - IB_ATTACHING, - IB_ATTACHED, - IB_DETACHING, - IB_DETACHED, - IB_DISCONNECTED -} IbState_t; -#pragma warning ( disable : 4324 ) -typedef struct _vnic_path_record { - cl_list_item_t list_entry; - ib_path_rec_t path_rec; -} vnic_path_record_t; -#pragma warning( default : 4324 ) - -typedef struct IbQp { - LIST_ENTRY listPtrs; - struct _viport *pViport; - struct IbConfig *p_conf; - NDIS_SPIN_LOCK qpLock; - volatile LONG qpState; - uint32_t qpNumber; - struct IbCa *pCa; - uint64_t portGuid; - ib_qp_handle_t qp; - ib_cq_handle_t cq; -#ifdef VNIC_STATISTIC - struct { - int64_t connectionTime; - int64_t rdmaPostTime; - uint32_t rdmaPostIos; - int64_t rdmaCompTime; - uint32_t rdmaCompIos; - int64_t sendPostTime; - uint32_t sendPostIos; - int64_t sendCompTime; - uint32_t sendCompIos; - int64_t recvPostTime; - uint32_t recvPostIos; - int64_t recvCompTime; - uint32_t recvCompIos; - uint32_t numIos; - uint32_t numCallbacks; - uint32_t maxIos; - } statistics; -#endif /* VNIC_STATISTIC */ -} IbQp_t; - -typedef struct IbRegion { - uint64_t virtAddress; - net64_t len; - ib_mr_handle_t h_mr; - net32_t lkey; - net32_t rkey; -} IbRegion_t; - - -#define VNIC_CA_MAX_PORTS 2 -typedef struct IbCa { - cl_list_item_t list_entry; - net64_t caGuid; - ib_pd_handle_t hPd; - IbRegion_t region; - uint32_t numPorts; - uint64_t portGuids[VNIC_CA_MAX_PORTS]; -} IbCa_t; - -typedef enum _OpType { - RECV, - RDMA, - SEND -} OpType_t; - -typedef struct Io { - LIST_ENTRY listPtrs; - struct _viport *pViport; - CompRoutine_t *pRoutine; - ib_send_wr_t wrq; - ib_recv_wr_t r_wrq; - ib_wc_status_t wc_status; -#ifdef VNIC_STATISTIC - int64_t time; -#endif /* VNIC_STATISTIC */ - OpType_t type; -} Io_t; - -typedef struct RdmaIo { - Io_t io; - ib_local_ds_t dsList[MAX_NUM_SGE]; - uint16_t index; - uint32_t len; - NDIS_PACKET *p_packet; - NDIS_BUFFER *p_buf; - ULONG packet_sz; - struct ViportTrailer *p_trailer; - uint8_t data[2* VIPORT_TRAILER_ALIGNMENT]; -} RdmaIo_t; - -typedef struct SendIo { - Io_t io; - ib_local_ds_t dsList; -} SendIo_t; - -typedef struct RecvIo { - Io_t io; - ib_local_ds_t dsList; -} RecvIo_t; - -void -ibqp_construct( - IN OUT IbQp_t *pQp, - IN struct _viport *pViport ); - -ib_api_status_t -ibqp_init( - IN IbQp_t *pQp, - IN uint64_t guid, - IN OUT struct IbConfig *p_conf); - -ib_api_status_t -ibqp_connect( - IN IbQp_t *pQp); - -void -ibqp_detach( - IN IbQp_t *pQp); - -void -ibqp_cleanup( - IN IbQp_t *pQp); - -ib_api_status_t -ibqp_postSend( - IN IbQp_t *pQp, - IN Io_t *pIo); - -ib_api_status_t -ibqp_postRecv( - IN IbQp_t *pQp, - IN Io_t *pIo); -uint8_t -ibca_findPortNum( - IN struct _viport *p_viport, - IN uint64_t guid ); - -ib_api_status_t -ibregion_init( - IN struct _viport *p_viport, - OUT IbRegion_t *pRegion, - IN ib_pd_handle_t hPd, - IN void* __ptr64 vaddr, - IN uint64_t len, - IN ib_access_t access_ctrl ); - -void -ibregion_cleanup( - IN struct _viport *p_viport, - IN IbRegion_t *pRegion ); - -void -ib_asyncEvent( - IN ib_async_event_rec_t *pEventRecord ); - -#define ibpd_fromCa(pCa) (&(pCa)->pd) - - -#endif /* _VNIC_IB_H_ */ diff --git a/trunk/ulp/qlc_vnic/kernel/vnic_netpath.c b/trunk/ulp/qlc_vnic/kernel/vnic_netpath.c deleted file mode 100644 index 98ddb374..00000000 --- a/trunk/ulp/qlc_vnic/kernel/vnic_netpath.c +++ /dev/null @@ -1,345 +0,0 @@ -/* - * Copyright (c) 2007 QLogic Corporation. All rights reserved. - * - * This software is available to you under the OpenIB.org BSD license - * below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * $Id$ - */ -#include "vnic_adapter.h" - -extern vnic_globals_t g_vnic; - - -void -netpath_init( - IN Netpath_t *pNetpath, - IN vnic_adapter_t *p_adapter ) -{ - VNIC_ENTER( VNIC_DBG_FUNC ); - - pNetpath->p_adapter = p_adapter; - pNetpath->carrier = 0; - pNetpath->pViport = NULL; - pNetpath->p_path_rec = NULL; - pNetpath->timerState = NETPATH_TS_IDLE; - - VNIC_EXIT( VNIC_DBG_FUNC ); - return; -} - -BOOLEAN -netpath_addPath ( - Netpath_t *pNetpath, - viport_t *pViport ) -{ - - if( pNetpath->pViport ) - { - return FALSE; - } - else - { - pNetpath->pViport = pViport; - viport_setParent( pViport, pNetpath ); - return TRUE; - } -} - -BOOLEAN -netpath_setUnicast( - IN Netpath_t* p_netpath, - IN uint8_t* p_address ) -{ - if( p_netpath->pViport ) - { - return( viport_setUnicast( p_netpath->pViport, p_address ) ); - } - return FALSE; -} - -NDIS_STATUS -netpath_setMulticast( - IN Netpath_t* p_netpath ) -{ - if( netpath_is_connected( p_netpath ) ) - { - return viport_setMulticast( p_netpath->pViport ); - } - return NDIS_STATUS_NOT_ACCEPTED; -} - -BOOLEAN -netpath_removePath( - IN Netpath_t *p_netpath, - IN viport_t *p_viport ) - -{ - if( p_netpath->pViport != p_viport ) - { - return FALSE; - } - else - { - viport_timerStop( p_netpath->pViport ); - viport_unsetParent( p_netpath->pViport ); - viport_cleanup( p_viport ); - } - - return TRUE; -} - -void -netpath_free( - IN Netpath_t *pNetpath ) -{ - if( netpath_is_valid( pNetpath ) ) - { - netpath_removePath( pNetpath, pNetpath->pViport ); - } - return; -} - -BOOLEAN -netpath_is_valid( - IN Netpath_t* const p_netpath ) -{ - if( p_netpath == NULL ) - return FALSE; - - if( p_netpath->pViport == NULL ) - return FALSE; - - return TRUE; -} - -BOOLEAN -netpath_is_connected( - IN Netpath_t* const p_netpath ) -{ - if( !netpath_is_valid( p_netpath ) ) - return FALSE; - - if( p_netpath->pViport->errored ) - return FALSE; - - if( p_netpath->p_path_rec == NULL ) - return FALSE; - - if( p_netpath->pViport->state != VIPORT_CONNECTED ) - return FALSE; - - - return TRUE; -} - -BOOLEAN -netpath_is_primary( - IN Netpath_t* const p_netpath ) -{ - return (BOOLEAN)( p_netpath->instance == NETPATH_PRIMARY ); -} -BOOLEAN -netpath_linkUp( - IN Netpath_t* p_netpath ) -{ - if( p_netpath != p_netpath->p_adapter->p_currentPath ) - return FALSE; - - if( p_netpath->carrier == TRUE && - InterlockedExchange( &p_netpath->p_adapter->carrier, TRUE ) == FALSE ) - { - NdisMIndicateStatus( p_netpath->p_adapter->h_handle, - NDIS_STATUS_MEDIA_CONNECT, NULL, 0 ); - NdisMIndicateStatusComplete( p_netpath->p_adapter->h_handle ); - VNIC_TRACE( VNIC_DBG_INIT, - ("IOC[%d] %s Link UP\n", - p_netpath->p_adapter->ioc_num, - netpath_to_string( p_netpath ) ) ); - } - return TRUE; -} - -BOOLEAN -netpath_linkDown( - IN Netpath_t* p_netpath ) -{ - if( p_netpath != p_netpath->p_adapter->p_currentPath ) - return FALSE; - - if ( InterlockedExchange( &p_netpath->p_adapter->carrier, FALSE ) == TRUE ) - { - NdisMIndicateStatus( p_netpath->p_adapter->h_handle, - NDIS_STATUS_MEDIA_DISCONNECT, NULL, 0 ); - NdisMIndicateStatusComplete( p_netpath->p_adapter->h_handle ); - VNIC_TRACE( VNIC_DBG_INIT, - ("IOC[%d] %s Link DOWN\n", - p_netpath->p_adapter->ioc_num, - netpath_to_string( p_netpath ) ) ); - } - - return TRUE; -} - -int netpath_maxMtu(Netpath_t *pNetpath) -{ - int ret = MAX_PARAM_VALUE; - - if (pNetpath->pViport) { - ret = viport_maxMtu(pNetpath->pViport); - } - return ret; -} - -BOOLEAN -netpath_xmitPacket( - IN Netpath_t *pNetpath, - IN NDIS_PACKET * const p_packet ) -{ - - if ( pNetpath->pViport && - pNetpath->p_adapter->xmitStarted ) - { - return ( viport_xmitPacket(pNetpath->pViport, p_packet ) ); - } - else - { - NdisInterlockedInsertTailList( - &pNetpath->p_adapter->send_pending_list, - VNIC_LIST_ITEM_FROM_PACKET( p_packet ), - &pNetpath->p_adapter->pending_list_lock ); - return TRUE; - } -} - -void -netpath_cancel_xmit( - IN Netpath_t *p_netpath, - IN PVOID cancel_id ) -{ - if( p_netpath->pViport ) - { - viport_cancel_xmit( p_netpath->pViport, cancel_id ); - } -} - -void -netpath_stopXmit( - IN Netpath_t *pNetpath ) - -{ - - VNIC_ENTER( VNIC_DBG_NETPATH ); - - if( pNetpath == pNetpath->p_adapter->p_currentPath ) - { - InterlockedCompareExchange( &pNetpath->p_adapter->xmitStarted, 0, 1 ); - } -#ifdef INIC_STATISTICS - if ( pNetpath->p_adapter->statistics.xmitRef == 0) - { - pNetpath->p_adapter->statistics.xmitRef = get_time_stamp_ms(); - } -#endif /* INIC_STATISTICS */ - return; -} - -void netpath_restartXmit( - IN Netpath_t *pNetpath ) -{ - VNIC_ENTER( VNIC_DBG_NETPATH ); - - if( ( netpath_is_connected( pNetpath ) ) && - pNetpath == pNetpath->p_adapter->p_currentPath ) - { - InterlockedCompareExchange( &pNetpath->p_adapter->xmitStarted, 1, 0 ); - VNIC_TRACE( VNIC_DBG_NETPATH, - ("IOC[%d] instance %d Restart TRANSMIT\n", - pNetpath->pViport->ioc_num, - pNetpath->instance )); - - } -#ifdef INIC_STATISTICS - if (pNetpath->p_adapter->statistics.xmitRef != 0) - { - pNetpath->p_adapter->statistics.xmitOffTime += - get_time_stamp_ms() - pNetpath->p_adapter->statistics.xmitRef; - pNetpath->p_adapter->statistics.xmitOffNum++; - pNetpath->p_adapter->statistics.xmitRef = 0; - } -#endif /* INIC_STATISTICS */ - return; -} - -// Viport on input calls this -void netpath_recvPacket( - IN Netpath_t *pNetpath, - IN NDIS_PACKET** pp_packet_array, - IN uint32_t num_packets ) -{ - -#ifdef INIC_STATISTICS - extern uin64_t recvRef; -#endif /* INIC_STATISTICS */ - - VNIC_ENTER( VNIC_DBG_NETPATH ); - -#ifdef INIC_STATISTICS - pNetpath->p_adapter->statistics.recvTime += cl_get_tick_count() - recvRef; - pNetpath->p_adapter->statistics.recvNum++; -#endif /* INIC_STATISTICS */ - - NdisMIndicateReceivePacket( pNetpath->p_adapter->h_handle, - pp_packet_array, - num_packets ); - return; -} - -void netpath_tx_timeout( - IN Netpath_t *pNetpath ) -{ - if ( pNetpath->pViport ) - { - viport_failure( pNetpath->pViport ); - } -} - -const char * -netpath_to_string( - IN Netpath_t *p_netpath ) -{ - if ( !netpath_is_valid( p_netpath ) ) - { - return "NULL"; - } - else if ( p_netpath == p_netpath->p_adapter->p_currentPath ) - { - return "CURRENT"; - } - else - { - return "STANDBY"; - } -} diff --git a/trunk/ulp/qlc_vnic/kernel/vnic_trailer.h b/trunk/ulp/qlc_vnic/kernel/vnic_trailer.h deleted file mode 100644 index c047a9b6..00000000 --- a/trunk/ulp/qlc_vnic/kernel/vnic_trailer.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2007 QLogic Corporation. All rights reserved. - * - * This software is available to you under the OpenIB.org BSD license - * below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * $Id$ - */ - -#ifndef _VNIC_TRAILER_H_ -#define _VNIC_TRAILER_H_ - -/* pktFlags values */ -#define PF_CHASH_VALID 0x01 -#define PF_IPSEC_VALID 0x02 -#define PF_TCP_SEGMENT 0x04 -#define PF_KICK 0x08 -#define PF_VLAN_INSERT 0x10 -#define PF_PVID_OVERRIDDEN 0x20 -#define PF_FCS_INCLUDED 0x40 -#define PF_FORCE_ROUTE 0x80 - -/* txChksumFlags values */ -#define TX_CHKSUM_FLAGS_CHECKSUM_V4 0x01 -#define TX_CHKSUM_FLAGS_CHECKSUM_V6 0x02 -#define TX_CHKSUM_FLAGS_TCP_CHECKSUM 0x04 -#define TX_CHKSUM_FLAGS_UDP_CHECKSUM 0x08 -#define TX_CHKSUM_FLAGS_IP_CHECKSUM 0x10 - -/* rxChksumFlags values */ -#define RX_CHKSUM_FLAGS_TCP_CHECKSUM_FAILED 0x01 -#define RX_CHKSUM_FLAGS_UDP_CHECKSUM_FAILED 0x02 -#define RX_CHKSUM_FLAGS_IP_CHECKSUM_FAILED 0x04 -#define RX_CHKSUM_FLAGS_TCP_CHECKSUM_SUCCEEDED 0x08 -#define RX_CHKSUM_FLAGS_UDP_CHECKSUM_SUCCEEDED 0x10 -#define RX_CHKSUM_FLAGS_IP_CHECKSUM_SUCCEEDED 0x20 -#define RX_CHKSUM_FLAGS_LOOPBACK 0x40 -#define RX_CHKSUM_FLAGS_RESERVED 0x80 - -/* connectionHashAndValid values */ -#define CHV_VALID 0x80 -#define CHV_HASH_MASH 0x7f - -/* round down value to align, align must be a power of 2 */ -#ifndef ROUNDDOWNP2 -#define ROUNDDOWNP2(val, align) \ - (((ULONG)(val)) & (~((ULONG)(align)-1))) -#endif - -/* round up value to align, align must be a power of 2 */ -#ifndef ROUNDUPP2 -#define ROUNDUPP2(val, align) \ - (((ULONG)(val) + (ULONG)(align) - 1) & (~((ULONG)(align)-1))) -#endif - -#define VIPORT_TRAILER_ALIGNMENT 32 -#define BUFFER_SIZE(len) (sizeof(ViportTrailer_t) + ROUNDUPP2((len), VIPORT_TRAILER_ALIGNMENT)) -#define MAX_PAYLOAD(len) ROUNDDOWNP2((len) - sizeof(ViportTrailer_t), VIPORT_TRAILER_ALIGNMENT) -#define MIN_PACKET_LEN 64 -#include - -typedef struct ViportTrailer { - int8_t dataAlignmentOffset; - uint8_t rndisHeaderLength; /* reserved for use by Edp */ - uint16_t dataLength; - uint8_t pktFlags; - - uint8_t txChksumFlags; - - uint8_t rxChksumFlags; - - uint8_t ipSecFlags; - uint32_t tcpSeqNo; - uint32_t ipSecOffloadHandle; - uint32_t ipSecNextOffloadHandle; - uint8_t destMacAddr[6]; - uint16_t vLan; - uint16_t timeStamp; - uint8_t origin; - uint8_t connectionHashAndValid; -} ViportTrailer_t; - -#include - -#endif /* _VNIC_TRAILER_H_ */ diff --git a/trunk/ulp/qlc_vnic/kernel/vnic_util.h b/trunk/ulp/qlc_vnic/kernel/vnic_util.h deleted file mode 100644 index c974b8df..00000000 --- a/trunk/ulp/qlc_vnic/kernel/vnic_util.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2007 QLogic Corporation. All rights reserved. - * - * This software is available to you under the OpenIB.org BSD license - * below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * $Id$ - */ - -#ifndef _VNIC_UTIL_H_ -#define _VNIC_UTIL_H_ - -#include "vnic_debug.h" - -#define MAXU32 MAXULONG -#define MAXU64 ((uint64_t)(~0)) - -#define PTR64(what) ((uint64_t)(void * __ptr64)(what)) - -#ifndef min -#define min(a,b) ((a)<(b)?(a):(b)) -#endif - -#define hton16(x) _byteswap_ushort(x) -#define hton32(x) _byteswap_ulong(x) -#define hton64(x) _byteswap_uint64(x) - -#define ntoh16(x) hton16(x) -#define ntoh32(x) hton32(x) -#define ntoh64(x) hton64(x) - -#define IsPowerOf2(value) (((value) & (value - 1)) == 0) -/* round down to closest power of 2 value */ - -#define SetMinPowerOf2(_val) ((_val) & ( 1 << RtlFindMostSignificantBit( (uint64_t)(_val) ))) - - -#endif /* _VNIC_UTIL_H_ */ - diff --git a/trunk/ulp/qlc_vnic/kernel/vnic_viport.c b/trunk/ulp/qlc_vnic/kernel/vnic_viport.c deleted file mode 100644 index f34c8bf4..00000000 --- a/trunk/ulp/qlc_vnic/kernel/vnic_viport.c +++ /dev/null @@ -1,1232 +0,0 @@ -/* - * Copyright (c) 2007 QLogic Corporation. All rights reserved. - * - * This software is available to you under the OpenIB.org BSD license - * below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * $Id$ - */ - -#include "iba/ib_al.h" -#include "vnic_util.h" -#include "vnic_driver.h" -#include "vnic_viport.h" -#include "vnic_control.h" -#include "vnic_data.h" -#include "vnic_config.h" -#include "vnic_controlpkt.h" - -extern vnic_globals_t g_vnic; - -static void -viport_timeout( - void *context ); - -static ib_api_status_t -viport_initMacAddresses( - viport_t *p_viport ); - -BOOLEAN -viport_config_defaults( - IN viport_t *p_viport ) -{ - - vnic_adapter_t *p_adapter = p_viport->p_adapter; - ViportConfig_t *pConfig = &p_viport->port_config; - ControlConfig_t *pControlConfig = &p_viport->port_config.controlConfig; - DataConfig_t *pDataConfig = &p_viport->port_config.dataConfig; - - VNIC_ENTER( VNIC_DBG_VIPORT ); - - p_viport->state = VIPORT_DISCONNECTED; - p_viport->linkState = LINK_RETRYWAIT; - p_viport->newMtu = 1500; - p_viport->newFlags = 0; - p_viport->hb_send_pending = FALSE; - - cl_timer_init( &p_viport->timer, viport_timeout, p_viport ); - - pConfig->statsInterval = p_adapter->params.ViportStatsInterval; - pConfig->hbInterval = p_adapter->params.ViportHbInterval; - pConfig->hbTimeout = p_adapter->params.ViportHbTimeout; - - cl_memcpy ( pConfig->ioc_string, - p_adapter->ioc_info.profile.id_string, - min( sizeof( p_adapter->ioc_info.profile.id_string ), - sizeof( pConfig->ioc_string )) ); - - pControlConfig->ibConfig.sid = 0; /* will set it later, from svc entries */ - pControlConfig->ibConfig.connData.pathId = 0; - pControlConfig->ibConfig.connData.inicInstance = 0; // assign instance id in update_path - pControlConfig->ibConfig.connData.pathNum = 0; - - pControlConfig->ibConfig.retryCount = p_adapter->params.RetryCount; - pControlConfig->ibConfig.rnrRetryCount = p_adapter->params.RetryCount; - pControlConfig->ibConfig.minRnrTimer = (uint8_t)p_adapter->params.MinRnrTimer; - pControlConfig->ibConfig.numRecvs = 5; /* Not configurable */ - pControlConfig->ibConfig.numSends = 1; /* Not configurable */ - pControlConfig->ibConfig.recvScatter = 1; /* Not configurable */ - pControlConfig->ibConfig.sendGather = 1; /* Not configurable */ - - /* indicate new features support capabilities */ - pControlConfig->ibConfig.connData.featuresSupported = - hton32((uint32_t)(INIC_FEAT_IGNORE_VLAN | INIC_FEAT_RDMA_IMMED )); - - cl_memcpy ( pControlConfig->ibConfig.connData.nodename, - g_vnic.host_name, - min( sizeof( g_vnic.host_name ), - sizeof( pControlConfig->ibConfig.connData.nodename )) ); - - pControlConfig->numRecvs = pControlConfig->ibConfig.numRecvs; - - pControlConfig->inicInstance = pControlConfig->ibConfig.connData.inicInstance; - pControlConfig->maxAddressEntries = (uint16_t)p_adapter->params.MaxAddressEntries; - pControlConfig->minAddressEntries = (uint16_t)p_adapter->params.MinAddressEntries; - pControlConfig->reqRetryCount = (uint8_t)p_adapter->params.ControlReqRetryCount; - pControlConfig->rspTimeout = p_adapter->params.ControlRspTimeout; - - pDataConfig->ibConfig.sid = 0; /* will set it later, from svc entries */ - pDataConfig->ibConfig.connData.pathId = get_time_stamp_ms(); - pDataConfig->ibConfig.connData.inicInstance = pControlConfig->inicInstance; - pDataConfig->ibConfig.connData.pathNum = 0; - - pDataConfig->ibConfig.retryCount = p_adapter->params.RetryCount; - pDataConfig->ibConfig.rnrRetryCount = p_adapter->params.RetryCount; - pDataConfig->ibConfig.minRnrTimer = (uint8_t)p_adapter->params.MinRnrTimer; - - /* - * NOTE: The numRecvs size assumes that the EIOC could - * RDMA enough packets to fill all of the host recv - * pool entries, plus send a kick message after each - * packet, plus RDMA new buffers for the size of - * the EIOC recv buffer pool, plus send kick messages - * after each MinHostUpdateSz of new buffers all - * before the Host can even pull off the first completed - * receive off the completion queue, and repost the - * receive. NOT LIKELY! - */ - pDataConfig->ibConfig.numRecvs = p_adapter->params.HostRecvPoolEntries + - ( p_adapter->params.MaxEiocPoolSz / p_adapter->params.MinHostUpdateSz ); - -#if LIMIT_OUTSTANDING_SENDS - - pDataConfig->ibConfig.numSends = (2 * p_adapter->params.NotifyBundleSz ) + - ( p_adapter->params.HostRecvPoolEntries / p_adapter->params.MinEiocUpdateSz ) + 1; - -#else /* !defined(LIMIT_OUTSTANDING_SENDS) */ - /* - * NOTE: The numSends size assumes that the HOST could - * post RDMA sends for every single buffer in the EIOCs - * receive pool, and allocate a full complement of - * receive buffers on the host, and RDMA free buffers - * every MinEiocUpdateSz entries all before the HCA - * can complete a single RDMA transfer. VERY UNLIKELY, - * BUT NOT COMPLETELY IMPOSSIBLE IF THERE IS AN IB - * PROBLEM! - */ - pDataConfig->ibConfig.numSends = p_adapter->params.MaxEiocPoolSz + - ( p_adapter->params.HostRecvPoolEntries / p_adapter->params.MinEiocUpdateSz ) + 1; - -#endif /* !defined(LIMIT_OUTSTANDING_SENDS) */ - - pDataConfig->ibConfig.recvScatter = 1; /* Not configurable */ - pDataConfig->ibConfig.sendGather = MAX_NUM_SGE; /* Not configurable */ - - pDataConfig->numRecvs = pDataConfig->ibConfig.numRecvs; - pDataConfig->pathId = pDataConfig->ibConfig.connData.pathId; - - pDataConfig->hostMin.sizeRecvPoolEntry = - (uint32_t)BUFFER_SIZE(ETH_VLAN_HLEN + p_adapter->params.MinMtu); - pDataConfig->hostMax.sizeRecvPoolEntry = - (uint32_t)BUFFER_SIZE(ETH_VLAN_HLEN + p_adapter->params.MaxMtu); - pDataConfig->eiocMin.sizeRecvPoolEntry = - (uint32_t)BUFFER_SIZE(ETH_VLAN_HLEN + p_adapter->params.MinMtu); - pDataConfig->eiocMax.sizeRecvPoolEntry = MAX_PARAM_VALUE; - - pDataConfig->hostRecvPoolEntries = p_adapter->params.HostRecvPoolEntries; - pDataConfig->notifyBundle = p_adapter->params.NotifyBundleSz; - - pDataConfig->hostMin.numRecvPoolEntries = p_adapter->params.MinHostPoolSz; - pDataConfig->hostMax.numRecvPoolEntries = MAX_PARAM_VALUE; - pDataConfig->eiocMin.numRecvPoolEntries = p_adapter->params.MinEiocPoolSz; - pDataConfig->eiocMax.numRecvPoolEntries = p_adapter->params.MaxEiocPoolSz; - - pDataConfig->hostMin.timeoutBeforeKick = p_adapter->params.MinHostKickTimeout; - pDataConfig->hostMax.timeoutBeforeKick = p_adapter->params.MaxHostKickTimeout; - pDataConfig->eiocMin.timeoutBeforeKick = 0; - pDataConfig->eiocMax.timeoutBeforeKick = MAX_PARAM_VALUE; - - pDataConfig->hostMin.numRecvPoolEntriesBeforeKick = p_adapter->params.MinHostKickEntries; - pDataConfig->hostMax.numRecvPoolEntriesBeforeKick = p_adapter->params.MaxHostKickEntries; - pDataConfig->eiocMin.numRecvPoolEntriesBeforeKick = 0; - pDataConfig->eiocMax.numRecvPoolEntriesBeforeKick = MAX_PARAM_VALUE; - - pDataConfig->hostMin.numRecvPoolBytesBeforeKick = p_adapter->params.MinHostKickBytes; - pDataConfig->hostMax.numRecvPoolBytesBeforeKick = p_adapter->params.MaxHostKickBytes; - pDataConfig->eiocMin.numRecvPoolBytesBeforeKick = 0; - pDataConfig->eiocMax.numRecvPoolBytesBeforeKick = MAX_PARAM_VALUE; - - pDataConfig->hostMin.freeRecvPoolEntriesPerUpdate = p_adapter->params.MinHostUpdateSz; - pDataConfig->hostMax.freeRecvPoolEntriesPerUpdate = p_adapter->params.MaxHostUpdateSz; - pDataConfig->eiocMin.freeRecvPoolEntriesPerUpdate = p_adapter->params.MinEiocUpdateSz; - pDataConfig->eiocMax.freeRecvPoolEntriesPerUpdate = p_adapter->params.MaxEiocUpdateSz; - - VNIC_EXIT( VNIC_DBG_VIPORT ); - return TRUE; -} - -static BOOLEAN config_isValid(ViportConfig_t *pConfig) -{ - UNREFERENCED_PARAMETER( pConfig ); - return TRUE; -} - - -void -viport_cleanup( - viport_t *p_viport ) -{ - VNIC_ENTER( VNIC_DBG_VIPORT ); - - if( p_viport ) - { - if( InterlockedExchange( (volatile LONG *)&p_viport->disconnect, TRUE ) ) - { - return; - } - - VNIC_TRACE(VNIC_DBG_VIPORT, - ("IOC[%d]viport cleanup\n", p_viport->ioc_num )); - - data_disconnect( &p_viport->data ); - - control_cleanup( &p_viport->control ); - - data_cleanup( &p_viport->data ); - - if( p_viport->macAddresses != NULL ) - { - NdisFreeMemory( p_viport->macAddresses, - p_viport->numMacAddresses * sizeof(Inic_AddressOp_t), 0 ); - } - - cl_timer_destroy( &p_viport->timer ); - - NdisFreeMemory( p_viport, sizeof(viport_t), 0 ); - p_viport = NULL; - } - - VNIC_EXIT( VNIC_DBG_VIPORT ); - return; -} - -BOOLEAN -viport_setParent( - IN viport_t *p_viport, - IN Netpath_t *pNetpath ) -{ - VNIC_ENTER( VNIC_DBG_VIPORT ); - - - if(p_viport->p_netpath != NULL) - { - return FALSE; - } - - p_viport->p_netpath = pNetpath; - - VNIC_EXIT( VNIC_DBG_VIPORT ); - return TRUE; -} - -BOOLEAN -viport_unsetParent( - IN viport_t *p_viport ) -{ - if( !p_viport || - !p_viport->p_netpath ) - { - return FALSE; - } - InterlockedExchange( &p_viport->p_netpath->carrier, FALSE ); - p_viport->p_netpath->pViport = NULL; - p_viport->p_netpath = NULL; - - if( p_viport->state == VIPORT_CONNECTED ) - { - p_viport->p_adapter->num_paths--; - } - return TRUE; -} - - -NDIS_STATUS -viport_setLink( - IN viport_t *p_viport, - IN uint8_t flags, - IN uint16_t mtu , - IN BOOLEAN sync ) -{ - - NDIS_STATUS status = NDIS_STATUS_SUCCESS; - - VNIC_ENTER( VNIC_DBG_VIPORT ); - - if( mtu > data_maxMtu(&p_viport->data) ) - { - viport_failure(p_viport); - VNIC_TRACE_EXIT( VNIC_DBG_ERROR, - ("IOC[%d] Configuration error. Mtu of %d unsupported\n", p_viport->ioc_num, mtu ) ); - return NDIS_STATUS_FAILURE; - } - - NdisAcquireSpinLock( &p_viport->lock ); - - if( ( (p_viport->newFlags & flags ) != flags ) || - ( p_viport->newMtu != mtu ) ) - { - p_viport->newFlags = flags; - p_viport->newMtu = mtu; - InterlockedOr( &p_viport->updates, NEED_LINK_CONFIG ); - - NdisReleaseSpinLock( &p_viport->lock ); - - status = _viport_process_query( p_viport, sync ); - } - else - NdisReleaseSpinLock( &p_viport->lock ); - - VNIC_EXIT( VNIC_DBG_VIPORT ); - return status; -} - -BOOLEAN -viport_setUnicast( - IN viport_t* const p_viport, - IN uint8_t *p_address ) -{ - NDIS_STATUS status = NDIS_STATUS_SUCCESS; - - VNIC_ENTER( VNIC_DBG_VIPORT ); - - if( !p_viport ) - return FALSE; - - NdisAcquireSpinLock( &p_viport->lock ); - - if( p_viport->macAddresses == NULL ) - { - NdisReleaseSpinLock( &p_viport->lock ); - return FALSE; - } - - if( cl_memcmp(p_viport->macAddresses[UNICAST_ADDR].address, - p_address, MAC_ADDR_LEN ) ) - { - - cl_memcpy( p_viport->macAddresses[UNICAST_ADDR].address, - p_address, MAC_ADDR_LEN ); - - VNIC_TRACE( VNIC_DBG_VIPORT, - ("Change Viport MAC From : %02x %02x %02x %02x %02x %02x -> to : %02x %02x %02x %02x %02x %02x\n", - p_viport->hwMacAddress[0], p_viport->hwMacAddress[1], p_viport->hwMacAddress[2], - p_viport->hwMacAddress[3], p_viport->hwMacAddress[4], p_viport->hwMacAddress[5], - p_viport->macAddresses[UNICAST_ADDR].address[0], p_viport->macAddresses[UNICAST_ADDR].address[1], - p_viport->macAddresses[UNICAST_ADDR].address[2], p_viport->macAddresses[UNICAST_ADDR].address[3], - p_viport->macAddresses[UNICAST_ADDR].address[4], p_viport->macAddresses[UNICAST_ADDR].address[5] - ) ); - - NdisMoveMemory( p_viport->hwMacAddress, - p_viport->macAddresses[UNICAST_ADDR].address, MAC_ADDR_LEN ); - - p_viport->macAddresses[UNICAST_ADDR].operation = INIC_OP_SET_ENTRY; - - InterlockedOr( &p_viport->updates, NEED_ADDRESS_CONFIG ); - - NdisReleaseSpinLock( &p_viport->lock ); - - status = _viport_process_query( p_viport, FALSE ); - if( status != NDIS_STATUS_SUCCESS && - status != NDIS_STATUS_PENDING ) - { - VNIC_TRACE_EXIT( VNIC_DBG_ERROR, ("Viport MAC set failed\n") ); - return FALSE; - } - } - - NdisReleaseSpinLock( &p_viport->lock ); - - VNIC_EXIT( VNIC_DBG_VIPORT ); - return TRUE; -} - - -/* Returns flags for state machine operations. */ -NDIS_STATUS -viport_setMulticast( - IN viport_t* const p_viport ) -{ - vnic_adapter_t *p_adapter = p_viport->p_adapter; - uint32_t updates = 0; - int i; - NDIS_STATUS status; - - VNIC_ENTER( VNIC_DBG_VIPORT ); - - NdisAcquireSpinLock( &p_viport->lock ); - - if( p_viport->macAddresses == NULL ) - { - NdisReleaseSpinLock( &p_viport->lock ); - return NDIS_STATUS_NOT_ACCEPTED; - } - - ASSERT( (p_viport->updates & ~MCAST_OVERFLOW) == 0 ); - - if( p_adapter->mc_count == 0 ) - { - /* invalidate all entries for the remote */ - for (i = MCAST_ADDR_START; - i < min( MAX_ADDR_ARRAY, p_viport->numMacAddresses ); i++ ) - { - p_viport->macAddresses[i].valid = 0; - p_viport->macAddresses[i].operation = INIC_OP_SET_ENTRY; - } - /* do we have to report to remote ? */ - p_viport->updates = 0; - NdisReleaseSpinLock( &p_viport->lock ); - return NDIS_STATUS_SUCCESS; - } - - if( p_adapter->mc_count > p_viport->numMacAddresses - MCAST_ADDR_START ) - { - updates |= NEED_LINK_CONFIG | MCAST_OVERFLOW; - } - else - { - if( InterlockedAnd( - &p_viport->updates, ~MCAST_OVERFLOW ) & MCAST_OVERFLOW ) - { - updates |= NEED_LINK_CONFIG; - } - /* Brute force algorithm */ - for (i = MCAST_ADDR_START; - i < min( MAX_ADDR_ARRAY, p_adapter->mc_count + MCAST_ADDR_START ); - i++ ) - { - if( p_viport->macAddresses[i].valid && - NdisEqualMemory( p_viport->macAddresses[i].address, - p_adapter->mcast_array[i - MCAST_ADDR_START].addr, - MAC_ADDR_LEN ) ) - { - continue; - } - - NdisMoveMemory( &p_viport->macAddresses[i].address, - p_adapter->mcast_array[i - MCAST_ADDR_START].addr, - MAC_ADDR_LEN ); - - p_viport->macAddresses[i].valid = 1; - p_viport->macAddresses[i].operation = INIC_OP_SET_ENTRY; - - updates |= NEED_ADDRESS_CONFIG; - } - for (; i < min( MAX_ADDR_ARRAY, p_viport->numMacAddresses ); i++ ) - { - if( !p_viport->macAddresses[i].valid ) - continue; - - updates |= NEED_ADDRESS_CONFIG; - - p_viport->macAddresses[i].valid = 0; - p_viport->macAddresses[i].operation = INIC_OP_SET_ENTRY; - } - } - - /* - * Now that the mac array is setup, we can set the update bits - * to send the request. - */ - InterlockedOr( &p_viport->updates, updates ); - NdisReleaseSpinLock( &p_viport->lock ); - - status = _viport_process_query( p_viport, FALSE ); - - VNIC_EXIT( VNIC_DBG_VIPORT ); - return status; -} - -NDIS_STATUS -viport_getStats( - IN viport_t *p_viport ) -{ - uint64_t stats_update_ms; - NDIS_STATUS status = STATUS_SUCCESS; - - VNIC_ENTER( VNIC_DBG_VIPORT ); - - stats_update_ms = get_time_stamp_ms(); - - if( stats_update_ms > p_viport->lastStatsTime + p_viport->port_config.statsInterval ) - { - p_viport->lastStatsTime = (uint32_t)stats_update_ms; - - InterlockedOr( &p_viport->updates, NEED_STATS ); - - status = _viport_process_query( p_viport, FALSE ); - if ( status != NDIS_STATUS_SUCCESS ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("Query NEED_STATS Failed\n") ); - } - } - - VNIC_EXIT( VNIC_DBG_VIPORT ); - return status; -} - - -BOOLEAN -viport_xmitPacket( - IN viport_t* const p_viport, - IN NDIS_PACKET* const p_packet ) -{ - BOOLEAN status; - LIST_ENTRY *p_list_item; - NDIS_PACKET *p_pending_packet; - vnic_adapter_t* p_adapter; - - VNIC_ENTER( VNIC_DBG_VIPORT ); - - NdisAcquireSpinLock( &p_viport->lock ); - - p_adapter = p_viport->p_netpath->p_adapter; - - while( ( p_list_item = NdisInterlockedRemoveHeadList( - &p_adapter->send_pending_list, - &p_adapter->pending_list_lock ) ) != NULL ) - { - p_pending_packet = VNIC_PACKET_FROM_LIST_ITEM( p_list_item ); - - status = data_xmitPacket( &p_viport->data, p_pending_packet ); - if( !status ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("IOC[%d] Xmit Pending Packet failed\n", p_viport->ioc_num )); - - /* put it back on pending list - will complete it on cleanup */ - NdisInterlockedInsertTailList( - &p_adapter->send_pending_list, - VNIC_LIST_ITEM_FROM_PACKET( p_pending_packet ), - &p_adapter->pending_list_lock ); - /*do not try to send packet, just exit */ - goto err; - } - } - - /* send a packet */ - status = data_xmitPacket( &p_viport->data, p_packet ); - if( status ) - { - NdisReleaseSpinLock( &p_viport->lock ); - - VNIC_EXIT( VNIC_DBG_VIPORT ); - return status; - } - -err: - NdisInterlockedInsertTailList( - &p_adapter->send_pending_list, - VNIC_LIST_ITEM_FROM_PACKET( p_packet ), - &p_adapter->pending_list_lock ); - - viport_stopXmit( p_viport ); - - NdisReleaseSpinLock( &p_viport->lock ); - - VNIC_EXIT( VNIC_DBG_VIPORT ); - return status; -} - -void -viport_cancel_xmit( - viport_t *p_viport, - PVOID cancel_id ) -{ - NDIS_PACKET *p_packet; - LIST_ENTRY *p_list_item; - LIST_ENTRY *p_list; - PVOID _id; - vnic_adapter_t* p_adapter; - - NdisAcquireSpinLock( &p_viport->lock ); - - p_adapter = p_viport->p_netpath->p_adapter; - p_list = &p_adapter->send_pending_list; - - while( !IsListEmpty( &p_adapter->send_pending_list ) ) - { - p_list_item = p_list->Flink; - - if ( p_list_item->Flink == &p_adapter->send_pending_list ) - break; - - p_packet = VNIC_PACKET_FROM_LIST_ITEM( p_list_item ); - - _id = NdisGetPacketCancelId( p_packet ); - - if( _id == cancel_id ) - { - NdisInterlockedRemoveHeadList( p_list, &p_adapter->pending_list_lock ); - NdisInterlockedInsertTailList( &p_adapter->cancel_send_list, p_list_item, - &p_adapter->cancel_list_lock ); - p_list_item = p_list->Flink; - } - else - { - p_list = p_list_item; - } - } - - while( !IsListEmpty( &p_adapter->cancel_send_list ) ) - { - p_list_item = NdisInterlockedRemoveHeadList( &p_adapter->cancel_send_list, - &p_adapter->cancel_list_lock ); - - p_packet = VNIC_PACKET_FROM_LIST_ITEM( p_list_item ); - - if( p_packet ) - { - NDIS_SET_PACKET_STATUS( p_packet, NDIS_STATUS_REQUEST_ABORTED ); - NdisMSendComplete( p_adapter->h_handle, p_packet, NDIS_STATUS_REQUEST_ABORTED ); - } - } - - NdisReleaseSpinLock( &p_viport->lock ); -} - -void -viport_linkUp(viport_t *p_viport) -{ - VNIC_ENTER( VNIC_DBG_VIPORT ); - - netpath_linkUp( p_viport->p_netpath ); - - VNIC_EXIT( VNIC_DBG_VIPORT ); - return; -} - -void -viport_linkDown(viport_t *p_viport) -{ - VNIC_ENTER( VNIC_DBG_VIPORT ); - - netpath_linkDown( p_viport->p_netpath ); - - VNIC_EXIT( VNIC_DBG_VIPORT ); - return; -} - -void -viport_stopXmit(viport_t *p_viport) -{ - VNIC_ENTER( VNIC_DBG_VIPORT ); - netpath_stopXmit( p_viport->p_netpath ); - VNIC_EXIT( VNIC_DBG_VIPORT ); - return; -} - -void -viport_restartXmit(viport_t *p_viport) -{ - VNIC_ENTER( VNIC_DBG_VIPORT ); - netpath_restartXmit( p_viport->p_netpath ); - VNIC_EXIT( VNIC_DBG_VIPORT ); - return; -} - -void -viport_recvPacket( - IN viport_t *p_viport, - IN NDIS_PACKET **pp_pkt_arr, - IN uint32_t num_packets ) -{ - VNIC_ENTER( VNIC_DBG_VIPORT ); - netpath_recvPacket(p_viport->p_netpath, pp_pkt_arr, num_packets ); - VNIC_EXIT( VNIC_DBG_VIPORT ); - return; -} - - -void -viport_failure( - IN viport_t *p_viport ) -{ - VNIC_ENTER( VNIC_DBG_VIPORT ); - - if( !p_viport || !p_viport->p_netpath ) - return; - - InterlockedExchange( &p_viport->p_netpath->carrier, FALSE ); - - if( InterlockedExchange( (volatile LONG*)&p_viport->errored, TRUE ) == FALSE ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("IOC[%d] %s instance %d FAILED\n", - p_viport->ioc_num, - netpath_to_string( p_viport->p_netpath ), - p_viport->p_netpath->instance )); - viport_stopXmit( p_viport ); - viport_linkDown( p_viport ); - } - - VNIC_EXIT( VNIC_DBG_VIPORT ); -} - - -void -viport_timeout( - IN void *context ) -{ - viport_t *p_viport = (viport_t *)context; - CL_ASSERT( p_viport ); - - if( InterlockedExchange( &p_viport->timerActive, FALSE ) == TRUE ) - { - // did we send a query and got response ? - if( p_viport->link_hb_state != LINK_HEARTBEATRSP && - !p_viport->hb_send_pending ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("IOC[%d] instance %d HEARTBEAT TIMEOUT\n", - p_viport->ioc_num, - p_viport->p_netpath->instance )); - viport_failure( p_viport ); - return; - } - /* send heartbeat message again */ - else if( !p_viport->errored && - p_viport->state == VIPORT_CONNECTED ) - { - viport_timer( p_viport, p_viport->port_config.hbInterval ); - } - } -} - - -void -viport_timer( - IN viport_t *p_viport, - IN int timeout ) -{ - ib_api_status_t ib_status; - - VNIC_ENTER( VNIC_DBG_VIPORT ); - - if( !p_viport->errored ) - { - p_viport->link_hb_state = LINK_HEARTBEATREQ; - InterlockedExchange( &p_viport->timerActive, TRUE ); - - /* we can send now */ - if( !p_viport->control.reqOutstanding ) - { - p_viport->hb_send_pending = FALSE; - cl_timer_start( &p_viport->timer, (uint32_t)timeout ); - - ib_status = control_heartbeatReq( &p_viport->control, - p_viport->port_config.hbTimeout ); - - if( ib_status != IB_SUCCESS ) - { - viport_timerStop( p_viport ); - VNIC_TRACE( VNIC_DBG_ERROR, - ("IOC[%d] instance %d HEARTBEAT send failed\n", - p_viport->ioc_num, - p_viport->p_netpath->instance )); - viport_failure( p_viport ); - return; - } - } - /* schedule send on next timeout */ - else - { - p_viport->hb_send_pending = TRUE; - cl_timer_start(&p_viport->timer, (uint32_t)timeout ); - } - } - - VNIC_EXIT( VNIC_DBG_VIPORT ); -} - - -void -viport_timerStop( - IN viport_t *p_viport ) -{ - VNIC_ENTER( VNIC_DBG_VIPORT ); - - if( p_viport ) - { - if( InterlockedExchange( &p_viport->timerActive, FALSE ) == TRUE ) - { - cl_timer_stop( &p_viport->timer ); - } - } - - VNIC_EXIT( VNIC_DBG_VIPORT ); - return; -} - -static ib_api_status_t -viport_initMacAddresses( - IN viport_t *p_viport ) -{ - int i, size; - NDIS_STATUS status; - VNIC_ENTER( VNIC_DBG_VIPORT ); - - size = p_viport->numMacAddresses * sizeof(Inic_AddressOp_t); - status = NdisAllocateMemoryWithTag( &p_viport->macAddresses, size , 'acam' ); - - if ( status != NDIS_STATUS_SUCCESS ) - { - VNIC_TRACE_EXIT( VNIC_DBG_ERROR, - ("Failed allocating MAC address table size %d\n", size) ); - return IB_INSUFFICIENT_MEMORY; - } - - NdisZeroMemory( p_viport->macAddresses, size ); - - NdisAcquireSpinLock( &p_viport->lock ); - for( i = 0; i < p_viport->numMacAddresses; i++ ) - { - p_viport->macAddresses[i].index = (uint16_t)i; - p_viport->macAddresses[i].vlan = p_viport->defaultVlan; - } - - NdisFillMemory( p_viport->macAddresses[BROADCAST_ADDR].address, - MAC_ADDR_LEN, 0xFF ); - p_viport->macAddresses[BROADCAST_ADDR].valid = TRUE; - - NdisMoveMemory( p_viport->macAddresses[UNICAST_ADDR].address, - p_viport->hwMacAddress, MAC_ADDR_LEN ); - - p_viport->macAddresses[UNICAST_ADDR].valid = TRUE; - - if( !p_viport->p_adapter->macSet ) - { - p_viport->p_adapter->macSet = TRUE; - } - - NdisReleaseSpinLock( &p_viport->lock ); - - VNIC_EXIT( VNIC_DBG_VIPORT ); - return IB_SUCCESS; -} - - -ib_api_status_t -viport_control_connect( - IN viport_t* const p_viport ) -{ - ib_api_status_t ib_status; - cl_status_t cl_status; - - VNIC_ENTER( VNIC_DBG_INIT ); - - ib_status = control_init( &p_viport->control, p_viport, - &p_viport->port_config.controlConfig, p_viport->portGuid ); - if( ib_status != IB_SUCCESS ) - { - VNIC_EXIT( VNIC_DBG_VIPORT ); - return ib_status; - } - - ib_status = ibqp_connect( &p_viport->control.qp ); - if( ib_status != IB_SUCCESS ) - { - VNIC_TRACE_EXIT( VNIC_DBG_ERROR, - ("control QP connect failed\n")); - control_cleanup( &p_viport->control ); - return ib_status; - } - - InterlockedExchange( (volatile LONG*)&p_viport->linkState, - (LONG)LINK_INITINICREQ ); - - ib_status = control_initInicReq( &p_viport->control ); - if( ib_status != IB_SUCCESS ) - { - VNIC_TRACE_EXIT( VNIC_DBG_ERROR, - ("CMD_INIT_INIC REQ failed\n") ); - - control_cleanup( &p_viport->control ); - return ib_status; - } - cl_status = cl_event_wait_on( &p_viport->sync_event, - (p_viport->control.p_conf->rspTimeout << 11), FALSE ); - - if( p_viport->linkState != LINK_INITINICRSP ) - { - VNIC_TRACE_EXIT( VNIC_DBG_ERROR, - ("CMD_INIT_INIC RSP failed: return linkstate: %d, cl_status: %d\n", - p_viport->linkState, cl_status )); - - ib_status = IB_INSUFFICIENT_RESOURCES; - control_cleanup( &p_viport->control ); - return ib_status; - } - - vnic_resume_oids( p_viport->p_adapter ); - - ib_status = viport_initMacAddresses( p_viport ); - if( ib_status != IB_SUCCESS ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("Init MAC Addresses failed\n")); - control_cleanup( &p_viport->control ); - } - - VNIC_EXIT( VNIC_DBG_INIT ); - return ib_status; -} - -ib_api_status_t -viport_data_connect( - IN viport_t* const p_viport ) -{ - NDIS_STATUS status; - ib_api_status_t ib_status; - - VNIC_ENTER( VNIC_DBG_INIT ); - - ib_status = data_init( &p_viport->data, - &p_viport->port_config.dataConfig, - p_viport->portGuid ); - if( ib_status != IB_SUCCESS ) - { - VNIC_TRACE( VNIC_DBG_ERROR, ("Data init returned %s\n", - p_viport->p_adapter->ifc.get_err_str( ib_status )) ); - return ib_status; - } - InterlockedExchange( (volatile LONG*)&p_viport->linkState, - (LONG)LINK_CONFIGDATAPATHREQ ); - - ib_status = control_configDataPathReq( &p_viport->control, - data_pathId(&p_viport->data ), data_hostPoolMax( &p_viport->data ), - data_eiocPoolMax( &p_viport->data ) ); - if( ib_status != IB_SUCCESS ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("command CONFIGDATAPATH REQ failed\n")); - return ib_status; - } - cl_event_wait_on( &p_viport->sync_event, - (p_viport->control.p_conf->rspTimeout << 11), TRUE ); - - if( p_viport->linkState != LINK_CONFIGDATAPATHRSP ) - { - VNIC_TRACE( VNIC_DBG_ERROR, - ("failed to get CONFIGDATAPATH RSP\n")); - return IB_INSUFFICIENT_RESOURCES; - } - - ib_status = data_connect( &p_viport->data ); - if( ib_status != IB_SUCCESS ) - { - VNIC_EXIT( VNIC_DBG_INIT ); - return ib_status; - } - cl_event_wait_on( &p_viport->sync_event, - (p_viport->control.p_conf->rspTimeout << 11), TRUE ); - if( p_viport->data.qp.qpState != IB_ATTACHED ) - { - VNIC_EXIT( VNIC_DBG_INIT ); - return IB_ERROR; - } - InterlockedExchange( (volatile LONG*)&p_viport->linkState, - (LONG)LINK_XCHGPOOLREQ ); - ib_status = control_exchangePoolsReq( &p_viport->control, - data_localPoolAddr(&p_viport->data), - data_localPoolRkey(&p_viport->data) ); - if( ib_status != IB_SUCCESS ) - { - VNIC_TRACE_EXIT( VNIC_DBG_ERROR, - ("command XCHGPOOL REQ failed\n")); - return ib_status; - } - cl_event_wait_on( &p_viport->sync_event, - (p_viport->control.p_conf->rspTimeout << 11), TRUE ); - - if( p_viport->linkState != LINK_XCHGPOOLRSP ) - { - VNIC_TRACE_EXIT( VNIC_DBG_ERROR, - ("failed to get LINK_XCHGPOOL RSP\n")); - return IB_ERROR; - } - - InterlockedExchange( (volatile LONG*)&p_viport->linkState, - (LONG)LINK_INITIALIZED ); - - p_viport->state = VIPORT_CONNECTED; - - ib_status = data_connected( &p_viport->data ); - if( ib_status != IB_SUCCESS ) - { - VNIC_TRACE_EXIT( VNIC_DBG_ERROR, - ("Alloc/Send Recv Buffers failed\n")); - return ib_status; - } - - p_viport->flags = 0; - - if( p_viport->p_netpath == p_viport->p_adapter->p_currentPath ) - { - status = viport_setLink( p_viport, - INIC_FLAG_ENABLE_NIC| INIC_FLAG_SET_MTU, - (uint16_t)p_viport->p_adapter->params.MinMtu, TRUE ); - if( status != NDIS_STATUS_SUCCESS ) - { - VNIC_TRACE_EXIT( VNIC_DBG_ERROR, - ("failed to set Link flags\n")); - return IB_ERROR; - } - - /* start periodic heartbeat timer for active path */ - if( p_viport->port_config.hbInterval ) - { - viport_timer( p_viport, p_viport->port_config.hbInterval ); - } - } - VNIC_EXIT( VNIC_DBG_INIT ); - return IB_SUCCESS; -} - - -NDIS_STATUS -_viport_process_query( - IN viport_t* const p_viport, - IN BOOLEAN sync ) -{ - NDIS_STATUS status; - ib_api_status_t ib_status; - LinkState_t expected_state = 0; - - VNIC_ENTER( VNIC_DBG_VIPORT ); - - if( p_viport->errored || - p_viport->p_adapter->pnp_state == IB_PNP_IOC_REMOVE ) - { - VNIC_TRACE( VNIC_DBG_WARN, - ("IOC[%d] updates = %#x packet_filter = %#x, query: %#x(%d) set: %#x(%d)\n", - p_viport->ioc_num, - p_viport->updates, - p_viport->p_adapter->packet_filter, - p_viport->p_adapter->query_oid.oid, - p_viport->p_adapter->pending_query, - p_viport->p_adapter->set_oid.oid, - p_viport->p_adapter->pending_set )); - - VNIC_TRACE_EXIT( VNIC_DBG_WARN, ("IOC[%d] in REMOVE or invalid state.\n", - p_viport->ioc_num )); - - return NDIS_STATUS_NOT_ACCEPTED; - } - - // Check for updates. Note that unless sync is set to TRUE, this - // is the only way for this function to return success. - if( !InterlockedCompareExchange( &p_viport->updates, 0, 0 ) ) - { - /* now can restart heartbeats */ - if( !p_viport->timerActive && - p_viport->port_config.hbInterval ) - { - viport_timer( p_viport, p_viport->port_config.hbInterval ); - } - return NDIS_STATUS_SUCCESS; - } - - else - { - /* stop heartbeat timer to serve another query */ - viport_timerStop( p_viport ); - } - - if( sync ) - { - status = NDIS_STATUS_SUCCESS; - InterlockedOr( &p_viport->updates, SYNC_QUERY ); - } - else - { - status = NDIS_STATUS_PENDING; - } - - // Handle update bits one at a time. - if( p_viport->updates & NEED_ADDRESS_CONFIG ) - { - VNIC_TRACE( VNIC_DBG_CONF,("QUERY NEED_ADDRESS_CONFIG\n")); - - NdisAcquireSpinLock(&p_viport->lock ); - - p_viport->linkState = LINK_CONFIGADDRSREQ; - ib_status = control_configAddrsReq( - &p_viport->control, p_viport->macAddresses, - p_viport->numMacAddresses, &p_viport->addrs_query_done ); - - NdisReleaseSpinLock( &p_viport->lock ); - - if ( ib_status != IB_SUCCESS ) - { - InterlockedAnd( &p_viport->updates, ~NEED_ADDRESS_CONFIG ); - VNIC_EXIT( VNIC_DBG_VIPORT ); - return NDIS_STATUS_FAILURE; - } - expected_state = LINK_CONFIGADDRSRSP; - } - else if( p_viport->updates & NEED_LINK_CONFIG ) - { - VNIC_TRACE( VNIC_DBG_CONF, - ("QUERY NEED_LINK_CONFIG\n")); - - NdisAcquireSpinLock(&p_viport->lock ); - - p_viport->linkState = LINK_CONFIGLINKREQ; - - if( (InterlockedAnd( - &p_viport->updates, ~MCAST_OVERFLOW ) & MCAST_OVERFLOW ) ) - { - p_viport->newFlags |= INIC_FLAG_ENABLE_MCAST_ALL; - } - else - { - p_viport->newFlags &= ~INIC_FLAG_ENABLE_MCAST_ALL; - } - - if ( p_viport->mtu != p_viport->newMtu ) - { - p_viport->newFlags |= INIC_FLAG_SET_MTU; - p_viport->mtu = p_viport->newMtu; - } - if( ( p_viport->newFlags & INIC_FLAG_ENABLE_NIC ) && - ( p_viport->p_netpath != p_viport->p_adapter->p_currentPath ) ) - { - ASSERT(0); - } - - ib_status = control_configLinkReq( &p_viport->control, - p_viport->newFlags, p_viport->newMtu ); - - p_viport->newFlags &= ~INIC_FLAG_SET_MTU; - - NdisReleaseSpinLock( &p_viport->lock ); - - if( ib_status != IB_SUCCESS ) - { - InterlockedAnd( &p_viport->updates, ~NEED_LINK_CONFIG ); - VNIC_EXIT( VNIC_DBG_VIPORT ); - return NDIS_STATUS_FAILURE; - } - expected_state = LINK_CONFIGLINKRSP; - } - else if( p_viport->updates & NEED_STATS ) - { - // TODO: - VNIC_TRACE( VNIC_DBG_CONF, - ("QUERY NEED_STATS\n")); - - NdisAcquireSpinLock( &p_viport->lock ); - - p_viport->linkState = LINK_REPORTSTATREQ; - - ib_status = control_reportStatisticsReq( &p_viport->control ); - - NdisReleaseSpinLock( &p_viport->lock ); - - if( ib_status != IB_SUCCESS ) - { - InterlockedAnd( &p_viport->updates, ~NEED_STATS ); - VNIC_EXIT( VNIC_DBG_VIPORT ); - return NDIS_STATUS_FAILURE; - } - expected_state = LINK_REPORTSTATRSP; - } - - if( sync ) - { - cl_event_wait_on( &p_viport->sync_event, EVENT_NO_TIMEOUT, TRUE ); - - if( p_viport->linkState != expected_state ) - { - status = NDIS_STATUS_FAILURE; - VNIC_TRACE( VNIC_DBG_ERROR, - ("Link state error: expected %d but got %d\n", - expected_state, p_viport->linkState)); - } - } - VNIC_EXIT( VNIC_DBG_VIPORT ); - return status; -} - -BOOLEAN -viport_canTxCsum( - IN viport_t* p_viport ) -{ - if( !p_viport ) - return FALSE; - - return( BOOLEAN )( ( p_viport->featuresSupported & - ( INIC_FEAT_IPV4_HEADERS | - INIC_FEAT_IPV6_HEADERS | - INIC_FEAT_IPV4_CSUM_TX | - INIC_FEAT_TCP_CSUM_TX | - INIC_FEAT_UDP_CSUM_TX ) ) == - ( INIC_FEAT_IPV4_HEADERS | - INIC_FEAT_IPV6_HEADERS | - INIC_FEAT_IPV4_CSUM_TX | - INIC_FEAT_TCP_CSUM_TX | - INIC_FEAT_UDP_CSUM_TX ) ); -} - -BOOLEAN -viport_canRxCsum( - IN viport_t* p_viport ) -{ - if( !p_viport ) - return FALSE; - - return( BOOLEAN )( ( p_viport->featuresSupported & - ( INIC_FEAT_IPV4_HEADERS | - INIC_FEAT_IPV6_HEADERS | - INIC_FEAT_IPV4_CSUM_RX | - INIC_FEAT_TCP_CSUM_RX | - INIC_FEAT_UDP_CSUM_RX ) ) == - ( INIC_FEAT_IPV4_HEADERS | - INIC_FEAT_IPV6_HEADERS | - INIC_FEAT_IPV4_CSUM_RX | - INIC_FEAT_TCP_CSUM_RX | - INIC_FEAT_UDP_CSUM_RX ) ); -} diff --git a/trunk/ulp/qlc_vnic/kernel/vnic_viport.h b/trunk/ulp/qlc_vnic/kernel/vnic_viport.h deleted file mode 100644 index b881e69f..00000000 --- a/trunk/ulp/qlc_vnic/kernel/vnic_viport.h +++ /dev/null @@ -1,396 +0,0 @@ -/* - * Copyright (c) 2007 QLogic Corporation. All rights reserved. - * - * This software is available to you under the OpenIB.org BSD license - * below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * $Id$ - */ -#ifndef _VNIC_VIPORT_H_ -#define _VNIC_VIPORT_H_ - -typedef struct _mc_list { - uint8_t mc_addr[MAC_ADDR_LEN]; -} mc_list_t; - -typedef enum { - VIPORT_DISCONNECTED, - VIPORT_CONNECTED -} viport_state_t; - -typedef enum { - LINK_UNINITIALIZED, - LINK_INITIALIZE, - LINK_INITIALIZECONTROL, - LINK_INITIALIZEDATA, - LINK_CONTROLCONNECT, - LINK_CONTROLCONNECTWAIT, - LINK_INITINICREQ, - LINK_INITINICRSP, - LINK_BEGINDATAPATH, - LINK_CONFIGDATAPATHREQ, - LINK_CONFIGDATAPATHRSP, - LINK_DATACONNECT, - LINK_DATACONNECTWAIT, - LINK_XCHGPOOLREQ, - LINK_XCHGPOOLRSP, - LINK_INITIALIZED, - LINK_IDLE, - LINK_IDLING, - LINK_CONFIGLINKREQ, - LINK_CONFIGLINKRSP, - LINK_CONFIGADDRSREQ, - LINK_CONFIGADDRSRSP, - LINK_REPORTSTATREQ, - LINK_REPORTSTATRSP, - LINK_HEARTBEATREQ, - LINK_HEARTBEATRSP, - LINK_RESET, - LINK_RESETRSP, - LINK_RESETCONTROL, - LINK_RESETCONTROLRSP, - LINK_DATADISCONNECT, - LINK_CONTROLDISCONNECT, - LINK_CLEANUPDATA, - LINK_CLEANUPCONTROL, - LINK_DISCONNECTED, - LINK_RETRYWAIT -} LinkState_t; - -/* index entries */ -#define BROADCAST_ADDR 0 -#define UNICAST_ADDR 1 -#define MCAST_ADDR_START 2 -#define MAX_MCAST (MAX_ADDR_ARRAY - MCAST_ADDR_START) - -#define currentMacAddress macAddresses[UNICAST_ADDR].address - -#define NEED_STATS 0x00000001 -#define NEED_ADDRESS_CONFIG 0x00000002 -#define NEED_LINK_CONFIG 0x00000004 -#define MCAST_OVERFLOW 0x00000008 -#define SYNC_QUERY 0x80000000 - -typedef enum { - NETPATH_TS_IDLE, - NETPATH_TS_ACTIVE, - NETPATH_TS_EXPIRED -} netpathTS_t; - - -typedef struct { - LIST_ENTRY listPtrs; - struct _vnic_adapter *p_adapter; - uint8_t event_num; -} InicNPEvent_t; - -typedef enum { - NETPATH_PRIMARY = 1, - NETPATH_SECONDARY = 2 -} netpath_instance_t; - - -typedef struct Netpath { - volatile LONG carrier; - struct _vnic_adapter *p_adapter; - struct _viport *pViport; - ib_path_rec_t *p_path_rec; - uint64_t connectTime; - netpathTS_t timerState; - netpath_instance_t instance; -} Netpath_t; - -typedef enum { - WAIT, - DELAY, - NOW -} conn_wait_state_t; - -typedef struct _viport { - LIST_ENTRY listPtrs; - NDIS_SPIN_LOCK lock; - cl_obj_t obj; - struct _vnic_adapter *p_adapter; - struct Netpath *p_netpath; - struct ViportConfig port_config; - struct Control control; - struct Data data; - uint64_t iocGuid; - uint64_t portGuid; - uint32_t ioc_num; - // connected/disconnected state of control and data QPs. - viport_state_t state; - - // Control Path cmd state Query/Rsp - LinkState_t linkState; - LinkState_t link_hb_state; - Inic_CmdReportStatisticsRsp_t stats; - uint64_t lastStatsTime; - uint32_t featuresSupported; - uint8_t hwMacAddress[MAC_ADDR_LEN]; - uint16_t defaultVlan; - uint16_t numMacAddresses; - Inic_AddressOp_t *macAddresses; - int32_t addrs_query_done; - - // Indicates actions (to the VEx) that need to be taken. - volatile LONG updates; - - uint8_t flags; - uint8_t newFlags; - uint16_t mtu; - uint16_t newMtu; - uint32_t errored; - uint32_t disconnect; - volatile LONG timerActive; - cl_timer_t timer; - cl_event_t sync_event; - BOOLEAN hb_send_pending; -} viport_t; - - -BOOLEAN -viport_xmitPacket( - IN viport_t* const p_viport, - IN NDIS_PACKET* const p_pkt ); - -BOOLEAN -viport_config_defaults( - IN viport_t *p_viport ); - -uint32_t -viport_get_adapter_name( - IN viport_t *p_viport ); - -void -viport_cleanup( - IN viport_t *p_viport ); - -BOOLEAN -viport_setParent( - IN viport_t *pViport, - IN struct Netpath *pNetpath); - -NDIS_STATUS -viport_setLink( - IN viport_t *pViport, - IN uint8_t flags, - IN uint16_t mtu, - IN BOOLEAN sync ); - -NDIS_STATUS -viport_getStats( - IN viport_t *pViport ); - -void -viport_timer( - IN viport_t *p_viport, - IN int timeout ); - -void -viport_timerStop( - IN viport_t *p_viport ); - -void -viport_linkUp( - IN viport_t *pViport); - -void -viport_linkDown( - IN viport_t *pViport); - -void -viport_stopXmit( - IN viport_t *pViport); - -void -viport_restartXmit( - IN viport_t *pViport); - -void -viport_recvPacket( - IN viport_t *pViport, - IN NDIS_PACKET **p_pkt, - IN uint32_t num_pkts ); - -void -viport_failure( - IN viport_t *pViport); - -BOOLEAN -viport_setUnicast( - IN viport_t* const pViport, - IN uint8_t * pAddress); - -NDIS_STATUS -viport_setMulticast( - IN viport_t* const pViport ); - -void -netpath_init( - IN struct Netpath *pNetpath, - IN struct _vnic_adapter *p_adapter ); - -BOOLEAN -netpath_addPath( - IN struct Netpath *pNetpath, - IN viport_t *pViport); - -BOOLEAN -viport_unsetParent( - IN viport_t *pViport ); - -ib_api_status_t -viport_control_connect( - IN viport_t* const p_viport ); - -ib_api_status_t -viport_data_connect( - IN viport_t* const p_viport ); - -NDIS_STATUS -_viport_process_query( - IN viport_t* const p_viport, - IN BOOLEAN sync ); - -void -viport_cancel_xmit( - IN viport_t *p_viport, - IN void *p_cancel_id ); - -BOOLEAN -netpath_removePath( - IN struct Netpath *pNetpath, - IN viport_t *p_viport ); - -void -netpath_free( - IN struct Netpath *pNetpath ); - -BOOLEAN -netpath_getStats( - IN struct Netpath *pNetpath ); - -NDIS_STATUS -netpath_setMulticast( - IN struct Netpath *pNetpath ); - -int -netpath_maxMtu( - IN struct Netpath *pNetpath); - -BOOLEAN -netpath_linkDown( - IN Netpath_t* p_netpath ); - - -BOOLEAN -netpath_linkUp( - IN Netpath_t* p_netpath ); - -BOOLEAN -netpath_is_valid( - IN Netpath_t* const p_netpath ); - -BOOLEAN -netpath_is_connected( - IN Netpath_t* const p_netpath ); - -BOOLEAN -netpath_is_primary( - IN Netpath_t* const p_netpath ); - -BOOLEAN -netpath_xmitPacket( - IN struct Netpath* pNetpath, - IN NDIS_PACKET* const p_pkt ); - -void -netpath_cancel_xmit( - IN struct Netpath* p_netpath, - IN PVOID cancel_id ); - -void -netpath_recvPacket( - IN struct Netpath* pNetpath, - IN NDIS_PACKET** pp_pkt, - IN uint32_t num_packets); - -void -netpath_stopXmit( - IN struct Netpath *pNetpath ); - -void -netpath_restartXmit( - IN struct Netpath *pNetpath ); - -void -netpath_kick( - IN struct Netpath *pNetpath); - -void -netpath_timer( - IN struct Netpath *pNetpath, - IN int timeout); - -void -netpath_tx_timeout( - IN struct Netpath *pNetpath); - -const char* -netpath_to_string( - IN struct Netpath *pNetpath ); - -BOOLEAN -netpath_setUnicast( - IN Netpath_t* p_netpath, - IN uint8_t* p_address ); - -BOOLEAN -viport_canTxCsum( - IN viport_t* p_viport ); - -BOOLEAN -viport_canRxCsum( - IN viport_t* p_viport ); - -#define viport_portGuid(pViport) ((pViport)->portGuid) -#define viport_maxMtu(pViport) data_maxMtu(&(pViport)->data) - -#define viport_getHwAddr(pViport,pAddress) \ - cl_memcpy(pAddress, (pViport)->hwMacAddress, MAC_ADDR_LEN) - -#define viport_features(pViport) ( (pViport)->featuresSupported ) - -#define netpath_getHwAddr(pNetpath, pAddress) \ - viport_getHwAddr((pNetpath)->pViport, pAddress) - -#define netpath_canTxCsum(pNetpath) \ - viport_canTxCsum( (pNetpath)->pViport ) - -#define netpath_canRxCsum(pNetpath) \ - viport_canRxCsum( (pNetpath)->pViport ) - -#endif /* _VNIC_VIPORT_H_ */ diff --git a/trunk/ulp/qlgcvnic/dirs b/trunk/ulp/qlgcvnic/dirs new file mode 100644 index 00000000..ed41dcf4 --- /dev/null +++ b/trunk/ulp/qlgcvnic/dirs @@ -0,0 +1,2 @@ +DIRS=\ + kernel diff --git a/trunk/ulp/qlgcvnic/kernel/SOURCES b/trunk/ulp/qlgcvnic/kernel/SOURCES new file mode 100644 index 00000000..3a29204d --- /dev/null +++ b/trunk/ulp/qlgcvnic/kernel/SOURCES @@ -0,0 +1,81 @@ +######################################################################## +# +# Copyright(c) Infinicon Systems All rights reserved. +# +######################################################################## + + +# The TARGETNAME. This is name of the item being built (without the +# extension. +TARGETNAME=qlgcvnic + +######################################################################## +# The path where all binaries are built. +# +TARGETPATH=..\..\..\bin\kernel\obj$(BUILD_ALT_DIR) + +######################################################################## +# The type of item that is being built. This is manditory. +# Value Meaning +# DYNLINK - A DLL. +# DRIVER - A kernel device driver. +# EXPORT_DRIVER - A kernel device driver with exports. +# PROGRAM - A windows executable. +# PROGLIB - A windows library. +# MINPORT - A miniport driver. +# GDI_DRIVER - A video driver. +# LIBRARY - A library +TARGETTYPE=MINIPORT + +######################################################################## +# The type of driver being built. This affects the include paths. +# Comment out for non-WDM drivers. +#DRIVERTYPE=WDM + +# +######################################################################## +# All the source files in this project. +# +SOURCES= inic.rc \ + vnic_driver.c \ + vnic_adapter.c \ + vnic_ib.c \ + vnic_control.c \ + vnic_data.c \ + vnic_netpath.c \ + vnic_viport.c \ + + + + +INCLUDES=..;..\..\..\inc;..\..\..\inc\kernel; + +C_DEFINES=$(C_DEFINES) -DNDIS_MINIPORT_DRIVER -DNDIS_WDM=1 \ + -DDEPRECATE_DDK_FUNCTIONS -DNDIS51_MINIPORT -DBINARY_COMPATIBLE=0 -DLBFO_ENABLED=1 + +#!if $(FREEBUILD) +# Free build will printout error messages +#C_DEFINES=$(C_DEFINES) -DFREE_BUILD_DBG=1 +#!endif + +TARGETLIBS= \ + $(DDK_LIB_PATH)\ntoskrnl.lib \ + $(DDK_LIB_PATH)\hal.lib \ + $(DDK_LIB_PATH)\ndis.lib \ + $(TARGETPATH)\*\complib.lib \ + $(TARGETPATH)\*\ibal.lib + +#!if !defined(DDK_TARGET_OS) || "$(DDK_TARGET_OS)"=="Win2K" +# +# The driver is built in the Win2K build environment +# - use the library version of safe strings +# +#TARGETLIBS= $(TARGETLIBS) $(DDK_LIB_PATH)\ntstrsafe.lib +#!endif + +######################################################################## +# Set the warning levels to maximum. +MSC_WARNING_LEVEL= /W4 +# + + diff --git a/trunk/ulp/qlgcvnic/kernel/inic.rc b/trunk/ulp/qlgcvnic/kernel/inic.rc new file mode 100644 index 00000000..84699441 --- /dev/null +++ b/trunk/ulp/qlgcvnic/kernel/inic.rc @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2005 SilverStorm Technologies. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id$ + */ + + +#include + +#define VER_FILETYPE VFT_DRV +#define VER_FILESUBTYPE VFT2_DRV_NETWORK + +#ifdef _DEBUG_ +#define VER_FILEDESCRIPTION_STR "QLogic VNIC NDIS Miniport (Debug)" +#else +#define VER_FILEDESCRIPTION_STR "QLogic VNIC NDIS Miniport" +#endif + +#define VER_INTERNALNAME_STR "qlgcvnic.sys" +#define VER_ORIGINALFILENAME_STR "qlgcvnic.sys" + +#include diff --git a/trunk/ulp/qlgcvnic/kernel/makefile b/trunk/ulp/qlgcvnic/kernel/makefile new file mode 100644 index 00000000..128ed372 --- /dev/null +++ b/trunk/ulp/qlgcvnic/kernel/makefile @@ -0,0 +1,7 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the driver components of the Windows NT DDK +# + +!INCLUDE ..\..\..\inc\openib.def diff --git a/trunk/ulp/qlgcvnic/kernel/netvnic.inf b/trunk/ulp/qlgcvnic/kernel/netvnic.inf new file mode 100644 index 00000000..fc4ae520 --- /dev/null +++ b/trunk/ulp/qlgcvnic/kernel/netvnic.inf @@ -0,0 +1,206 @@ +; QLogic Corporation Ethernet over Infiniband NIC. +; Copyright (c) QLogic Corporation all Rights Reserved. + +[Version] +Signature="$Windows NT$" +Class=Net +ClassGUID={4d36e972-e325-11ce-bfc1-08002be10318} +Provider=%Inf_Provider% +DriverVer=01/21/2008,1.0.0000.927 + +[ControlFlags] +ExcludeFromSelect = IBA\V00066aP00000030 + +; ================= Device Install section ===================== + +[DestinationDirs] +DefaultDestDir=12 + +[SourceDisksNames.x86] +1=%DiskId%,,,"" + +[SourceDisksNames.amd64] +1=%DiskId%,,,"" + +[SourceDisksNames.ia64] +1=%DiskId%,,,"" + +[SourceDisksFiles] +qlgcvnic.sys=1 + +[Manufacturer] +%Inf_Provider% = vnic.DeviceSection,ntx86,ntamd64,ntia64 + +[vnic.DeviceSection] +; empty since we don't support W9x/Me + +[vnic.DeviceSection.ntx86] +%vnic.DeviceDesc% = VNIC.DDInstall,IBA\V00066aP00000030S00066as00000030v0001, \ + IBA\V00066aP00000030S00066as00000030, \ + IBA\V00066aP00000030v0001, \ + IBA\V00066aP00000030 + +[vnic.DeviceSection.ntamd64] +%vnic.DeviceDesc% = vnic.DDInstall,IBA\V00066aP00000030S00066as00000030v0001, \ + IBA\V00066aP00000030S00066as00000030, \ + IBA\V00066aP00000030v0001, \ + IBA\V00066aP00000030 + +[vnic.DeviceSection.ntia64] +%vnic.DeviceDesc% = vnic.DDInstall,IBA\V00066aP00000030S00066as00000030v0001, \ + IBA\V00066aP00000030S00066as00000030, \ + IBA\V00066aP00000030v0001, \ + IBA\V00066aP00000030 + +[vnic.DDInstall.ntx86] +Characteristics = %CHARACTERISTICS% +AddReg = vnic.AddReg +CopyFiles = vnic.CopyFiles + +[vnic.DDInstall.ntamd64] +Characteristics = %CHARACTERISTICS% +AddReg = vnic.AddReg +CopyFiles = vnic.CopyFiles + +[vnic.DDInstall.ntia64] +Characteristics = %CHARACTERISTICS% +AddReg = vnic.AddReg +CopyFiles = vnic.CopyFiles + +[vnic.DDInstall.ntx86.Services] +AddService = qlgcvnic,%SPSVCINST_ASSOCSERVICE%,vnic.ServiceInstall,vnic.EventLogInstall + +[vnic.DDInstall.ntamd64.Services] +AddService = qlgcvnic,%SPSVCINST_ASSOCSERVICE%,vnic.ServiceInstall,vnic.EventLogInstall + +[vnic.DDInstall.ntia64.Services] +AddService = qlgcvnic,%SPSVCINST_ASSOCSERVICE%,vnic.ServiceInstall,vnic.EventLogInstall + +[vnic.CopyFiles] +qlgcvnic.sys,,,2 + +[vnic.AddReg] +HKR, Ndi, Service, 0, "qlgcvnic" +HKR, Ndi\Interfaces, UpperRange, 0, "ndis5" +HKR, Ndi\Interfaces, LowerRange, 0, "ethernet" + +HKR, Ndi\params\VlanId, ParamDesc, 0, "802.1q VlanId" +HKR, Ndi\params\VlanId, Type, 0, "dword" +HKR, Ndi\params\VlanId, Optional, 0, "1" +HKR, Ndi\params\VlanId, Default, 0, "1" +HKR, Ndi\params\VlanId, Min, 0, "1" +HKR, Ndi\params\VlanId, Max, 0, "4094" +HKR, Ndi\params\VlanId, Step, 0, "1" +HKR, Ndi\params\VlanId, Base, 0, "10" + +HKR, Ndi\params\UserPriority, ParamDesc, 0, "802.1p Priority" +HKR, Ndi\params\UserPriority, Type, 0, "dword" +HKR, Ndi\Params\UserPriority, Optional, 0, "1" +HKR, Ndi\params\UserPriority, Default, 0, "0" +HKR, Ndi\params\UserPriority, Min, 0, "0" +HKR, Ndi\params\UserPriority, Max, 0, "7" +HKR, Ndi\params\UserPriority, Step, 0, "1" + +HKR, Ndi\Params\PayloadMtu, ParamDesc, 0, "Payload Mtu size" +HKR, Ndi\Params\PayloadMtu, Type, 0, "dword" +HKR, Ndi\Params\PayloadMtu, Default, 0, "1500" +HKR, Ndi\Params\PayloadMtu, Min, 0, "1500" +HKR, Ndi\Params\PayloadMtu, Max, 0, "9500" +HKR, Ndi\Params\PayloadMtu, Step, 0, "100" +HKR, Ndi\Params\PayloadMtu, Base, 0, "10" + +HKR, Ndi\Params\UseTxCsum, ParamDesc, 0, "Send Chksum Offload" +HKR, Ndi\Params\UseTxCsum, Type, 0, "enum" +HKR, Ndi\Params\UseTxCsum, Default, 0, "1" +HKR, Ndi\Params\UseTxCsum, Optional, 0, "0" +HKR, Ndi\Params\UseTxCsum\enum, "0", 0, "Disabled" +HKR, Ndi\Params\UseTxCsum\enum, "1", 0, "Enabled" + +HKR, Ndi\Params\UseRxCsum,ParamDesc, 0, "Recv Chksum Offload" +HKR, Ndi\Params\UseRxCsum,Type, 0, "enum" +HKR, Ndi\Params\UseRxCsum,Default, 0, "1" +HKR, Ndi\Params\UseRxCsum,Optional, 0, "0" +HKR, Ndi\Params\UseRxCsum\enum, "0", 0, "Disabled" +HKR, Ndi\Params\UseRxCsum\enum, "1", 0, "Enabled" + +HKR, Ndi\Params\SecondaryPath, ParamDesc, 0, "Secondary path" +HKR, Ndi\Params\SecondaryPath, Type, 0, "enum" +HKR, Ndi\Params\SecondaryPath, Default, 0, "0" +HKR, Ndi\Params\SecondaryPath, Optional, 0, "0" +HKR, Ndi\Params\SecondaryPath\enum, "0", 0, "Disabled" +HKR, Ndi\Params\SecondaryPath\enum, "1", 0, "Enabled" + +HKR, Ndi\Params\Heartbeat, ParamDesc, 0, "Heartbeat interval (ms)" +HKR, Ndi\Params\Heartbeat, Type, 0, "dword" +HKR, Ndi\Params\Heartbeat, Default, 0, "2000" +HKR, Ndi\Params\Heartbeat, Min, 0, "0" +HKR, Ndi\Params\Heartbeat, Max, 0, "10000" +HKR, Ndi\Params\Heartbeat, Step, 0, "1000" +HKR, Ndi\Params\Heartbeat, Base, 0, "10" + +HKR, Ndi\Params\BundleId, ParamDesc, 0, "LBFO Bundle Id" +HKR, Ndi\Params\BundleId, Type, 0, "enum" +HKR, Ndi\Params\BundleId, Default, 0, "1" +HKR, Ndi\Params\BundleId, Optional, 0, "1" +HKR, Ndi\Params\BundleId\enum, "1", 0, "Bundle 1" +HKR, Ndi\Params\BundleId\enum, "2", 0, "Bundle 2" +HKR, Ndi\Params\BundleId\enum, "3", 0, "Bundle 3" +HKR, Ndi\Params\BundleId\enum, "4", 0, "Bundle 4" +; +; +; ============= Service Install section ============== +; + +[vnic.ServiceInstall] +DisplayName = %vnic.ServiceDesc% +ServiceType = %SERVICE_KERNEL_DRIVER% +StartType = %SERVICE_DEMAND_START% +ErrorControl = %SERVICE_ERROR_NORMAL% +ServiceBinary = %12%\qlgcvnic.sys +LoadOrderGroup = NDIS +AddReg = vnic.ParamsReg + +[vnic.ParamsReg] + +HKR,"Parameters","DebugFlags",%REG_DWORD%,0x00000003 + +HKR,"Parameters","MinHostPoolSz",%REG_DWORD%,256 +HKR, "Parameters","HostRecvPoolEntries",%REG_DWORD%,512 +HKR, "Parameters","MinEiocPoolSz",%REG_DWORD%,256 +HKR, "Parameters","MaxEiocPoolSz",%REG_DWORD%,512 +HKR, "Parameters","MinHostKickTimeout",%REG_DWORD%,50 +HKR, "Parameters","MaxHostKickTimeout",%REG_DWORD%,100 +HKR, "Parameters","MinHostKickEntries",%REG_DWORD%,1 +HKR, "Parameters","MaxHostKickEntries",%REG_DWORD%,64 +HKR, "Parameters","MinHostKickBytes",%REG_DWORD%,0 +HKR, "Parameters","MaxHostKickBytes",%REG_DWORD%,5000 +HKR, "Parameters","MinHostUpdateSz",%REG_DWORD%,8 +HKR, "Parameters","MaxHostUpdateSz",%REG_DWORD%,32 +HKR, "Parameters","MinEiocUpdateSz",%REG_DWORD%,8 +HKR, "Parameters","MaxEiocUpdateSz",%REG_DWORD%,32 +HKR, "Parameters","HeartbeatTimeout",%REG_DWORD%,40000 + +[vnic.EventLogInstall] +AddReg = vnic.EventLogAddReg + +[vnic.EventLogAddReg] +HKR,,EventMessageFile,%REG_EXPAND_SZ%,"%%SystemRoot%%\System32\netevent.dll" +HKR,,TypesSupported,%REG_DWORD%,7 + +[Strings] +NetClassGuid="{4d36e972-e325-11ce-bfc1-08002be10318}" +Inf_Provider="QLogic Corporation" +vnic.DeviceDesc="Ethernet over InfiniBand Virtual NIC" +vnic.ServiceDesc="Virtual NIC" +DiskId="QLogic Ethernet over InfiniBand Disk" +InternalBus=0 +PNPBus=15 +SPSVCINST_NULL=0x0 +SPSVCINST_ASSOCSERVICE=0x00000002 +SERVICE_KERNEL_DRIVER=1 +SERVICE_DEMAND_START=3 +SERVICE_ERROR_NORMAL=1 +REG_DWORD=0x00010001 +REG_DWORD_NO_CLOBBER=0x00010003 +REG_EXPAND_SZ=0x00020000 +CHARACTERISTICS=0x81; NCF_VIRTUAL | NCF_HAS_UI diff --git a/trunk/ulp/qlgcvnic/kernel/vnic_adapter.c b/trunk/ulp/qlgcvnic/kernel/vnic_adapter.c new file mode 100644 index 00000000..7be95023 --- /dev/null +++ b/trunk/ulp/qlgcvnic/kernel/vnic_adapter.c @@ -0,0 +1,1815 @@ +/* + * Copyright (c) 2007 QLogic Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id$ + */ + +#include +#include +#include +#include "vnic_adapter.h" + +//#include "vnic_driver.h" + +extern struct _vnic_globals g_vnic; + +NDIS_STATUS +vnic_get_adapter_params( + IN NDIS_HANDLE h_handle, + OUT vnic_params_t* const p_params ); + +static +NDIS_STATUS +_adapter_set_sg_size( + IN NDIS_HANDLE h_handle, + IN ULONG mtu_size ); + +NDIS_STATUS +vnic_get_adapter_interface( + IN NDIS_HANDLE h_handle, + IN vnic_adapter_t *p_adapter); + +static +vnic_path_record_t* +__path_record_add( + IN vnic_adapter_t* const p_adapter, + IN ib_path_rec_t* const p_path_rec ); + +static +vnic_path_record_t* +__path_record_remove( + IN vnic_adapter_t* const p_adapter, + IN ib_path_rec_t* const p_path_rec ); + +static BOOLEAN +__path_records_match( + IN ib_path_rec_t* const p_path1, + IN ib_path_rec_t* const p_path2 ); + +static +vnic_path_record_t * +__path_record_find( + IN vnic_adapter_t* const p_adapter, + IN ib_path_rec_t* const p_path_rec ); + +static +vnic_path_record_t* +__path_record_get( + IN vnic_adapter_t* const p_adapter ); + +static void +__path_records_cleanup( + IN vnic_adapter_t *p_adapter ); + +static ib_api_status_t +_adapter_open_ca( + IN vnic_adapter_t* const p_adapter ); + + +static ib_api_status_t +_adapter_close_ca( + IN vnic_adapter_t* const p_adapter ); + +static +ib_api_status_t +_adapter_netpath_update( + IN vnic_adapter_t* const p_adapter, + IN viport_t* const p_viport, + IN vnic_path_record_t* p_path ); + +static +ib_api_status_t +adapter_netpath_update_and_connect( + IN vnic_adapter_t* const p_adapter, + IN vnic_path_record_t *p_path ); + +static inline uint8_t +_get_ioc_num_from_iocguid( + IN ib_net64_t *p_iocguid ); + +static BOOLEAN +__sid_valid( + IN vnic_adapter_t *p_adapter, + IN ib_net64_t sid ); + +static void +__adapter_cleanup( + IN vnic_adapter_t *p_adapter ); + +#if ( LBFO_ENABLED ) + +static NDIS_STATUS +__adapter_set_failover_primary( + IN vnic_adapter_t* const p_adapter, + IN BOOLEAN promote_secondary ); + +static NDIS_STATUS +__adapter_set_failover_secondary( + IN vnic_adapter_t* const p_adapter, + IN NDIS_HANDLE primary_handle ); + +static void +__adapter_add_to_failover_list( + IN vnic_adapter_t* const p_adapter, + IN lbfo_state_t failover_state ); +static void +__adapter_remove_from_failover_list( + IN vnic_adapter_t* const p_adapter ); + +static +vnic_adapter_t* +__adapter_find_on_failover_list( + IN int list_flag, + IN uint32_t bundle_id ); + +#endif // LBFO_ENABLED + +ib_api_status_t +vnic_create_adapter( + IN NDIS_HANDLE h_handle, + IN NDIS_HANDLE wrapper_config_context, + OUT vnic_adapter_t** const pp_adapter) +{ + NDIS_STATUS status; + ib_api_status_t ib_status; + vnic_adapter_t *p_adapter; + + VNIC_ENTER( VNIC_DBG_ADAPTER ); + + status = NdisAllocateMemoryWithTag( &p_adapter, sizeof(vnic_adapter_t), 'pada'); + + if ( status != NDIS_STATUS_SUCCESS ) + { + VNIC_TRACE_EXIT(VNIC_DBG_ERROR,("Failed to allocate adapter\n")); + return IB_INSUFFICIENT_MEMORY; + } + + NdisZeroMemory( p_adapter, sizeof(vnic_adapter_t) ); + + NdisAllocateSpinLock( &p_adapter->lock ); + NdisAllocateSpinLock( &p_adapter->path_records_lock ); + NdisAllocateSpinLock( &p_adapter->pending_list_lock ); + NdisAllocateSpinLock( &p_adapter->cancel_list_lock ); + + InitializeListHead( &p_adapter->send_pending_list ); + InitializeListHead( &p_adapter->cancel_send_list ); + + cl_qlist_init( &p_adapter->path_records_list ); + + status = + vnic_get_adapter_params( wrapper_config_context, &p_adapter->params ); + + if ( status != NDIS_STATUS_SUCCESS ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + (" vnic_get_adapter_params failed with status %d\n", status)); + NdisFreeMemory( p_adapter, sizeof(vnic_adapter_t), 0 ); + return IB_INVALID_PARAMETER; + } + + status = vnic_get_adapter_interface( h_handle, p_adapter ); + if ( status != NDIS_STATUS_SUCCESS ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("failed status %x\n", status ) ); + NdisFreeMemory( p_adapter, sizeof(vnic_adapter_t), 0 ); + return IB_INVALID_PARAMETER; + } + + /*Open AL */ + ib_status = p_adapter->ifc.open_al( &p_adapter->h_al ); + if ( ib_status != IB_SUCCESS ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("ib_open_al returned %s\n", + p_adapter->ifc.get_err_str( ib_status )) ); + NdisFreeMemory( p_adapter, sizeof(vnic_adapter_t), 0 ); + return ib_status; + } + + /* we will use these indexes later as an viport instance ID for connect request + * since target requires unique instance per connection per IOC. + */ + p_adapter->primaryPath.instance = NETPATH_PRIMARY; + p_adapter->secondaryPath.instance = NETPATH_SECONDARY; + + /* set adapter level params here */ + p_adapter->vlan_info = p_adapter->params.VlanInfo; + +#if ( LBFO_ENABLED ) + + p_adapter->failover.bundle_id = p_adapter->params.bundle_id; + p_adapter->failover.fo_state = _ADAPTER_NOT_BUNDLED; + +#endif + + p_adapter->h_handle = h_handle; + *pp_adapter = p_adapter; + + VNIC_EXIT( VNIC_DBG_ADAPTER ); + return IB_SUCCESS; +} + + +void +vnic_destroy_adapter( + IN vnic_adapter_t *p_adapter) +{ + ib_api_status_t ib_status = IB_SUCCESS; + ib_pnp_handle_t h_pnp; + ib_al_handle_t h_al; + + VNIC_ENTER( VNIC_DBG_ADAPTER ); + + ASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL ); + + if( ( h_pnp = InterlockedExchangePointer( (void *)&p_adapter->h_pnp, NULL ) ) != NULL ) + { + ib_status = + p_adapter->ifc.dereg_pnp( h_pnp, NULL ); + } + + /* should not receive new path notifications anymore, safe to cleanup */ + + if( InterlockedCompareExchange( (volatile LONG *)&p_adapter->state, + INIC_DEREGISTERING, INIC_REGISTERED ) == INIC_REGISTERED ) + { + __adapter_cleanup( p_adapter ); + } + + _adapter_close_ca( p_adapter ); + +#if ( LBFO_ENABLED ) + + __adapter_remove_from_failover_list( p_adapter ); + +#endif + + InterlockedExchange( (volatile LONG *)&p_adapter->state, INIC_UNINITIALIZED ); + if( ( h_al = InterlockedExchangePointer( (void *)&p_adapter->h_al, NULL ) ) != NULL ) + { + ib_status = p_adapter->ifc.close_al( h_al ); + ASSERT( ib_status == IB_SUCCESS ); + } + + NdisFreeSpinLock( &p_adapter->lock ); + NdisFreeSpinLock( &p_adapter->path_records_lock ); + NdisFreeMemory( p_adapter, sizeof(vnic_adapter_t), 0 ); + p_adapter = NULL; + + VNIC_EXIT( VNIC_DBG_ADAPTER ); +} + +static ib_api_status_t +_adapter_open_ca( + IN vnic_adapter_t* const p_adapter ) +{ + ib_api_status_t ib_status = IB_SUCCESS; + ib_al_ifc_t *p_ifc = &p_adapter->ifc; + uint32_t attr_size; + ib_ca_attr_t *p_ca_attrs; + uint32_t num; + uint64_t start_addr = 0; + + if( p_adapter->h_ca ) + return ib_status; + + ib_status = p_ifc->open_ca( p_adapter->h_al, + p_adapter->ifc_data.ca_guid, + NULL, //ib_asyncEvent, + p_adapter, + &p_adapter->h_ca ); + + if ( ib_status != IB_SUCCESS ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("Failed to open hca\n") ); + return IB_INSUFFICIENT_RESOURCES; + } + + ib_status = p_ifc->query_ca( p_adapter->h_ca, NULL , &attr_size ); + if( ib_status != IB_INSUFFICIENT_MEMORY ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("ib_query_ca failed status %s\n", + p_ifc->get_err_str( ib_status )) ); + + ib_status = IB_INSUFFICIENT_RESOURCES; + goto ca_failure; + } + + ASSERT( attr_size ); + + p_ca_attrs = cl_zalloc( attr_size ); + if ( p_ca_attrs == NULL ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("Allocate %d bytes failed for Channel adapter\n", attr_size )); + + ib_status = IB_INSUFFICIENT_MEMORY; + goto ca_failure; + } + + ib_status = p_ifc->query_ca( p_adapter->h_ca, p_ca_attrs , &attr_size ); + if ( ib_status != IB_SUCCESS ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("CA attributes query failed\n") ); + cl_free ( p_ca_attrs ); + goto ca_failure; + } + + p_adapter->ca.numPorts = p_ca_attrs->num_ports; + if( p_adapter->ca.numPorts > VNIC_CA_MAX_PORTS ) + p_adapter->ca.numPorts = VNIC_CA_MAX_PORTS; + + for( num = 0; num < p_adapter->ca.numPorts; num++ ) + p_adapter->ca.portGuids[num] = p_ca_attrs->p_port_attr[num].port_guid; + + p_adapter->ca.caGuid = p_adapter->ifc_data.ca_guid; + + cl_free ( p_ca_attrs ); + + ib_status = p_adapter->ifc.alloc_pd( p_adapter->h_ca, + IB_PDT_NORMAL, p_adapter, &p_adapter->ca.hPd ); + if ( ib_status != IB_SUCCESS ) + { + VNIC_TRACE_EXIT ( VNIC_DBG_ERROR, + ("Alloc PD failed status %s(%d)\n", + p_adapter->ifc.get_err_str(ib_status), ib_status )); + goto ca_failure; + } + + if ( ( ib_status = ibregion_physInit( p_adapter, + &p_adapter->ca.region, + p_adapter->ca.hPd, + &start_addr, + MAX_PHYS_MEMORY ) ) != IB_SUCCESS ) + { + VNIC_TRACE_EXIT ( VNIC_DBG_ERROR, + ("phys region init failed status %s(%d)\n", + p_adapter->ifc.get_err_str(ib_status), ib_status )); + p_adapter->ifc.dealloc_pd( p_adapter->ca.hPd, NULL ); + goto ca_failure; + } + + return ib_status; + +ca_failure: + if( p_adapter->h_ca ) + p_ifc->close_ca( p_adapter->h_ca, NULL ); + + return ib_status; +} + +static BOOLEAN +_adapter_params_sanity_check(vnic_params_t *p_params) +{ + DEFAULT_PARAM( p_params->MaxAddressEntries, MAX_ADDRESS_ENTRIES ); + DEFAULT_PARAM( p_params->MinAddressEntries, MIN_ADDRESS_ENTRIES ); + + DEFAULT_PARAM( p_params->ViportStatsInterval, VIPORT_STATS_INTERVAL ); + DEFAULT_PARAM( p_params->ViportHbInterval, VIPORT_HEARTBEAT_INTERVAL ); + DEFAULT_PARAM( p_params->ViportHbTimeout, VIPORT_HEARTBEAT_TIMEOUT ); + + DEFAULT_PARAM( p_params->ControlRspTimeout, CONTROL_RSP_TIMEOUT ); + DEFAULT_PARAM( p_params->ControlReqRetryCount, CONTROL_REQ_RETRY_COUNT ); + + DEFAULT_PARAM( p_params->RetryCount, RETRY_COUNT ); + DEFAULT_PARAM( p_params->MinRnrTimer, MIN_RNR_TIMER ); + + DEFAULT_PARAM( p_params->MaxViportsPerNetpath, MAX_VIPORTS_PER_NETPATH ); + DEFAULT_PARAM( p_params->DefaultViportsPerNetpath, DEFAULT_VIPORTS_PER_NETPATH ); + + DEFAULT_PARAM( p_params->DefaultPkey, DEFAULT_PKEY ); + DEFAULT_PARAM( p_params->NotifyBundleSz, NOTIFY_BUNDLE_SZ ); + DEFAULT_PARAM( p_params->DefaultNoPathTimeout, DEFAULT_NO_PATH_TIMEOUT ); + DEFAULT_PARAM( p_params->DefaultPrimaryConnectTimeout, DEFAULT_PRI_CON_TIMEOUT ); + DEFAULT_PARAM( p_params->DefaultPrimaryReconnectTimeout, DEFAULT_PRI_RECON_TIMEOUT ); + DEFAULT_PARAM( p_params->DefaultPrimarySwitchTimeout, DEFAULT_PRI_SWITCH_TIMEOUT ); + DEFAULT_PARAM( p_params->DefaultPreferPrimary, DEFAULT_PREFER_PRIMARY ); + + U32_RANGE( p_params->MaxAddressEntries ); + U32_RANGE( p_params->MinAddressEntries ); + RANGE_CHECK( p_params->MinMtu, MIN_MTU, MAX_MTU ); + RANGE_CHECK( p_params->MaxMtu, MIN_MTU, MAX_MTU ); + U32_RANGE( p_params->HostRecvPoolEntries ); + U32_RANGE( p_params->MinHostPoolSz ); + U32_RANGE( p_params->MinEiocPoolSz ); + U32_RANGE( p_params->MaxEiocPoolSz ); + U32_ZERO_RANGE( p_params->MinHostKickTimeout ); + U32_ZERO_RANGE( p_params->MaxHostKickTimeout ); + U32_ZERO_RANGE( p_params->MinHostKickEntries ); + U32_ZERO_RANGE( p_params->MaxHostKickEntries ); + U32_ZERO_RANGE( p_params->MinHostKickBytes ); + U32_ZERO_RANGE( p_params->MaxHostKickBytes ); + U32_RANGE( p_params->MinHostUpdateSz ); + U32_RANGE( p_params->MaxHostUpdateSz ); + U32_RANGE( p_params->MinEiocUpdateSz ); + U32_RANGE( p_params->MaxEiocUpdateSz ); + U8_RANGE( p_params->NotifyBundleSz ); + U32_ZERO_RANGE( p_params->ViportStatsInterval ); + U32_ZERO_RANGE( p_params->ViportHbInterval ); + U32_ZERO_RANGE( p_params->ViportHbTimeout ); + U32_RANGE( p_params->ControlRspTimeout ); + U8_RANGE( p_params->ControlReqRetryCount ); + ZERO_RANGE_CHECK( p_params->RetryCount, 0, 7 ); + ZERO_RANGE_CHECK( p_params->MinRnrTimer, 0, 31 ); + U32_RANGE( p_params->DefaultViportsPerNetpath ); + U8_RANGE( p_params->MaxViportsPerNetpath ); + U16_ZERO_RANGE( p_params->DefaultPkey ); + U32_RANGE( p_params->DefaultNoPathTimeout ); + U32_RANGE( p_params->DefaultPrimaryConnectTimeout ); + U32_RANGE( p_params->DefaultPrimaryReconnectTimeout ); + U32_RANGE( p_params->DefaultPrimarySwitchTimeout ); + BOOLEAN_RANGE( p_params->DefaultPreferPrimary ); + BOOLEAN_RANGE( p_params->UseRxCsum ); + BOOLEAN_RANGE( p_params->UseTxCsum ); + + LESS_THAN_OR_EQUAL( p_params->MinAddressEntries, p_params->MaxAddressEntries ); + LESS_THAN_OR_EQUAL( p_params->MinMtu, p_params->MaxMtu ); + LESS_THAN_OR_EQUAL( p_params->MinHostPoolSz, p_params->HostRecvPoolEntries ); + POWER_OF_2( p_params->HostRecvPoolEntries ); + POWER_OF_2( p_params->MinHostPoolSz ); + POWER_OF_2( p_params->NotifyBundleSz ); + LESS_THAN( p_params->NotifyBundleSz, p_params->MinEiocPoolSz ); + LESS_THAN_OR_EQUAL( p_params->MinEiocPoolSz, p_params->MaxEiocPoolSz ); + POWER_OF_2( p_params->MinEiocPoolSz ); + POWER_OF_2( p_params->MaxEiocPoolSz ); + LESS_THAN_OR_EQUAL( p_params->MinHostKickTimeout, p_params->MaxHostKickTimeout ); + LESS_THAN_OR_EQUAL( p_params->MinHostKickEntries, p_params->MaxHostKickEntries ); + LESS_THAN_OR_EQUAL( p_params->MinHostKickBytes, p_params->MaxHostKickBytes ); + LESS_THAN_OR_EQUAL( p_params->MinHostUpdateSz, p_params->MaxHostUpdateSz ); + POWER_OF_2( p_params->MinHostUpdateSz ); + POWER_OF_2( p_params->MaxHostUpdateSz ); + LESS_THAN( p_params->MinHostUpdateSz, p_params->MinHostPoolSz ); + LESS_THAN( p_params->MaxHostUpdateSz, p_params->HostRecvPoolEntries ); + LESS_THAN_OR_EQUAL( p_params->MinEiocUpdateSz, p_params->MaxEiocUpdateSz ); + POWER_OF_2( p_params->MinEiocUpdateSz ); + POWER_OF_2( p_params->MaxEiocUpdateSz ); + LESS_THAN( p_params->MinEiocUpdateSz, p_params->MinEiocPoolSz ); + LESS_THAN( p_params->MaxEiocUpdateSz, p_params->MaxEiocPoolSz ); + LESS_THAN_OR_EQUAL( p_params->DefaultViportsPerNetpath, p_params->MaxViportsPerNetpath ); + + return TRUE; + +} +NDIS_STATUS +vnic_get_adapter_params( + IN NDIS_HANDLE wrapper_config_context, + OUT vnic_params_t* const p_params ) +{ + NDIS_STATUS status; + NDIS_HANDLE h_config; + NDIS_CONFIGURATION_PARAMETER *p_reg_prm; + NDIS_STRING keyword; + + VNIC_ENTER( VNIC_DBG_ADAPTER ); + + CL_ASSERT(p_params ); + + /* prepare params for default initialization */ + cl_memset( p_params, 0xff, sizeof (vnic_params_t) ); + + NdisOpenConfiguration( &status, &h_config, wrapper_config_context ); + if( status != NDIS_STATUS_SUCCESS ) + { + VNIC_TRACE_EXIT( VNIC_DBG_ERROR, + ("NdisOpenConfiguration returned 0x%.8x\n", status) ); + return status; + } + + status = NDIS_STATUS_FAILURE; + p_reg_prm = NULL; + + RtlInitUnicodeString( &keyword, L"PayloadMtu" ); + NdisReadConfiguration( + &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger ); + + p_params->MinMtu = ( status != NDIS_STATUS_SUCCESS ) ? MIN_MTU: + p_reg_prm->ParameterData.IntegerData; + p_params->MaxMtu = MAX_MTU; + + RtlInitUnicodeString( &keyword, L"UseRxCsum" ); + NdisReadConfiguration( + &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger ); + + p_params->UseRxCsum = ( status != NDIS_STATUS_SUCCESS ) ? + TRUE : ( p_reg_prm->ParameterData.IntegerData )? TRUE : FALSE; + + RtlInitUnicodeString( &keyword, L"UseTxCsum" ); + NdisReadConfiguration( + &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger ); + + /* turn it on by default, if not present */ + p_params->UseTxCsum = ( status != NDIS_STATUS_SUCCESS ) ? + TRUE : ( p_reg_prm->ParameterData.IntegerData )? TRUE : FALSE; + + /* handle VLAN + Priority paramters */ + RtlInitUnicodeString( &keyword, L"VlanId" ); + NdisReadConfiguration( + &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger ); + + if( status == NDIS_STATUS_SUCCESS ) + { + p_params->VlanInfo = + ( p_reg_prm->ParameterData.IntegerData & 0x00000fff ); + + RtlInitUnicodeString( &keyword, L"UserPriority" ); + NdisReadConfiguration( + &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger ); + + p_params->VlanInfo |= ( status != NDIS_STATUS_SUCCESS ) ? 0 : + ( ( p_reg_prm->ParameterData.IntegerData & 0x00000007 ) << 13 ); + } + else + { + p_params->VlanInfo = 0; + } + + RtlInitUnicodeString( &keyword, L"SecondaryPath" ); + NdisReadConfiguration( + &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger ); + + /* disable, if not set. Save extra viport slot */ + p_params->SecondaryPath = ( status != NDIS_STATUS_SUCCESS ) ? + FALSE : ( p_reg_prm->ParameterData.IntegerData )? TRUE : FALSE; + + RtlInitUnicodeString( &keyword, L"Heartbeat" ); + NdisReadConfiguration( + &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger ); + + p_params->ViportHbInterval = ( status != NDIS_STATUS_SUCCESS ) ? + VIPORT_HEARTBEAT_INTERVAL : p_reg_prm->ParameterData.IntegerData; + +#if ( LBFO_ENABLED ) + /* read Failover group Name/Number */ + + RtlInitUnicodeString( &keyword, L"BundleId" ); + NdisReadConfiguration( + &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger ); + + p_params->bundle_id = ( status != NDIS_STATUS_SUCCESS ) ? 0 : + p_reg_prm->ParameterData.IntegerData; +#endif // LBFO_ENABLED + + NdisCloseConfiguration( h_config ); + + /* initialize the rest of adapter parameters with driver's global set */ + if( g_vnic.p_params != NULL ) + { + /* get global parameters from service entry */ + p_params->MinHostPoolSz = g_vnic.p_params[INDEX_MIN_HOST_POOL_SZ].value; + p_params->HostRecvPoolEntries = g_vnic.p_params[INDEX_HOST_RECV_POOL_ENTRIES].value; + + p_params->MinEiocPoolSz = g_vnic.p_params[INDEX_MIN_EIOC_POOL_SZ].value; + p_params->MaxEiocPoolSz = g_vnic.p_params[INDEX_MAX_EIOC_POOL_SZ].value; + + p_params->MinHostKickTimeout = g_vnic.p_params[INDEX_MIN_HOST_KICK_TIMEOUT].value; + p_params->MaxHostKickTimeout = g_vnic.p_params[INDEX_MAX_HOST_KICK_TIMEOUT].value; + + p_params->MinHostKickEntries = g_vnic.p_params[INDEX_MIN_HOST_KICK_ENTRIES].value; + p_params->MaxHostKickEntries = g_vnic.p_params[INDEX_MAX_HOST_KICK_ENTRIES].value; + + p_params->MinHostKickBytes = g_vnic.p_params[INDEX_MIN_HOST_KICK_BYTES].value; + p_params->MaxHostKickBytes = g_vnic.p_params[INDEX_MAX_HOST_KICK_BYTES].value; + + p_params->MinHostUpdateSz = g_vnic.p_params[INDEX_MIN_HOST_UPDATE_SZ].value; + p_params->MaxHostUpdateSz = g_vnic.p_params[INDEX_MAX_HOST_UPDATE_SZ].value; + + p_params->MinEiocUpdateSz = g_vnic.p_params[INDEX_MIN_EIOC_UPDATE_SZ].value; + p_params->MaxEiocUpdateSz = g_vnic.p_params[INDEX_MAX_EIOC_UPDATE_SZ].value; + + p_params->ViportHbTimeout = g_vnic.p_params[INDEX_HEARTBEAT_TIMEOUT].value; + } + else + { + /* set default constants */ + p_params->MinHostPoolSz = MIN_HOST_POOL_SZ; + p_params->HostRecvPoolEntries = HOST_RECV_POOL_ENTRIES; + p_params->MinEiocPoolSz = MIN_EIOC_POOL_SZ; + p_params->MaxEiocPoolSz = MAX_EIOC_POOL_SZ; + p_params->MinHostKickTimeout = MIN_HOST_KICK_TIMEOUT; + p_params->MaxHostKickTimeout = MAX_HOST_KICK_TIMEOUT; + p_params->MinHostKickEntries = MIN_HOST_KICK_ENTRIES; + p_params->MaxHostKickEntries = MAX_HOST_KICK_ENTRIES; + p_params->MinHostKickBytes = MIN_HOST_KICK_BYTES; + p_params->MaxHostKickBytes = MAX_HOST_KICK_BYTES; + p_params->MinHostUpdateSz = MIN_HOST_UPDATE_SZ; + p_params->MaxHostUpdateSz = MAX_HOST_UPDATE_SZ; + p_params->MinEiocUpdateSz = MIN_EIOC_UPDATE_SZ; + p_params->MaxEiocUpdateSz = MAX_EIOC_UPDATE_SZ; + } + + status = ( _adapter_params_sanity_check(p_params)? + NDIS_STATUS_SUCCESS: NDIS_STATUS_FAILURE ); + + VNIC_EXIT( VNIC_DBG_ADAPTER ); + return status; +} + +ib_api_status_t +adapter_viport_allocate( + IN vnic_adapter_t* const p_adapter, + IN OUT viport_t** const pp_viport ) +{ + viport_t *p_viport; + NDIS_STATUS status; + + VNIC_ENTER( VNIC_DBG_ADAPTER ); + + NdisAcquireSpinLock( &p_adapter->lock ); + + status = NdisAllocateMemoryWithTag( &p_viport, sizeof(viport_t), 'trop' ); + if( status != NDIS_STATUS_SUCCESS ) + { + NdisReleaseSpinLock( &p_adapter->lock ); + VNIC_TRACE_EXIT(VNIC_DBG_ERROR, + ( "Failed allocating Viport structure\n" )); + return IB_ERROR; + } + + NdisZeroMemory( p_viport, sizeof(viport_t) ); + NdisAllocateSpinLock( &p_viport->lock ); + InitializeListHead( &p_viport->listPtrs ); + cl_event_init( &p_viport->sync_event, FALSE ); + + p_viport->p_adapter = p_adapter; + viport_config_defaults ( p_viport ); + + control_construct( &p_viport->control, p_viport ); + data_construct( &p_viport->data, p_viport ); + + p_viport->ioc_num = _get_ioc_num_from_iocguid( &p_adapter->ifc_data.guid ); + if( !p_adapter->ioc_num ) + { + p_adapter->ioc_num = p_viport->ioc_num; + } + + CL_ASSERT( p_adapter->ioc_num == p_viport->ioc_num ); + + *pp_viport = p_viport; + + NdisReleaseSpinLock( &p_adapter->lock ); + + VNIC_EXIT( VNIC_DBG_ADAPTER ); + return IB_SUCCESS; +} + + +static void +_adapter_netpath_free( + IN vnic_adapter_t* const p_adapter, + IN Netpath_t* p_netpath ) +{ + + UNREFERENCED_PARAMETER( p_adapter ); + + if( netpath_is_valid( p_netpath ) ) + { + VNIC_TRACE( VNIC_DBG_INFO, + ("IOC[%d] instance %d Free Path\n", + p_adapter->ioc_num, p_netpath->instance )); + + netpath_free( p_netpath ); + netpath_init( p_netpath, NULL ); + } +} + +NDIS_STATUS +adapter_set_mcast( + IN vnic_adapter_t* const p_adapter, + IN mac_addr_t* const p_mac_array, + IN const uint8_t mc_count ) +{ + NDIS_STATUS status; + int i; + VNIC_ENTER( VNIC_DBG_MCAST ); + + if( !netpath_is_valid( p_adapter->p_currentPath ) ) + return NDIS_STATUS_NOT_ACCEPTED; + + VNIC_TRACE( VNIC_DBG_MCAST, + ("IOC[%d] MCAST COUNT to set = %d\n", + p_adapter->ioc_num, mc_count)); + + /* Copy the MC address list into the adapter. */ + if( mc_count ) + { + RtlCopyMemory( + p_adapter->mcast_array, p_mac_array, mc_count * MAC_ADDR_LEN ); + for( i = 0; i < mc_count; i++ ) + VNIC_TRACE( VNIC_DBG_MCAST, + ("[%d] %02x:%02x:%02x:%02x:%02x:%02x\n", i, + p_mac_array->addr[0], p_mac_array->addr[1], p_mac_array->addr[2], + p_mac_array->addr[3], p_mac_array->addr[4], p_mac_array->addr[5] )); + } + p_adapter->mc_count = mc_count; + + p_adapter->pending_set = TRUE; + status = netpath_setMulticast( p_adapter->p_currentPath ); + if( status != NDIS_STATUS_PENDING ) + { + p_adapter->pending_set = FALSE; + } + + VNIC_EXIT( VNIC_DBG_MCAST ); + return status; +} + + +static BOOLEAN +__path_records_match( + IN ib_path_rec_t* const p_path1, + IN ib_path_rec_t* const p_path2 ) +{ + if( p_path1->dgid.unicast.prefix != p_path2->dgid.unicast.prefix ) + return FALSE; + if( p_path1->dgid.unicast.interface_id != p_path2->dgid.unicast.interface_id ) + return FALSE; + if( p_path1->dlid != p_path2->dlid ) + return FALSE; + + if( p_path1->sgid.unicast.prefix != p_path2->sgid.unicast.prefix ) + return FALSE; + if( p_path1->sgid.unicast.interface_id != p_path2->sgid.unicast.interface_id ) + return FALSE; + if( p_path1->slid != p_path2->slid ) + return FALSE; + + if( p_path1->pkey != p_path2->pkey ) + return FALSE; + if( p_path1->rate != p_path2->rate ) + return FALSE; + if( p_path1->sl != p_path2->sl ) + return FALSE; + if( p_path1->tclass != p_path2->tclass ) + return FALSE; + + return TRUE; +} + +static BOOLEAN +__sid_valid( + IN vnic_adapter_t *p_adapter, + IN ib_net64_t sid ) +{ + vnic_sid_t svc_id; + svc_id.as_uint64 = sid; + if( ( svc_id.s.base_id & 0x10 ) != 0x10 ) + return FALSE; + if( svc_id.s.oui[0] != 0x00 && + svc_id.s.oui[1] != 0x06 && + svc_id.s.oui[2] != 0x6a ) + return FALSE; + if ( svc_id.s.type != CONTROL_SID && + svc_id.s.type != DATA_SID ) + return FALSE; + if ( svc_id.s.ioc_num != _get_ioc_num_from_iocguid( &p_adapter->ifc_data.guid ) ) + return FALSE; + return TRUE; +} +static inline uint8_t +_get_ioc_num_from_iocguid( + IN ib_net64_t *p_iocguid ) +{ + return ( (vnic_ioc_guid_t *)p_iocguid)->s.ioc_num; +} + +static +vnic_path_record_t* +__path_record_add( + IN vnic_adapter_t* const p_adapter, + IN ib_path_rec_t* const p_path_rec ) +{ + + vnic_path_record_t *p_path; + + p_path = __path_record_find( p_adapter, p_path_rec ); + + if( !p_path ) + { + p_path = cl_zalloc( sizeof( vnic_path_record_t ) ); + if( !p_path ) + return NULL; + + NdisAcquireSpinLock( &p_adapter->path_records_lock ); + + p_path->path_rec = *p_path_rec; + cl_qlist_insert_tail( &p_adapter->path_records_list, &p_path->list_entry ); + + NdisReleaseSpinLock( &p_adapter->path_records_lock ); + + VNIC_TRACE( VNIC_DBG_PNP, + ("New path Added to the list[ list size %d]\n", + cl_qlist_count(&p_adapter->path_records_list) )); + + return p_path; + } + VNIC_TRACE( VNIC_DBG_PNP, + ( "Path to add is already on the List\n" ) ); + + return NULL; +} + +static +vnic_path_record_t* +__path_record_get( + IN vnic_adapter_t* const p_adapter ) +{ + cl_list_item_t *p_item; + + p_item = cl_qlist_head( &p_adapter->path_records_list ); + + if( p_item != cl_qlist_end( &p_adapter->path_records_list ) ) + { + return ( vnic_path_record_t *)p_item; + } + return NULL; +} + +static +vnic_path_record_t* +__path_record_remove( + IN vnic_adapter_t* const p_adapter, + IN ib_path_rec_t* const p_path_rec ) +{ + + vnic_path_record_t *p_path; + + + p_path = __path_record_find( p_adapter, p_path_rec ); + + if ( p_path ) + { + NdisAcquireSpinLock( &p_adapter->path_records_lock ); + + cl_qlist_remove_item( &p_adapter->path_records_list, &p_path->list_entry ); + + NdisReleaseSpinLock( &p_adapter->path_records_lock ); + } + + return p_path; +} + +static +vnic_path_record_t * +__path_record_find( + IN vnic_adapter_t* const p_adapter, + IN ib_path_rec_t* const p_path_rec ) +{ + cl_list_item_t *p_item; + vnic_path_record_t *p_path = NULL; + + NdisAcquireSpinLock( &p_adapter->path_records_lock ); + + if( !cl_qlist_count( &p_adapter->path_records_list ) ) + { + NdisReleaseSpinLock( &p_adapter->path_records_lock ); + return NULL; + } + + p_item = cl_qlist_head( &p_adapter->path_records_list ); + + while( p_item != cl_qlist_end( &p_adapter->path_records_list ) ) + { + p_path = ( vnic_path_record_t *)p_item; + + if ( __path_records_match( &p_path->path_rec, p_path_rec ) ) + { + break; + } + + p_item = cl_qlist_next( p_item ); + } + + NdisReleaseSpinLock( &p_adapter->path_records_lock ); + + if( p_item == cl_qlist_end( &p_adapter->path_records_list ) ) + { + p_path = NULL; + } + return p_path; +} + +void +__pending_queue_cleanup( + IN vnic_adapter_t *p_adapter ) +{ + LIST_ENTRY *p_list_item; + NDIS_PACKET *p_packet; + + VNIC_ENTER( VNIC_DBG_ADAPTER ); + + /* clear pending queue if any */ + + while( ( p_list_item = NdisInterlockedRemoveHeadList( + &p_adapter->send_pending_list, + &p_adapter->pending_list_lock )) != NULL ) + { + p_packet = VNIC_PACKET_FROM_LIST_ITEM( p_list_item ); + if ( p_packet ) + { + NDIS_SET_PACKET_STATUS( p_packet, NDIS_STATUS_FAILURE ); + NdisMSendComplete( p_adapter->h_handle, p_packet, NDIS_STATUS_FAILURE ); + } + } + + VNIC_EXIT( VNIC_DBG_ADAPTER ); +} + +static void +__path_records_cleanup( + vnic_adapter_t *p_adapter ) +{ + + vnic_path_record_t *p_path; + cl_list_item_t *p_item; + + p_item = cl_qlist_remove_head( &p_adapter->path_records_list ); + + while( p_item != cl_qlist_end( &p_adapter->path_records_list ) ) + { + p_path = (vnic_path_record_t *)p_item; + + cl_free( p_path ); + + p_item = cl_qlist_remove_head( &p_adapter->path_records_list ); + } + + return; +} + +ib_api_status_t +__vnic_pnp_cb( + IN ib_pnp_rec_t *p_pnp_rec ) +{ + ib_api_status_t ib_status = IB_SUCCESS; + ib_pnp_ioc_rec_t *p_ioc_rec; + ib_pnp_ioc_path_rec_t *p_ioc_path; + vnic_path_record_t *p_path_record; + Netpath_t* p_netpath = NULL; + +#if ( LBFO_ENABLED ) + vnic_adapter_t *p_primary_adapter; +#endif + + vnic_adapter_t * __ptr64 p_adapter = (vnic_adapter_t * __ptr64)p_pnp_rec->pnp_context; + + VNIC_ENTER( VNIC_DBG_PNP ); + + CL_ASSERT( p_adapter ); + + switch( p_pnp_rec->pnp_event ) + { + case IB_PNP_IOC_ADD: + p_ioc_rec = (ib_pnp_ioc_rec_t*)p_pnp_rec; + + if( p_adapter->ifc_data.ca_guid != p_ioc_rec->ca_guid ) + { + ib_status = IB_INVALID_GUID; + break; + } + if( p_adapter->ifc_data.guid != p_ioc_rec->info.profile.ioc_guid ) + { + ib_status = IB_INVALID_GUID; + break; + } + InterlockedExchange( (volatile LONG*)&p_adapter->pnp_state, IB_PNP_IOC_ADD ); + + VNIC_TRACE( VNIC_DBG_PNP, ("IB_PNP_IOC_ADD for %s.\n", + p_ioc_rec->info.profile.id_string) ); + + /* get ioc profile data */ + NdisAcquireSpinLock( &p_adapter->lock ); + + if( !__sid_valid( p_adapter, p_ioc_rec->svc_entry_array[0].id ) ) + { + NdisReleaseSpinLock( &p_adapter->lock ); + + VNIC_TRACE_EXIT( VNIC_DBG_ERROR, + ("Invalid Service ID %#I64x\n",p_ioc_rec->svc_entry_array[0].id ) ); + + ib_status = IB_INVALID_GUID; // should it be set INVALID_SERVICE_TYPE ? + break; + } + + p_adapter->ioc_info = p_ioc_rec->info; + CL_ASSERT(p_adapter->ioc_info.profile.num_svc_entries == 2 ); + + p_adapter->svc_entries[0] = p_ioc_rec->svc_entry_array[0]; + p_adapter->svc_entries[1] = p_ioc_rec->svc_entry_array[1]; + p_adapter->ioc_num = _get_ioc_num_from_iocguid( &p_adapter->ifc_data.guid ); + + VNIC_TRACE( VNIC_DBG_PNP, + ("Found %d Service Entries.\n", p_adapter->ioc_info.profile.num_svc_entries)); + + NdisReleaseSpinLock( &p_adapter->lock ); + + break; + + case IB_PNP_IOC_REMOVE: + CL_ASSERT( p_pnp_rec->guid == p_adapter->ifc_data.guid ); + + p_ioc_rec = (ib_pnp_ioc_rec_t*)p_pnp_rec; + + if( InterlockedExchange( (volatile LONG*)&p_adapter->pnp_state, IB_PNP_IOC_REMOVE ) == IB_PNP_IOC_ADD ) + { + VNIC_TRACE( VNIC_DBG_INIT, ("IB_PNP_IOC_REMOVE for %s.\n", + p_adapter->ioc_info.profile.id_string) ); + + if( netpath_is_valid( p_adapter->p_currentPath ) ) + { + netpath_stopXmit( p_adapter->p_currentPath ); + InterlockedExchange( &p_adapter->p_currentPath->carrier, (LONG)FALSE ); + netpath_linkDown( p_adapter->p_currentPath ); + __pending_queue_cleanup( p_adapter ); + } + } + break; + + case IB_PNP_IOC_PATH_ADD: + /* path for our IOC ? */ + if ( p_pnp_rec->guid != p_adapter->ifc_data.guid ) + { + VNIC_TRACE( VNIC_DBG_PNP, + ("Getting path for wrong IOC\n") ); + ib_status = IB_INVALID_GUID; + break; + } + p_ioc_path = (ib_pnp_ioc_path_rec_t*)p_pnp_rec; + + p_path_record = __path_record_add( p_adapter, &p_ioc_path->path ); + if ( p_path_record == NULL ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("Failed to add path record\n") ); + break; + } + + if( p_adapter->state == INIC_REGISTERED ) + { + if( p_adapter->num_paths > 0 ) + { + if( p_adapter->params.SecondaryPath != TRUE ) + { + VNIC_TRACE ( VNIC_DBG_WARN, + ("Allowed one path at a time\n") ); + break; + } + } + + if( p_adapter->num_paths > 1 ) + { + VNIC_TRACE ( VNIC_DBG_WARN, + ("Max Paths[%d] Connected already\n", p_adapter->num_paths) ); + break; + } + } + + ib_status = adapter_netpath_update_and_connect( + p_adapter, p_path_record ); + if( ib_status != IB_SUCCESS ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("IOC[%d] adapter_netpath_update_and_connect return %s\n", + p_adapter->ioc_num, + p_adapter->ifc.get_err_str( ib_status )) ); + break; + } + + InterlockedCompareExchange( (volatile LONG *)&p_adapter->state, + INIC_REGISTERED, INIC_UNINITIALIZED ); +#if ( LBFO_ENABLED ) + + if( p_adapter->failover.fo_state == _ADAPTER_NOT_BUNDLED ) + { + /* we don't look for zero id, since it meant to be primary by default */ + if( p_adapter->failover.bundle_id != 0 && + ( p_primary_adapter = __adapter_find_on_failover_list( _ADAPTER_PRIMARY, + p_adapter->failover.bundle_id ) ) != NULL ) + { + /* found matching primary */ + __adapter_set_failover_secondary( + p_adapter, p_primary_adapter->h_handle ); + } + else + { + /* bundle_id '0' , all go to primary */ + __adapter_set_failover_primary( p_adapter, FALSE ); + } + } + +#endif // LBFO_ENABLED + + break; + + case IB_PNP_IOC_PATH_REMOVE: + p_ioc_path = (ib_pnp_ioc_path_rec_t*)p_pnp_rec; + + VNIC_TRACE( VNIC_DBG_PNP, + ("IB_PNP_IOC_PATH_REMOVE (slid:%d dlid:%d) for %s.\n", + ntoh16( p_ioc_path->path.slid ), + ntoh16( p_ioc_path->path.dlid ), + p_adapter->ioc_info.profile.id_string)); + + p_path_record = __path_record_remove( p_adapter, &p_ioc_path->path ); + + if ( p_path_record != NULL ) + { + int fail_over = 0; + + if( p_adapter->p_currentPath->p_path_rec != &p_path_record->path_rec ) + { + VNIC_TRACE( VNIC_DBG_INFO, + ("IOC[%d] Standby Path lost\n", p_adapter->ioc_num )); + + if( p_adapter->p_currentPath != &p_adapter->primaryPath ) + { + _adapter_netpath_free( p_adapter, &p_adapter->primaryPath ); + } + else + { + _adapter_netpath_free( p_adapter, &p_adapter->secondaryPath ); + } + + cl_free( p_path_record ); + break; + } + + VNIC_TRACE( VNIC_DBG_ERROR, + ("IOC[%d]Current Path lost\n", p_adapter->ioc_num )); + + p_netpath = p_adapter->p_currentPath; + netpath_stopXmit( p_netpath ); + viport_timerStop( p_netpath->pViport ); + + if( !p_adapter->params.SecondaryPath ) + { + vnic_path_record_t* p_record; + + netpath_linkDown( p_netpath ); + _adapter_netpath_free(p_adapter, p_netpath ); + + p_record = __path_record_get( p_adapter ); + if( p_record ) + { + ib_status = adapter_netpath_update_and_connect( p_adapter, p_record ); + } + + cl_free( p_path_record ); + break; + } + + if( p_netpath == &p_adapter->primaryPath ) + { + if( netpath_is_connected( &p_adapter->secondaryPath ) ) + { + netpath_stopXmit( &p_adapter->secondaryPath ); + p_adapter->p_currentPath = &p_adapter->secondaryPath; + fail_over = 1; + VNIC_TRACE( VNIC_DBG_ERROR, + ("IOC[%d]Switch to Secondary Path\n", p_adapter->ioc_num )); + } + } + else + { + if( netpath_is_connected( &p_adapter->primaryPath ) ) + { + netpath_stopXmit( &p_adapter->primaryPath ); + p_adapter->p_currentPath = &p_adapter->primaryPath; + fail_over = 1; + VNIC_TRACE( VNIC_DBG_ERROR, + ("IOC[%d]Switch to Primary Path\n", p_adapter->ioc_num )); + } + } + if( fail_over ) + { + viport_setLink( p_adapter->p_currentPath->pViport, + INIC_FLAG_ENABLE_NIC| INIC_FLAG_SET_MTU, + (uint16_t)p_adapter->params.MinMtu, FALSE ); + } + + _adapter_netpath_free(p_adapter, p_netpath ); + cl_free( p_path_record ); + } + + break; + + default: + VNIC_TRACE( VNIC_DBG_PNP, + (" Received unhandled PnP event %#x\n", p_pnp_rec->pnp_event ) ); + break; + } + + VNIC_EXIT( VNIC_DBG_PNP ); + return ib_status; +} + + +NDIS_STATUS +vnic_get_adapter_interface( + IN NDIS_HANDLE h_handle, + IN vnic_adapter_t *p_adapter) +{ + NTSTATUS status; + ib_al_ifc_data_t data; + IO_STACK_LOCATION io_stack; + + VNIC_ENTER( VNIC_DBG_ADAPTER ); + + NdisMGetDeviceProperty( h_handle, &p_adapter->p_pdo, NULL, NULL, NULL, NULL ); + + data.size = sizeof(ioc_ifc_data_t); + data.type = &GUID_IOC_INTERFACE_DATA; + data.version = IOC_INTERFACE_DATA_VERSION; + data.p_data = &p_adapter->ifc_data; + + io_stack.MinorFunction = IRP_MN_QUERY_INTERFACE; + io_stack.Parameters.QueryInterface.Version = AL_INTERFACE_VERSION; + io_stack.Parameters.QueryInterface.Size = sizeof(ib_al_ifc_t); + io_stack.Parameters.QueryInterface.Interface = (INTERFACE*)&p_adapter->ifc; + io_stack.Parameters.QueryInterface.InterfaceSpecificData = &data; + io_stack.Parameters.QueryInterface.InterfaceType = &GUID_IB_AL_INTERFACE; + + status = cl_fwd_query_ifc( p_adapter->p_pdo, &io_stack ); + + if( !NT_SUCCESS( status ) ) + { + VNIC_TRACE_EXIT( VNIC_DBG_ERROR, + ("Query interface for VNIC interface returned %08x.\n", status) ); + return status; + } + /* + * Dereference the interface now so that the bus driver doesn't fail a + * query remove IRP. We will always get unloaded before the bus driver + * since we're a child device. + */ + p_adapter->ifc.wdm.InterfaceDereference( + p_adapter->ifc.wdm.Context ); + + VNIC_EXIT( VNIC_DBG_ADAPTER ); + + return NDIS_STATUS_SUCCESS; +} + + +static void +__adapter_cleanup( + IN vnic_adapter_t *p_adapter ) +{ + __pending_queue_cleanup( p_adapter ); + + __path_records_cleanup( p_adapter ); + + _adapter_netpath_free( p_adapter, &p_adapter->primaryPath ); + _adapter_netpath_free( p_adapter, &p_adapter->secondaryPath ); + + VNIC_EXIT( VNIC_DBG_ADAPTER ); +} + +void +__vnic_pnp_dereg_cb( + IN void* context ) +{ + vnic_adapter_t* p_adapter; + ib_api_status_t ib_status; + ib_pnp_req_t pnp_req; + + NDIS_STATUS ndis_status = NDIS_STATUS_SUCCESS; + + VNIC_ENTER( VNIC_DBG_INIT ); + + p_adapter = (vnic_adapter_t*)context; + + CL_ASSERT( !p_adapter->h_pnp ); + + /* Destroy port instances if still exist. */ + __adapter_cleanup( p_adapter ); + + if( p_adapter->pnp_state != IB_PNP_IOC_REMOVE ) + { + p_adapter->pnp_state = IB_PNP_IOC_ADD; + /* Register for IOC events */ + pnp_req.pfn_pnp_cb = __vnic_pnp_cb; + pnp_req.pnp_class = IB_PNP_IOC | IB_PNP_FLAG_REG_SYNC; + pnp_req.pnp_context = (const void *)p_adapter; + + ib_status = p_adapter->ifc.reg_pnp( p_adapter->h_al, &pnp_req, &p_adapter->h_pnp ); + if( ib_status != IB_SUCCESS ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("pnp_reg returned %s\n", + p_adapter->ifc.get_err_str( ib_status )) ); + ndis_status = NDIS_STATUS_HARD_ERRORS; + } + } + else + { + ndis_status = NDIS_STATUS_HARD_ERRORS; + } + + if( p_adapter->reset ) + { + p_adapter->reset = FALSE; + NdisMResetComplete( + p_adapter->h_handle, ndis_status, TRUE ); + } + + VNIC_EXIT( VNIC_DBG_INIT ); +} + + +ib_api_status_t +adapter_reset( + IN vnic_adapter_t* const p_adapter ) +{ + + ib_api_status_t status; + ib_pnp_handle_t h_pnp; + + VNIC_ENTER( VNIC_DBG_INIT ); + + if( p_adapter->reset ) + return IB_INVALID_STATE; + + p_adapter->reset = TRUE; + p_adapter->hung = 0; + +#if ( LBFO_ENABLED ) + __adapter_remove_from_failover_list( p_adapter ); + +#endif // LBFO_ENABLED + + if( p_adapter->h_pnp ) + { + h_pnp = p_adapter->h_pnp; + p_adapter->h_pnp = NULL; + status = p_adapter->ifc.dereg_pnp( h_pnp, __vnic_pnp_dereg_cb ); + if( status == IB_SUCCESS ) + status = IB_NOT_DONE; + } + else + { + status = IB_NOT_FOUND; + } + + VNIC_EXIT( VNIC_DBG_INIT ); + return status; +} + +static +NDIS_STATUS +_adapter_set_sg_size( + IN NDIS_HANDLE h_handle, + IN ULONG mtu_size ) +{ + NDIS_STATUS status; + ULONG buf_size; + + VNIC_ENTER( VNIC_DBG_INIT ); + + buf_size = mtu_size + ETH_VLAN_HLEN; + + status = NdisMInitializeScatterGatherDma( h_handle, TRUE, buf_size ); + + if ( status != NDIS_STATUS_SUCCESS ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("Init ScatterGatherDma failed status %#x\n", status ) ); + } + + VNIC_EXIT( VNIC_DBG_INIT ); + return status; +} + +static ib_api_status_t +_adapter_close_ca( + IN vnic_adapter_t* const p_adapter ) +{ + ib_api_status_t ib_status = IB_SUCCESS; + ib_ca_handle_t h_ca; + + VNIC_ENTER( VNIC_DBG_INIT ); + + if( !p_adapter ) + return ib_status; + + VNIC_TRACE(VNIC_DBG_INIT, + ("IOC[%d] Close CA\n", p_adapter->ioc_num )); + + if( p_adapter->ca.region.h_mr ) + { + ib_status = p_adapter->ifc.dereg_mr( p_adapter->ca.region.h_mr ); + if( ib_status != IB_SUCCESS ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("Failed to dereg MR\n")); + } + p_adapter->ca.region.h_mr = NULL; + } + + if( p_adapter->ca.hPd ) + { + ib_status = p_adapter->ifc.dealloc_pd( p_adapter->ca.hPd, NULL ); + if( ib_status != IB_SUCCESS ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("Failed to dealloc PD\n")); + } + p_adapter->ca.hPd = NULL; + } + + if( ( h_ca = InterlockedExchangePointer( (void *)&p_adapter->h_ca, NULL ) ) != NULL ) + { + + ib_status = p_adapter->ifc.close_ca( h_ca, NULL ); + if( ib_status != IB_SUCCESS ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("Failed to close CA\n")); + } + } + + VNIC_EXIT( VNIC_DBG_INIT ); + return ib_status; +} + +static +ib_api_status_t +_adapter_netpath_update( + IN vnic_adapter_t* const p_adapter, + IN viport_t* const p_viport, + IN vnic_path_record_t* p_path ) +{ + + Netpath_t *p_netpath_init; + + VNIC_ENTER( VNIC_DBG_PNP ); + + NdisAcquireSpinLock( &p_adapter->lock ); + /* set primary first */ + if( !netpath_is_valid( p_adapter->p_currentPath ) ) + { + p_netpath_init = &p_adapter->primaryPath; + p_adapter->p_currentPath = p_netpath_init; + } + + else + { + if( p_adapter->p_currentPath != &p_adapter->primaryPath ) + { + p_netpath_init = &p_adapter->primaryPath; + } + else + { + p_netpath_init = &p_adapter->secondaryPath; + } + } + + /* shouldn't really happened ?? */ + if( netpath_is_connected( p_netpath_init ) ) + { + VNIC_TRACE( VNIC_DBG_WARN, + ("No available Netpath found for update\n")); + + NdisReleaseSpinLock( &p_adapter->lock ); + return IB_NO_MATCH; + } + + p_netpath_init->p_path_rec = &p_path->path_rec; + + /* netpath initialization */ + + p_netpath_init->p_adapter = p_adapter; + p_netpath_init->pViport = p_viport; + p_netpath_init->carrier = FALSE; + + /* viport initialization */ + p_viport->p_netpath = p_netpath_init; + + p_viport->portGuid = p_netpath_init->p_path_rec->sgid.unicast.interface_id; + p_viport->port_config.dataConfig.ibConfig.pathInfo = *p_netpath_init->p_path_rec; + p_viport->port_config.controlConfig.ibConfig.pathInfo = *p_netpath_init->p_path_rec; + + /* set our instance id per IOC */ + p_viport->port_config.controlConfig.ibConfig.connData.inicInstance = (uint8_t)p_netpath_init->instance; + p_viport->port_config.dataConfig.ibConfig.connData.inicInstance = (uint8_t)p_netpath_init->instance; + /* save for later use */ + p_viport->port_config.controlConfig.inicInstance = (uint8_t)p_netpath_init->instance; + + p_viport->iocGuid = p_adapter->ioc_info.profile.ioc_guid; + p_viport->port_config.controlConfig.ibConfig.sid = p_adapter->svc_entries[0].id; + p_viport->port_config.dataConfig.ibConfig.sid = p_adapter->svc_entries[1].id; + + VNIC_TRACE( VNIC_DBG_INFO, + ("IOC[%d] instance %d [%s] is using SLID=%d DLID=%d Target:%s\n", + p_viport->ioc_num, + p_netpath_init->instance, + netpath_to_string( p_netpath_init ), + cl_ntoh16( p_path->path_rec.slid ), + cl_ntoh16( p_path->path_rec.dlid), + p_adapter->ioc_info.profile.id_string) ); + + NdisReleaseSpinLock( &p_adapter->lock ); + + VNIC_EXIT( VNIC_DBG_PNP ); + return IB_SUCCESS; +} + +static +ib_api_status_t +adapter_netpath_update_and_connect( + IN vnic_adapter_t* const p_adapter, + IN vnic_path_record_t* p_path ) +{ + ib_api_status_t ib_status; + viport_t* p_viport; + + ib_status = adapter_viport_allocate( p_adapter, &p_viport ); + if( ib_status != IB_SUCCESS ) + { + VNIC_TRACE ( VNIC_DBG_ERROR, + ("IOC[%] Viport allocate Failed status %s\n", + p_adapter->ioc_num, p_adapter->ifc.get_err_str( ib_status )) ); + goto err; + } + + ib_status = _adapter_open_ca( p_adapter ); + if( ib_status != IB_SUCCESS ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("IOC[%d]Open CA failed %s\n", p_adapter->ioc_num, + p_adapter->ifc.get_err_str( ib_status )) ); + goto err; + } + + ib_status = _adapter_netpath_update( p_adapter, p_viport, p_path ); + if( ib_status != IB_SUCCESS ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("IOC[%d]Update New Path failed %s\n", p_adapter->ioc_num, + p_adapter->ifc.get_err_str( ib_status )) ); + goto err; + } + + ib_status = viport_control_connect( p_viport ); + if( ib_status != IB_SUCCESS ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("IOC[%d]Control QP connect return %s\n", p_adapter->ioc_num, + p_adapter->ifc.get_err_str( ib_status )) ); + goto err; + } + + /* should call this only once */ + if( p_adapter->state == INIC_UNINITIALIZED ) + { + if( _adapter_set_sg_size( p_adapter->h_handle, + p_adapter->params.MinMtu ) != NDIS_STATUS_SUCCESS ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("IOC[%d]ScatterGather Init using MTU size %d failed\n", p_adapter->ioc_num, + p_adapter->params.MinMtu ) ); + goto err; + } + } + + ib_status = viport_data_connect( p_viport ); + if( ib_status != IB_SUCCESS ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("IOC[%d]Data QP connect return %s\n", p_adapter->ioc_num, + p_adapter->ifc.get_err_str( ib_status )) ); + goto err; + } + + VNIC_TRACE( VNIC_DBG_INFO, + ("IOC[%d] instance %d %s is CONNECTED\n", + p_viport->ioc_num, + p_viport->p_netpath->instance, + netpath_to_string( p_viport->p_netpath ) )); + + if( p_viport->state == VIPORT_CONNECTED ) + { + p_adapter->num_paths++; + } + + if( p_adapter->num_paths > 1 && + p_viport->p_netpath != p_adapter->p_currentPath ) + { + if ( !netpath_setUnicast( p_viport->p_netpath, + p_adapter->p_currentPath->pViport->hwMacAddress ) ) + { + ib_status = IB_ERROR; + goto err; + } + } + + return ib_status; + +err: + VNIC_TRACE( VNIC_DBG_ERROR, + ("IOC[%d] allocate return %#x (%s)\n", p_adapter->ioc_num, + ib_status, p_adapter->ifc.get_err_str( ib_status )) ); + + if( p_viport != NULL && + p_viport->p_netpath != NULL ) + { + netpath_free( p_viport->p_netpath ); + } + return ib_status; +} + +#if ( LBFO_ENABLED ) + +static void +__adapter_add_to_failover_list( + IN vnic_adapter_t* const p_adapter, + IN lbfo_state_t state ) +{ + + CL_ASSERT( p_adapter ); + CL_ASSERT( state == _ADAPTER_PRIMARY || state == _ADAPTER_SECONDARY ); + + p_adapter->failover.fo_state = state; + + if( state == _ADAPTER_PRIMARY ) + { + p_adapter->failover.primary_handle = p_adapter; + cl_qlist_insert_tail( &g_vnic.primary_list, &p_adapter->list_item ); + } + else + { + cl_qlist_insert_tail( &g_vnic.secondary_list, &p_adapter->list_item ); + } +} + +static void +__adapter_remove_from_failover_list( + IN vnic_adapter_t* const p_adapter ) +{ + lbfo_state_t lbfo_state; + vnic_adapter_t *p_adapter_to_promote; + uint32_t bundle_id; + + CL_ASSERT( p_adapter ); + + lbfo_state = p_adapter->failover.fo_state; + p_adapter->failover.fo_state = _ADAPTER_NOT_BUNDLED; + bundle_id = p_adapter->failover.bundle_id; + + if( lbfo_state == _ADAPTER_PRIMARY ) + { + cl_qlist_remove_item( &g_vnic.primary_list, &p_adapter->list_item ); + + /* search for secondary adapter with same id && (id != 0 ) */ + if( bundle_id != 0 ) + { + p_adapter_to_promote = + __adapter_find_on_failover_list( _ADAPTER_SECONDARY, bundle_id ); + + if( p_adapter_to_promote && + p_adapter_to_promote->pnp_state != IB_PNP_IOC_REMOVE && + p_adapter_to_promote->state == INIC_REGISTERED && + p_adapter_to_promote->reset == FALSE ) + { + /* a small recursion */ + __adapter_set_failover_primary( p_adapter_to_promote, TRUE ); + } + } + } + else if( lbfo_state == _ADAPTER_SECONDARY ) + { + cl_qlist_remove_item( &g_vnic.secondary_list, &p_adapter->list_item ); + VNIC_TRACE( VNIC_DBG_INFO, + ("IOC[%d] LBFO bundle %d Secondary Adapter Removed\n", + p_adapter->ioc_num, p_adapter->failover.bundle_id )); + } + else if( lbfo_state == _ADAPTER_NOT_BUNDLED ) + { + VNIC_TRACE( VNIC_DBG_INFO, + ("IOC[%d] Adapter not bundled\n", p_adapter->ioc_num )); + } + + return; +} + + +static vnic_adapter_t* +__adapter_find_on_failover_list( + IN lbfo_state_t list_flag, + IN uint32_t bundle_id ) +{ + vnic_adapter_t *p_adapter = NULL; + cl_list_item_t *p_item; + cl_qlist_t *p_qlist = ( list_flag == _ADAPTER_PRIMARY ) ? + &g_vnic.primary_list : &g_vnic.secondary_list; + + p_item = cl_qlist_head( p_qlist ); + + while( p_item != cl_qlist_end( p_qlist ) ) + { + p_adapter = PARENT_STRUCT( p_item, vnic_adapter_t, list_item ); + + if( p_adapter && + p_adapter->failover.bundle_id == bundle_id ) + { + return p_adapter; + } + + p_item = cl_qlist_next( p_item ); + } + return NULL; +} + +static NDIS_STATUS +__adapter_set_failover_primary( + IN vnic_adapter_t* const p_adapter, + IN BOOLEAN promote_secondary ) +{ + NDIS_STATUS status = NDIS_STATUS_SUCCESS; + + CL_ASSERT( p_adapter ); + + if( promote_secondary ) + { + if( p_adapter->failover.fo_state != _ADAPTER_SECONDARY ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("LBFO Can't promote NON_SECONDARY\n")); + return NDIS_STATUS_NOT_ACCEPTED; + } + __adapter_remove_from_failover_list( p_adapter ); + status = NdisMPromoteMiniport( p_adapter->h_handle ); + } + + if( status == NDIS_STATUS_SUCCESS ) + { + p_adapter->failover.p_adapter = p_adapter; + p_adapter->failover.fo_state = _ADAPTER_PRIMARY; + p_adapter->failover.primary_handle = p_adapter->h_handle; + __adapter_add_to_failover_list( p_adapter, _ADAPTER_PRIMARY ); + + VNIC_TRACE( VNIC_DBG_INFO, + ("IOC[%d] Set LBFO bundle %d Primary Adapter\n", + p_adapter->ioc_num, p_adapter->failover.bundle_id )); + } + else + VNIC_TRACE( VNIC_DBG_ERROR, + ("LBFO Set to Primary Failed\n")); + + return status; +} + +static NDIS_STATUS +__adapter_set_failover_secondary( + IN vnic_adapter_t* const p_adapter, + IN NDIS_HANDLE primary_handle ) +{ + NDIS_STATUS status; + + CL_ASSERT( p_adapter ); + + status = NdisMSetMiniportSecondary( p_adapter->h_handle, primary_handle ); + + if ( status == NDIS_STATUS_SUCCESS ) + { + p_adapter->failover.fo_state = _ADAPTER_SECONDARY; + p_adapter->failover.primary_handle = primary_handle; + __adapter_add_to_failover_list( p_adapter, _ADAPTER_SECONDARY ); + + VNIC_TRACE( VNIC_DBG_INFO, + ("IOC[%d] Set LBFO bundle %d Secondary Adapter\n", + p_adapter->ioc_num, p_adapter->failover.bundle_id )); + } + + return status; +} + +#endif //LBFO_ENABLED diff --git a/trunk/ulp/qlgcvnic/kernel/vnic_adapter.h b/trunk/ulp/qlgcvnic/kernel/vnic_adapter.h new file mode 100644 index 00000000..cd143b52 --- /dev/null +++ b/trunk/ulp/qlgcvnic/kernel/vnic_adapter.h @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2007 QLogic Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id$ + */ + +#if !defined _VNIC_ADAPTER_H_ +#define _VNIC_ADAPTER_H_ + +#include +#include +#include +#include +#include "vnic_ib.h" +#include "vnic_controlpkt.h" +#include "vnic_config.h" +#include "vnic_control.h" +#include "vnic_data.h" +#include "vnic_viport.h" +#include + +typedef struct _pending_oid +{ + NDIS_OID oid; + PVOID p_buf; + ULONG buf_len; + PULONG p_bytes_used; + PULONG p_bytes_needed; + +} pending_oid_t; + +typedef struct _ipv4_address_item +{ + union _net_address_item_address + { + ULONG as_ulong; + UCHAR as_bytes[4]; + } address; + +} ipv4_address_item_t; + +typedef struct _lbfo_failover { + struct _vnic_adapter *p_adapter; + NDIS_HANDLE primary_handle; + uint32_t bundle_id; + lbfo_state_t fo_state; +} lbfo_failover_t; + +typedef struct _vnic_params { + uint32_t MaxAddressEntries; + uint32_t MinAddressEntries; + uint32_t MinMtu; + uint32_t MaxMtu; + uint32_t HostRecvPoolEntries; + uint32_t MinHostPoolSz; + uint32_t MinEiocPoolSz; + uint32_t MaxEiocPoolSz; + uint32_t MinHostKickTimeout; + uint32_t MaxHostKickTimeout; + uint32_t MinHostKickEntries; + uint32_t MaxHostKickEntries; + uint32_t MinHostKickBytes; + uint32_t MaxHostKickBytes; + uint32_t MinHostUpdateSz; + uint32_t MaxHostUpdateSz; + uint32_t MinEiocUpdateSz; + uint32_t MaxEiocUpdateSz; + uint32_t NotifyBundleSz; + uint32_t ViportStatsInterval; + uint32_t ViportHbInterval; + uint32_t ViportHbTimeout; + uint32_t ControlRspTimeout; + uint32_t ControlReqRetryCount; + uint32_t RetryCount; + uint32_t MinRnrTimer; + uint32_t MaxViportsPerNetpath; + uint32_t DefaultViportsPerNetpath; + uint32_t DefaultPkey; + uint32_t DefaultNoPathTimeout; + uint32_t DefaultPrimaryConnectTimeout; + uint32_t DefaultPrimaryReconnectTimeout; + uint32_t DefaultPrimarySwitchTimeout; + uint32_t DefaultPreferPrimary; + uint32_t UseRxCsum; + uint32_t UseTxCsum; + uint32_t VlanInfo; + uint32_t SecondaryPath; + uint32_t bundle_id; + mac_addr_t conf_mac; +} vnic_params_t; + + +typedef struct _vnic_adapter { + cl_list_item_t list_item; + NDIS_HANDLE h_handle; + DEVICE_OBJECT *p_pdo; + NDIS_SPIN_LOCK lock; + ib_al_ifc_t ifc; + ioc_ifc_data_t ifc_data; + ib_ioc_info_t ioc_info; + LIST_ENTRY send_pending_list; + LIST_ENTRY cancel_send_list; + NDIS_SPIN_LOCK pending_list_lock; + NDIS_SPIN_LOCK cancel_list_lock; + NDIS_SPIN_LOCK path_records_lock; + cl_qlist_t path_records_list; + ib_al_handle_t h_al; + ib_ca_handle_t h_ca; + ib_pnp_handle_t h_pnp; + ib_pnp_event_t pnp_state; + IbCa_t ca; + InicState_t state; + struct Netpath primaryPath; + struct Netpath secondaryPath; + struct Netpath *p_currentPath; + vnic_params_t params; + uint32_t num_paths; + int macSet; + int mc_count; + mac_addr_t mcast_array[MAX_MCAST]; + LONG xmitStarted; + LONG carrier; + uint32_t ioc_num; + uint32_t link_speed; + uint32_t packet_filter; + uint32_t vlan_info; + uint32_t hung; + BOOLEAN reset; + BOOLEAN pending_set; + BOOLEAN pending_query; + pending_oid_t query_oid; + pending_oid_t set_oid; + ib_svc_entry_t svc_entries[2]; + +#if ( LBFO_ENABLED ) + lbfo_failover_t failover; +#endif +#ifdef VNIC_STATISTIC + struct { + uint64_t startTime; + uint64_t connTime; + uint64_t disconnRef; /* Intermediate time */ + uint64_t disconnTime; + uint32_t disconnNum; + uint64_t xmitTime; + uint32_t xmitNum; + uint32_t xmitFail; + uint64_t recvTime; + uint32_t recvNum; + uint64_t xmitRef; /* Intermediate time */ + uint64_t xmitOffTime; + uint32_t xmitOffNum; + uint64_t carrierRef; /* Intermediate time */ + uint64_t carrierOffTime; + uint32_t carrierOffNum; + } statistics; +#endif /* VNIC_STATISTIC */ + +} vnic_adapter_t; + +ib_api_status_t +vnic_create_adapter( + IN NDIS_HANDLE h_handle, + IN NDIS_HANDLE wrapper_config_context, + OUT vnic_adapter_t** const pp_adapter); + +void +vnic_destroy_adapter( + IN vnic_adapter_t* p_adapter); + +ib_api_status_t +vnic_construct_adapter( + IN vnic_adapter_t *p_adapter); + +NDIS_STATUS +adapter_set_mcast( + IN vnic_adapter_t* const p_adapter, + IN mac_addr_t* const p_mac_array, + IN const uint8_t mc_count ); + +ib_api_status_t +adapter_viport_allocate( + IN vnic_adapter_t* const p_adapter, + IN OUT viport_t** const pp_viport ); + +void +vnic_resume_set_oids( + IN vnic_adapter_t* const p_adapter ); + +void +vnic_resume_oids( + IN vnic_adapter_t* const p_adapter ); + +ib_api_status_t +__vnic_pnp_cb( + IN ib_pnp_rec_t *p_pnp_rec ); + +ib_api_status_t +ibregion_physInit( + IN struct _vnic_adapter* p_adapter, + OUT IbRegion_t *pRegion, + IN ib_pd_handle_t hPd, + IN uint64_t *p_vaddr, + IN uint64_t len ); + +void +__vnic_pnp_dereg_cb( + IN void* context ); + +ib_api_status_t +adapter_reset( + IN vnic_adapter_t* const p_adapter ); +void +__pending_queue_cleanup( + IN vnic_adapter_t *p_adapter ); + +#endif /* !defined _VNIC_ADAPTER_H_ */ diff --git a/trunk/ulp/qlgcvnic/kernel/vnic_config.h b/trunk/ulp/qlgcvnic/kernel/vnic_config.h new file mode 100644 index 00000000..9568b08f --- /dev/null +++ b/trunk/ulp/qlgcvnic/kernel/vnic_config.h @@ -0,0 +1,301 @@ +/* + * Copyright (c) 2007 QLogic Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id$ + */ +#ifndef _VNIC_CONFIG_H_ +#define _VNIC_CONFIG_H_ + +#include "vnic_util.h" +/* These are hard, compile time limits. + * Lower runtime overrides may be in effect + */ +#define INIC_CLASS_SUBCLASS 0x2000066A +#define INIC_PROTOCOL 0 +#define INIC_PROT_VERSION 1 + +#define INIC_MAJORVERSION 1 +#define INIC_MINORVERSION 1 + +#define LIMIT_OUTSTANDING_SENDS 0 + +#define MAX_ADDRESS_ENTRIES 64 /* max entries to negotiate with remote */ +#define MIN_ADDRESS_ENTRIES 16 /* min entries remote can return to us that we agree with */ +#define MAX_ADDR_ARRAY 32 /* address array we can handle. for now */ +#define MIN_MTU 1500 /* Minimum Negotiated payload size */ +#define MAX_MTU 9500 /* max Jumbo frame payload size */ +#define ETH_VLAN_HLEN 18 /* ethernet header with VLAN tag */ + +#define HOST_RECV_POOL_ENTRIES 512 /* TBD: Abritrary */ +#define MIN_HOST_POOL_SZ 256 /* TBD: Abritrary */ +#define MIN_EIOC_POOL_SZ 256 /* TBD: Abritrary */ +#define MAX_EIOC_POOL_SZ 512 /* TBD: Abritrary */ + +#define MIN_HOST_KICK_TIMEOUT 100 /* TBD: Arbitrary */ +#define MAX_HOST_KICK_TIMEOUT 200 /* In uSec */ + +#define MIN_HOST_KICK_ENTRIES 1 /* TBD: Arbitrary */ +#define MAX_HOST_KICK_ENTRIES 128 /* TBD: Arbitrary */ + +#define MIN_HOST_KICK_BYTES 0 +#define MAX_HOST_KICK_BYTES 5000 + +#define MIN_HOST_UPDATE_SZ 8 /* TBD: Arbitrary */ +#define MAX_HOST_UPDATE_SZ 32 /* TBD: Arbitrary */ +#define MIN_EIOC_UPDATE_SZ 8 /* TBD: Arbitrary */ +#define MAX_EIOC_UPDATE_SZ 32 /* TBD: Arbitrary */ + +#define NOTIFY_BUNDLE_SZ 32 + +#define MAX_PARAM_VALUE 0x40000000 + +#define DEFAULT_VIPORTS_PER_NETPATH 1 +#define MAX_VIPORTS_PER_NETPATH 1 + +#define INIC_USE_RX_CSUM TRUE +#define INIC_USE_TX_CSUM TRUE +#define DEFAULT_NO_PATH_TIMEOUT 10000 /* TBD: Arbitrary */ +#define DEFAULT_PRI_CON_TIMEOUT 10000 /* TBD: Arbitrary */ +#define DEFAULT_PRI_RECON_TIMEOUT 10000 /* TBD: Arbitrary */ +#define DEFAULT_PRI_SWITCH_TIMEOUT 10000 /* TBD: Arbitrary */ +#define DEFAULT_PREFER_PRIMARY TRUE + +/* timeouts: !! all data defined in milliseconds, + some later will be converted to microseconds */ +#define VIPORT_STATS_INTERVAL 5000 /* 5 sec */ +#define VIPORT_HEARTBEAT_INTERVAL 2000 /* 2 seconds */ +#define VIPORT_HEARTBEAT_TIMEOUT 60000 /* 60 sec */ +#define CONTROL_RSP_TIMEOUT 2000 /* 2 sec */ + +#define _100NS_IN_1MS (10000) +inline uint64_t +get_time_stamp_ms( void ) +{ + return( (KeQueryInterruptTime() / _100NS_IN_1MS ) ); +} + +/* InfiniBand Connection Parameters */ +#define CONTROL_REQ_RETRY_COUNT 4 +#define RETRY_COUNT 3 +#define MIN_RNR_TIMER 22 /* 20 ms */ +#define DEFAULT_PKEY 0 /* Pkey table index */ + +/* phys memory size to register with HCA*/ +#define MEM_REG_SIZE 0xFFFFFFFFFFFFFFFF + +/* link speed in 100 bits/sec units */ +#define LINK_SPEED_1MBIT_x100BPS 10000 +#define LINK_SPEED_1GBIT_x100BPS 10000000 +#define LINK_SPEED_10GBIT_x100BPS 100000000 + /* if VEx does not report it's link speed, so set it 1Gb/s so far */ +#define DEFAULT_LINK_SPEED_x100BPS LINK_SPEED_1GBIT_x100BPS + +#define DEFAULT_PARAM(x,y) if(x == MAXU32) { \ + x = y; } +#define POWER_OF_2(x) if (!IsPowerOf2(x)) { \ + VNIC_TRACE( VNIC_DBG_WARN, (" %s (%d) must be a power of 2\n",#x,x) ); \ + x = SetMinPowerOf2(x); \ + } +#define LESS_THAN(lo, hi) if (lo >= hi) { \ + VNIC_TRACE( VNIC_DBG_ERROR, (" %s (%d) must be less than %s (%d)\n",#lo,lo,#hi,hi) ); \ + lo = hi >> 1; \ + } +#define LESS_THAN_OR_EQUAL(lo, hi) if (lo > hi) { \ + VNIC_TRACE( VNIC_DBG_WARN, (" %s (%d) cannot be greater than %s (%d)\n",#lo,lo,#hi,hi) ); \ + lo = hi; \ + } +#define RANGE_CHECK(x, min, max) if ((x < min) || (x > max)) { \ + VNIC_TRACE( VNIC_DBG_WARN, (" %s (%d) must be between %d and %d\n",#x,x,min,max) ); \ + if (x < min) \ + x = min; \ + else \ + x = max; \ + } +#define ZERO_RANGE_CHECK(x, min, max) if (x > max) { \ + VNIC_TRACE( VNIC_DBG_WARN, (" %s (%d) must be between %d and %d\n",#x,x,min,max) ); \ + x = max; \ + } + +#define BOOLEAN_RANGE(x) ZERO_RANGE_CHECK(x, 0, 1) +#define U32_ZERO_RANGE(x) ZERO_RANGE_CHECK(x, 0, 0x7FFFFFFF) +#define U32_RANGE(x) RANGE_CHECK(x, 1, 0x7FFFFFFF) +#define U16_ZERO_RANGE(x) ZERO_RANGE_CHECK(x, 0, 0xFFFF) +#define U16_RANGE(x) RANGE_CHECK(x, 1, 0xFFFF) +#define U8_ZERO_RANGE(x) ZERO_RANGE_CHECK(x, 0, 0xFF) +#define U8_RANGE(x) RANGE_CHECK(x, 1, 0xFF) + +enum { + INDEX_RESERVED, + INDEX_MIN_HOST_POOL_SZ, + INDEX_HOST_RECV_POOL_ENTRIES, + INDEX_MIN_EIOC_POOL_SZ, + INDEX_MAX_EIOC_POOL_SZ, + INDEX_MIN_HOST_KICK_TIMEOUT, + INDEX_MAX_HOST_KICK_TIMEOUT, + INDEX_MIN_HOST_KICK_ENTRIES, + INDEX_MAX_HOST_KICK_ENTRIES, + INDEX_MIN_HOST_KICK_BYTES, + INDEX_MAX_HOST_KICK_BYTES, + INDEX_MIN_HOST_UPDATE_SZ, + INDEX_MAX_HOST_UPDATE_SZ, + INDEX_MIN_EIOC_UPDATE_SZ, + INDEX_MAX_EIOC_UPDATE_SZ, + INDEX_HEARTBEAT_TIMEOUT, + INDEX_LAST // keep it the last entry +}; + +typedef struct _g_registry_params { + PWSTR name; + uint32_t value; +}g_registry_params_t; + +#define ENTRY_INIT_VALUE MAXULONG +#define VNIC_REGISTRY_TBL_SIZE INDEX_LAST + +typedef struct { + uint64_t ioc_guid; + uint64_t portGuid; + uint64_t port; + uint64_t hca; + uint64_t instance; + char ioc_string[65]; + char ioc_guid_set; + char ioc_string_set; +} PathParam_t; + +typedef struct _vnic_globals { + NDIS_HANDLE ndis_handle; // ndis wrapper handle + NDIS_SPIN_LOCK lock; +#if ( LBFO_ENABLED ) + cl_qlist_t primary_list; + cl_qlist_t secondary_list; +#endif + uint32_t shutdown; + uint8_t host_name[IB_NODE_DESCRIPTION_SIZE]; + g_registry_params_t *p_params; +} vnic_globals_t; + +typedef struct IbConfig { + ib_path_rec_t pathInfo; + uint64_t sid; + Inic_ConnectionData_t connData; + uint32_t retryCount; + uint32_t rnrRetryCount; + uint8_t minRnrTimer; + uint32_t numSends; + uint32_t numRecvs; + uint32_t recvScatter; /* 1 */ + uint32_t sendGather; /* 1 or 2 */ + uint32_t overrides; +} IbConfig_t; + +typedef struct ControlConfig { + IbConfig_t ibConfig; + uint32_t numRecvs; + uint8_t inicInstance; + uint16_t maxAddressEntries; + uint16_t minAddressEntries; + uint32_t rspTimeout; + uint8_t reqRetryCount; + uint32_t overrides; +} ControlConfig_t; + +typedef struct DataConfig { + IbConfig_t ibConfig; + uint64_t pathId; + uint32_t numRecvs; + uint32_t hostRecvPoolEntries; + Inic_RecvPoolConfig_t hostMin; + Inic_RecvPoolConfig_t hostMax; + Inic_RecvPoolConfig_t eiocMin; + Inic_RecvPoolConfig_t eiocMax; + uint32_t notifyBundle; + uint32_t overrides; +} DataConfig_t; + +typedef struct ViportConfig { + struct _viport *pViport; + ControlConfig_t controlConfig; + DataConfig_t dataConfig; + uint32_t hca; + uint32_t port; + uint32_t statsInterval; + uint32_t hbInterval; /* heartbeat interval */ + uint32_t hbTimeout; /* heartbeat timeout */ + uint64_t portGuid; + uint64_t guid; + size_t instance; + char ioc_string[65]; + +#define HB_INTERVAL_OVERRIDE 0x1 +#define GUID_OVERRIDE 0x2 +#define STRING_OVERRIDE 0x4 +#define HCA_OVERRIDE 0x8 +#define PORT_OVERRIDE 0x10 +#define PORTGUID_OVERRIDE 0x20 + uint32_t overrides; +} ViportConfig_t; + +/* + * primaryConnectTimeout - If the secondary connects first, how long do we + * give the primary? + * primaryReconnectTimeout - Same as above, but used when recovering when + * both paths fail + * primarySwitchTimeout - How long do we wait before switching to the + * primary when it comes back? + */ +#define IFNAMSIZ 65 +typedef struct InicConfig { + //struct Inic *pInic; + char name[IFNAMSIZ]; + uint32_t noPathTimeout; + uint32_t primaryConnectTimeout; + uint32_t primaryReconnectTimeout; + uint32_t primarySwitchTimeout; + int preferPrimary; + BOOLEAN useRxCsum; + BOOLEAN useTxCsum; +#define USE_RX_CSUM_OVERRIDE 0x1 +#define USE_TX_CSUM_OVERRIDE 0x2 + uint32_t overrides; +} InicConfig_t; + +typedef enum { + INIC_UNINITIALIZED, + INIC_DEREGISTERING, + INIC_REGISTERED, +} InicState_t; + +typedef enum { + _ADAPTER_NOT_BUNDLED = 0, + _ADAPTER_PRIMARY, + _ADAPTER_SECONDARY +} lbfo_state_t; + +#endif /* _VNIC_CONFIG_H_ */ + diff --git a/trunk/ulp/qlgcvnic/kernel/vnic_control.c b/trunk/ulp/qlgcvnic/kernel/vnic_control.c new file mode 100644 index 00000000..c8967a86 --- /dev/null +++ b/trunk/ulp/qlgcvnic/kernel/vnic_control.c @@ -0,0 +1,2090 @@ +/* + * Copyright (c) 2007 QLogic Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id$ + */ + +#include "vnic_adapter.h" + +static void +control_recv( Control_t *pControl, RecvIo_t *pRecvIo ); + +static void +control_recvComplete( + IN Io_t *pIo ); + +static ib_api_status_t +control_send( Control_t *pControl ); + +static void +control_sendComplete( Io_t *pIo ); +static void +control_timeout( void * context ); + +static void +control_timer( Control_t *pControl, int timeout ); + +static void +control_timerStop( Control_t *pControl ); + +static void +control_initHdr( Control_t *pControl, uint8_t cmd ); + +static RecvIo_t * +control_getRsp( Control_t *pControl ); + +static void +copyRecvPoolConfig( Inic_RecvPoolConfig_t *pSrc, + Inic_RecvPoolConfig_t *pDst ); + +static BOOLEAN +checkRecvPoolConfigValue( + IN void *pSrc, + IN void *pDst, + IN void *pMax, + IN void *pMin, + IN char *name ); + +static BOOLEAN checkRecvPoolConfig( + Inic_RecvPoolConfig_t *pSrc, + Inic_RecvPoolConfig_t *pDst, + Inic_RecvPoolConfig_t *pMax, + Inic_RecvPoolConfig_t *pMin); + +static void +__control_logControlPacket( + Inic_ControlPacket_t *pPkt ); + +void +control_construct( + IN Control_t *pControl, + IN viport_t *pViport ) +{ + VNIC_ENTER( VNIC_DBG_CTRL ); + + cl_memclr(pControl, sizeof(Control_t)); + + pControl->p_viport = pViport; + + pControl->reqOutstanding = FALSE; + pControl->seqNum = 0; + + pControl->pResponse = NULL; + pControl->pInfo = NULL; + + pControl->p_viport->addrs_query_done = TRUE; + + InitializeListHead(&pControl->failureList); + KeInitializeSpinLock(&pControl->ioLock); + + cl_timer_construct( &pControl->timer ); + + ibqp_construct( &pControl->qp, pViport ); + + VNIC_EXIT( VNIC_DBG_CTRL ); +} + + +ib_api_status_t +control_init( + IN Control_t *pControl, + IN viport_t *pViport, + IN ControlConfig_t *pConfig, + IN uint64_t guid ) +{ + ib_api_status_t ib_status; + ib_pd_handle_t hPd; + Inic_ControlPacket_t *pkt; + Io_t *pIo; + int sz; + unsigned int i; + + VNIC_ENTER( VNIC_DBG_CTRL ); + + pControl->p_conf = pConfig; + + hPd = pViport->p_adapter->ca.hPd; + + cl_timer_init( &pControl->timer, control_timeout, pControl ); + + ib_status = ibqp_init( + &pControl->qp, guid, &pConfig->ibConfig ); + if( ib_status != IB_SUCCESS ) + { + VNIC_TRACE_EXIT( VNIC_DBG_ERROR, ("ibqp_init returned %s\n", + pViport->p_adapter->ifc.get_err_str( ib_status )) ); + goto failure; + } + + sz = (sizeof(RecvIo_t) * pConfig->numRecvs ) + + (sizeof(Inic_ControlPacket_t) * (pConfig->numRecvs + 1)); + + pControl->pLocalStorage = cl_zalloc( sz ); + + if ( pControl->pLocalStorage == NULL ) + { + VNIC_TRACE_EXIT( VNIC_DBG_ERROR, + ("Failed allocating space for local storage\n" )); + + ibqp_cleanup(&pControl->qp); + ib_status = IB_INSUFFICIENT_MEMORY; + goto failure; + } + + pControl->pRecvIos = (RecvIo_t *)pControl->pLocalStorage; + + pkt = (Inic_ControlPacket_t *)(pControl->pLocalStorage + + sizeof(SendIo_t) * pConfig->numRecvs); + + sz = sizeof(Inic_ControlPacket_t) * (pConfig->numRecvs + 1); + + ib_status = ibregion_init( pViport, &pControl->region, hPd, + pkt, sz, IB_AC_LOCAL_WRITE ); + if ( ib_status != IB_SUCCESS ) + { + /* NOTE: I'm allowing recvs into the send buffer as well + * as the receive buffers. I'm doing this to combine them + * into a single region, and conserve a region. + */ + VNIC_TRACE_EXIT( VNIC_DBG_ERROR , + (" Failed setting up control space region\n" )); + + ibqp_cleanup( &pControl->qp ); + cl_free( pControl->pLocalStorage ); + pControl->pLocalStorage = NULL; + goto failure; + } + pIo = &pControl->sendIo.io; + pIo->pViport = pViport; + pIo->pRoutine = control_sendComplete; + + pIo->wrq.p_next = NULL; + pIo->wrq.wr_type = WR_SEND; + pIo->wrq.send_opt = IB_SEND_OPT_SIGNALED; + pIo->wrq.wr_id = (uint64_t)(pIo); + pIo->wrq.num_ds = 1; + pIo->wrq.ds_array = &pControl->sendIo.dsList; + pIo->wrq.ds_array[0].length = sizeof(Inic_ControlPacket_t); + pIo->wrq.ds_array[0].lkey = pControl->region.lkey; + pIo->wrq.ds_array[0].vaddr = (uint64_t)(pkt++); + + for (i = 0; i < pConfig->numRecvs; i++ ) + { + pIo = &pControl->pRecvIos[i].io; + pIo->pViport = pViport; + pIo->pRoutine = control_recvComplete; + + pIo->r_wrq.wr_id = (uint64_t)(pIo); + pIo->r_wrq.p_next = NULL; + pIo->r_wrq.num_ds = 1; + pIo->r_wrq.ds_array = &pControl->pRecvIos[i].dsList; + pIo->r_wrq.ds_array[0].length = sizeof(Inic_ControlPacket_t); + pIo->r_wrq.ds_array[0].vaddr = (uint64_t)(pkt++); + pIo->r_wrq.ds_array[0].lkey = pControl->region.lkey; + + if ( ibqp_postRecv( &pControl->qp, pIo ) != IB_SUCCESS ) + { + control_cleanup( pControl ); + ib_status = IB_ERROR; + break; + } + } + +failure: + VNIC_EXIT( VNIC_DBG_CTRL ); + return ib_status; +} + + +void +control_cleanup( + IN Control_t *pControl ) +{ + VNIC_ENTER( VNIC_DBG_CTRL ); + + control_timerStop( pControl ); + ibqp_detach( &pControl->qp ); + ibregion_cleanup( pControl->p_viport, &pControl->region ); + + if ( pControl->pLocalStorage ) + { + cl_free( pControl->pLocalStorage ); + pControl->pLocalStorage = NULL; + } + + cl_timer_destroy( &pControl->timer ); + + VNIC_EXIT( VNIC_DBG_CTRL ); + return; +} + +void +control_processAsync( + IN Control_t *pControl ) +{ + RecvIo_t *pRecvIo; + Inic_ControlPacket_t *pPkt; + LIST_ENTRY *p_list_entry; + + VNIC_ENTER( VNIC_DBG_CTRL ); + + pRecvIo = InterlockedExchangePointer( &pControl->pInfo, NULL ); + + if ( pRecvIo != NULL ) + { + VNIC_TRACE( VNIC_DBG_CTRL, + ("IOC %d: processing info packet\n", + pControl->p_viport->ioc_num ) ); + + pPkt = control_packet( pRecvIo ); + + if ( pPkt->hdr.pktCmd == CMD_REPORT_STATUS ) + { + switch( ntoh32(pPkt->cmd.reportStatus.statusNumber) ) + { + case INIC_STATUS_LINK_UP: + VNIC_TRACE( VNIC_DBG_CTRL, + ("IOC %d: STATUS LINK UP\n", pControl->p_viport->ioc_num ) ); + /* renew link speed info since it can change */ + pControl->p_viport->p_adapter->link_speed = + ntoh32( pPkt->cmd.reportStatus.statusInfo ); + viport_linkUp( pControl->p_viport ); + break; + + case INIC_STATUS_LINK_DOWN: + VNIC_TRACE( VNIC_DBG_CTRL, + ("IOC %d: STATUS LINK DOWN\n", pControl->p_viport->ioc_num ) ); + + viport_linkDown( pControl->p_viport ); + break; + case INIC_STATUS_EIOC_ERROR: + case INIC_STATUS_EIOC_SHUTDOWN: + viport_failure( pControl->p_viport ); + VNIC_TRACE( VNIC_DBG_ERROR, + ("IOC %d: STATUS EIOC ERROR\n", + pControl->p_viport->ioc_num ) ); + break; + default: + VNIC_TRACE( VNIC_DBG_CTRL | VNIC_DBG_ERROR, + ("IOC %d: Asynchronous status %#x received\n", + pControl->p_viport->ioc_num, + ntoh32(pPkt->cmd.reportStatus.statusNumber)) ); + __control_logControlPacket( pPkt ); + break; + } + } + + if ( pPkt->hdr.pktCmd != CMD_REPORT_STATUS || + pPkt->cmd.reportStatus.isFatal ) + { + viport_failure( pControl->p_viport ); + } + + control_recv( pControl, pRecvIo ); + } + + while ( !IsListEmpty( &pControl->failureList ) ) + { + + VNIC_TRACE( VNIC_DBG_CTRL, + ("IOC %d: processing error packet\n", + pControl->p_viport->ioc_num ) ); + + p_list_entry = ExInterlockedRemoveHeadList( &pControl->failureList, &pControl->ioLock ); + pRecvIo = (RecvIo_t *)p_list_entry; + pPkt = control_packet( pRecvIo ); + + VNIC_TRACE( VNIC_DBG_CTRL, + ("IOC %d: Asynchronous error received from EIOC\n", + pControl->p_viport->ioc_num ) ); + + __control_logControlPacket( pPkt ); + + if ( ( pPkt->hdr.pktType != TYPE_ERR ) || + ( pPkt->hdr.pktCmd != CMD_REPORT_STATUS ) || + ( pPkt->cmd.reportStatus.isFatal ) ) + { + viport_failure( pControl->p_viport ); + break; + } + + control_recv( pControl, pRecvIo ); + } + + VNIC_EXIT( VNIC_DBG_CTRL ); +} + + +ib_api_status_t +control_initInicReq( + IN Control_t *pControl ) +{ + ControlConfig_t *p_conf = pControl->p_conf; + Inic_ControlPacket_t *pPkt; + Inic_CmdInitInicReq_t *pInitInicReq; + ib_api_status_t ib_status; + + VNIC_ENTER( VNIC_DBG_CTRL ); + + if( pControl->p_viport->errored ) + { + return IB_ERROR; + } + control_initHdr( pControl, CMD_INIT_INIC ); + + pPkt = control_packet( &pControl->sendIo ); + pInitInicReq = &pPkt->cmd.initInicReq; + pInitInicReq->inicMajorVersion = hton16( INIC_MAJORVERSION ); + pInitInicReq->inicMinorVersion = hton16( INIC_MINORVERSION ); + pInitInicReq->inicInstance = p_conf->inicInstance; + pInitInicReq->numDataPaths = 1; + pInitInicReq->numAddressEntries = hton16( p_conf->maxAddressEntries ); + + ib_status = control_send( pControl ); + VNIC_EXIT( VNIC_DBG_CTRL ); + return ib_status; +} + + +BOOLEAN +control_initInicRsp( + IN Control_t *pControl, + IN uint32_t *pFeatures, + IN uint8_t *pMacAddress, + IN uint16_t *pNumAddrs, + IN uint16_t *pVlan ) +{ + RecvIo_t *pRecvIo; + ControlConfig_t *p_conf = pControl->p_conf; + Inic_ControlPacket_t *pPkt; + Inic_CmdInitInicRsp_t *pInitInicRsp; + uint8_t numDataPaths, + numLanSwitches; + + VNIC_ENTER( VNIC_DBG_CTRL ); + + pRecvIo = control_getRsp( pControl ); + if (!pRecvIo) + return FALSE; + + pPkt = control_packet( pRecvIo ); + + if ( pPkt->hdr.pktCmd != CMD_INIT_INIC ) + { + + VNIC_TRACE( VNIC_DBG_CTRL | VNIC_DBG_ERROR, + ("IOC %d: Sent control request:\n", + pControl->p_viport->ioc_num ) ); + + __control_logControlPacket( control_lastReq( pControl ) ); + + VNIC_TRACE_EXIT( VNIC_DBG_CTRL | VNIC_DBG_ERROR, + ("IOC %d: Received control response:\n", + pControl->p_viport->ioc_num ) ); + + __control_logControlPacket( pPkt ); + goto failure; + } +#ifdef _DEBUG_ + VNIC_TRACE( VNIC_DBG_CTRL_PKT, + ("IOC %d: instance %d Sent initINIC request:\n", + pControl->p_viport->ioc_num, + pControl->p_viport->p_netpath->instance ) ); + __control_logControlPacket( control_lastReq( pControl ) ); + + VNIC_TRACE(VNIC_DBG_CTRL_PKT, + ("IOC %d: instance %d Received initInic response:\n", + pControl->p_viport->ioc_num, + pControl->p_viport->p_netpath->instance ) ); + __control_logControlPacket( pPkt ); +#endif + + pInitInicRsp = &pPkt->cmd.initInicRsp; + pControl->majVer = ntoh16( pInitInicRsp->inicMajorVersion ); + pControl->minVer = ntoh16( pInitInicRsp->inicMinorVersion ); + numDataPaths = pInitInicRsp->numDataPaths; + numLanSwitches = pInitInicRsp->numLanSwitches; + *pFeatures = ntoh32( pInitInicRsp->featuresSupported ); + *pNumAddrs = ntoh16( pInitInicRsp->numAddressEntries ); + + if ( ( pControl->majVer > INIC_MAJORVERSION ) || + (( pControl->majVer == INIC_MAJORVERSION ) && + ( pControl->minVer > INIC_MINORVERSION )) ) + { + VNIC_TRACE_EXIT( VNIC_DBG_CTRL | VNIC_DBG_ERROR, + ("IOC %d: Unsupported version\n", + pControl->p_viport->ioc_num ) ); + goto failure; + } + + if ( numDataPaths != 1 ) + { + VNIC_TRACE_EXIT( VNIC_DBG_CTRL | VNIC_DBG_ERROR, + ("IOC %d: EIOC returned too many datapaths\n", + pControl->p_viport->ioc_num ) ); + goto failure; + } + + if ( *pNumAddrs > p_conf->maxAddressEntries ) + { + VNIC_TRACE_EXIT( VNIC_DBG_CTRL | VNIC_DBG_ERROR, + ("IOC %d: EIOC returned more Address entries than requested\n", + pControl->p_viport->ioc_num) ); + goto failure; + } + if ( *pNumAddrs < p_conf->minAddressEntries ) + { + VNIC_TRACE_EXIT( VNIC_DBG_CTRL | VNIC_DBG_ERROR, + ("IOC %d: Not enough address entries\n", + pControl->p_viport->ioc_num ) ); + goto failure; + } + if ( numLanSwitches < 1 ) + { + VNIC_TRACE_EXIT( VNIC_DBG_CTRL | VNIC_DBG_ERROR, + ("IOC %d: EIOC returned no lan switches\n", + pControl->p_viport->ioc_num ) ); + goto failure; + } + if ( numLanSwitches > 1 ) + { + VNIC_TRACE_EXIT( VNIC_DBG_CTRL | VNIC_DBG_ERROR, + ("IOC %d: EIOC returned multiple lan switches\n", + pControl->p_viport->ioc_num ) ); + goto failure; + } + + pControl->lanSwitch.lanSwitchNum = + pInitInicRsp->lanSwitch[0].lanSwitchNum ; + pControl->lanSwitch.numEnetPorts = + pInitInicRsp->lanSwitch[0].numEnetPorts ; + pControl->lanSwitch.defaultVlan = + ntoh16( pInitInicRsp->lanSwitch[0].defaultVlan ); + *pVlan = pControl->lanSwitch.defaultVlan; + cl_memcpy( pControl->lanSwitch.hwMacAddress, + pInitInicRsp->lanSwitch[0].hwMacAddress, MAC_ADDR_LEN ); + cl_memcpy( pMacAddress, + pInitInicRsp->lanSwitch[0].hwMacAddress, MAC_ADDR_LEN); + + control_recv( pControl, pRecvIo ); + + VNIC_EXIT( VNIC_DBG_CTRL ); + return TRUE; +failure: + viport_failure( pControl->p_viport ); + return FALSE; +} + + +ib_api_status_t +control_configDataPathReq( + IN Control_t *pControl, + IN uint64_t pathId, + IN Inic_RecvPoolConfig_t *pHost, + IN Inic_RecvPoolConfig_t *pEioc ) +{ + Inic_ControlPacket_t *pPkt; + Inic_CmdConfigDataPath_t *pConfigDataPath; + ib_api_status_t ib_status; + + VNIC_ENTER( VNIC_DBG_CTRL ); + + if( pControl->p_viport->errored ) + { + return IB_ERROR; + } + control_initHdr( pControl, CMD_CONFIG_DATA_PATH ); + + pPkt = control_packet( &pControl->sendIo ); + pConfigDataPath = &pPkt->cmd.configDataPathReq; + NdisZeroMemory( pConfigDataPath, sizeof( Inic_CmdConfigDataPath_t ) ); + pConfigDataPath->dataPath = 0; + pConfigDataPath->pathIdentifier = pathId; + copyRecvPoolConfig( pHost, &pConfigDataPath->hostRecvPoolConfig ); + copyRecvPoolConfig( pEioc, &pConfigDataPath->eiocRecvPoolConfig ); + + ib_status = control_send( pControl ); + VNIC_EXIT( VNIC_DBG_CTRL ); + return ib_status; +} + + +BOOLEAN +control_configDataPathRsp( + IN Control_t *pControl, + IN Inic_RecvPoolConfig_t *pHost, + IN Inic_RecvPoolConfig_t *pEioc, + IN Inic_RecvPoolConfig_t *pMaxHost, + IN Inic_RecvPoolConfig_t *pMaxEioc, + IN Inic_RecvPoolConfig_t *pMinHost, + IN Inic_RecvPoolConfig_t *pMinEioc ) +{ + RecvIo_t *pRecvIo; + Inic_ControlPacket_t *pPkt; + Inic_CmdConfigDataPath_t *pConfigDataPath; + + VNIC_ENTER( VNIC_DBG_CTRL ); + + pRecvIo = control_getRsp( pControl ); + if ( !pRecvIo ) + return FALSE; + + pPkt = control_packet( pRecvIo ); + + if ( pPkt->hdr.pktCmd != CMD_CONFIG_DATA_PATH ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("IOC %d: Sent control request:\n", + pControl->p_viport->ioc_num ) ); + + __control_logControlPacket( control_lastReq( pControl ) ); + + VNIC_TRACE( VNIC_DBG_ERROR, + ("IOC %d: Received control response:\n", + pControl->p_viport->ioc_num ) ); + + __control_logControlPacket( pPkt ); + goto failure; + } +#ifdef _DEBUG_ + VNIC_TRACE( VNIC_DBG_CTRL_PKT, + ("IOC %d: instance %d Sent configDATAPATH request:\n", + pControl->p_viport->ioc_num, + pControl->p_viport->p_netpath->instance ) ); + __control_logControlPacket( control_lastReq( pControl ) ); + + VNIC_TRACE(VNIC_DBG_CTRL_PKT, + ("IOC %d: instance %d Received configDATAPATH response:\n", + pControl->p_viport->ioc_num, + pControl->p_viport->p_netpath->instance ) ); + __control_logControlPacket( pPkt ); +#endif + pConfigDataPath = &pPkt->cmd.configDataPathRsp; + + if ( pConfigDataPath->dataPath != 0 ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("IOC %d: Received CMD_CONFIG_DATA_PATH response for wrong data path: %u\n", + pControl->p_viport->ioc_num , pConfigDataPath->dataPath) ); + goto failure; + } + + if ( !checkRecvPoolConfig(&pConfigDataPath->hostRecvPoolConfig, + pHost, pMaxHost, pMinHost ) + || !checkRecvPoolConfig(&pConfigDataPath->eiocRecvPoolConfig, + pEioc, pMaxEioc, pMinEioc)) + { + goto failure; + } + + control_recv( pControl, pRecvIo ); + + VNIC_EXIT( VNIC_DBG_CTRL ); + return TRUE; +failure: + viport_failure( pControl->p_viport ); + VNIC_EXIT( VNIC_DBG_CTRL ); + return FALSE; +} + + +ib_api_status_t +control_exchangePoolsReq( + IN Control_t *pControl, + IN uint64_t addr, + IN uint32_t rkey ) +{ + Inic_CmdExchangePools_t *pExchangePools; + Inic_ControlPacket_t *pPkt; + ib_api_status_t ib_status; + + VNIC_ENTER( VNIC_DBG_CTRL ); + + if( pControl->p_viport->errored ) + { + return IB_ERROR; + } + control_initHdr(pControl, CMD_EXCHANGE_POOLS ); + + pPkt = control_packet( &pControl->sendIo ); + pExchangePools = &pPkt->cmd.exchangePoolsReq; + NdisZeroMemory( pExchangePools, sizeof( Inic_CmdExchangePools_t ) ); + pExchangePools->dataPath = 0; + pExchangePools->poolRKey = rkey; + pExchangePools->poolAddr = hton64( addr ); + + ib_status = control_send( pControl ); + VNIC_EXIT( VNIC_DBG_CTRL ); + return ib_status; +} + + +BOOLEAN +control_exchangePoolsRsp( + IN Control_t *pControl, + IN OUT uint64_t *pAddr, + IN OUT uint32_t *pRkey ) +{ + RecvIo_t *pRecvIo; + Inic_ControlPacket_t *pPkt; + Inic_CmdExchangePools_t *pExchangePools; + + VNIC_ENTER( VNIC_DBG_CTRL ); + + pRecvIo = control_getRsp( pControl ); + if ( !pRecvIo ) + return FALSE; + + pPkt = control_packet( pRecvIo ); + + if ( pPkt->hdr.pktCmd != CMD_EXCHANGE_POOLS ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("IOC %d: Sent control request:\n", + pControl->p_viport->ioc_num ) ); + + __control_logControlPacket( control_lastReq(pControl ) ); + + VNIC_TRACE( VNIC_DBG_ERROR, + ("IOC %d: Received control response:\n", + pControl->p_viport->ioc_num ) ); + + __control_logControlPacket( pPkt ); + goto failure; + } + +#ifdef _DEBUG_ + VNIC_TRACE( VNIC_DBG_CTRL_PKT, + ("IOC %d: instance %d Sent exchangePOOLS request:\n", + pControl->p_viport->ioc_num, + pControl->p_viport->p_netpath->instance ) ); + __control_logControlPacket( control_lastReq( pControl ) ); + + VNIC_TRACE(VNIC_DBG_CTRL_PKT, + ("IOC %d: instance %d Received exchangePOOLS response:\n", + pControl->p_viport->ioc_num, + pControl->p_viport->p_netpath->instance ) ); + __control_logControlPacket( pPkt ); +#endif + pExchangePools = &pPkt->cmd.exchangePoolsRsp; + *pRkey = pExchangePools->poolRKey; + *pAddr = ntoh64( pExchangePools->poolAddr ); + + if ( hton32( pExchangePools->dataPath ) != 0 ) + { + VNIC_TRACE_EXIT( VNIC_DBG_ERROR, + ("IOC %d: Received CMD_EXCHANGE_POOLS response for wrong data path: %u\n", + pControl->p_viport->ioc_num , pExchangePools->dataPath ) ); + goto failure; + } + + control_recv( pControl, pRecvIo ); + + VNIC_EXIT( VNIC_DBG_CTRL ); + return TRUE; + +failure: + viport_failure( pControl->p_viport ); + return FALSE; +} + + +ib_api_status_t +control_configLinkReq( + IN Control_t *pControl, + IN uint8_t flags, + IN uint16_t mtu ) +{ + Inic_CmdConfigLink_t *pConfigLinkReq; + Inic_ControlPacket_t *pPkt; + ib_api_status_t ib_status; + + VNIC_ENTER( VNIC_DBG_CTRL ); + + if( pControl->p_viport->errored ) + { + return IB_ERROR; + } + control_initHdr( pControl, CMD_CONFIG_LINK ); + + pPkt = control_packet( &pControl->sendIo ); + pConfigLinkReq = &pPkt->cmd.configLinkReq; + NdisZeroMemory( pConfigLinkReq, sizeof( Inic_CmdConfigLink_t ) ); + pConfigLinkReq->lanSwitchNum = pControl->lanSwitch.lanSwitchNum; + + if ( flags & INIC_FLAG_ENABLE_NIC ) + { + pConfigLinkReq->cmdFlags |= INIC_FLAG_ENABLE_NIC; + } + else + { + pConfigLinkReq->cmdFlags |= INIC_FLAG_DISABLE_NIC; + } + + if (flags & INIC_FLAG_ENABLE_MCAST_ALL ) + { + pConfigLinkReq->cmdFlags |= INIC_FLAG_ENABLE_MCAST_ALL; + } + else + { + pConfigLinkReq->cmdFlags |= INIC_FLAG_DISABLE_MCAST_ALL; + } + if (flags & INIC_FLAG_ENABLE_PROMISC ) + { + pConfigLinkReq->cmdFlags |= INIC_FLAG_ENABLE_PROMISC; + /* The EIOU doesn't really do PROMISC mode. + * If PROMISC is set, it only receives unicast packets + * I also have to set MCAST_ALL if I want real + * PROMISC mode. + */ + pConfigLinkReq->cmdFlags &= ~INIC_FLAG_DISABLE_MCAST_ALL; + pConfigLinkReq->cmdFlags |= INIC_FLAG_ENABLE_MCAST_ALL; + } + else + { + pConfigLinkReq->cmdFlags |= INIC_FLAG_DISABLE_PROMISC; + } + + if( flags & INIC_FLAG_SET_MTU ) + { + pConfigLinkReq->cmdFlags |= INIC_FLAG_SET_MTU; + pConfigLinkReq->mtuSize = hton16( mtu ); + } + + ib_status = control_send( pControl ); + VNIC_EXIT( VNIC_DBG_CTRL ); + return ib_status; +} + + +BOOLEAN +control_configLinkRsp( + IN Control_t *pControl, + IN OUT uint8_t *pFlags, + IN OUT uint16_t *pMtu ) +{ + RecvIo_t *pRecvIo; + Inic_ControlPacket_t *pPkt; + Inic_CmdConfigLink_t *pConfigLinkRsp; + + VNIC_ENTER( VNIC_DBG_CTRL ); + + pRecvIo = control_getRsp( pControl ); + if ( !pRecvIo ) + return FALSE; + + pPkt = control_packet( pRecvIo ); + if ( pPkt->hdr.pktCmd != CMD_CONFIG_LINK ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("IOC %d: Sent control request:\n", + pControl->p_viport->ioc_num ) ); + + __control_logControlPacket( control_lastReq( pControl ) ); + + VNIC_TRACE( VNIC_DBG_ERROR, + ("IOC %d: Received control response:\n", + pControl->p_viport->ioc_num ) ); + + __control_logControlPacket( pPkt ); + goto failure; + } +#ifdef _DEBUG_ + VNIC_TRACE( VNIC_DBG_CTRL_PKT, + ("IOC %d: instance %d Sent configLINK request:\n", + pControl->p_viport->ioc_num, + pControl->p_viport->p_netpath->instance ) ); + __control_logControlPacket( control_lastReq( pControl ) ); + + VNIC_TRACE(VNIC_DBG_CTRL_PKT, + ("IOC %d: instance %d Received configLINK response:\n", + pControl->p_viport->ioc_num, + pControl->p_viport->p_netpath->instance ) ); + __control_logControlPacket( pPkt ); +#endif + pConfigLinkRsp = &pPkt->cmd.configLinkRsp; + + *pFlags = pConfigLinkRsp->cmdFlags; + *pMtu = ntoh16( pConfigLinkRsp->mtuSize ); + + control_recv( pControl, pRecvIo ); + + VNIC_EXIT( VNIC_DBG_CTRL ); + return TRUE; + +failure: + viport_failure( pControl->p_viport ); + VNIC_EXIT( VNIC_DBG_CTRL ); + return FALSE; +} + +/* control_configAddrsReq: + * Return values: + * -1: failure + * 0: incomplete (successful operation, but more address + * table entries to be updated) + * 1: complete + */ +ib_api_status_t +control_configAddrsReq( + IN Control_t *pControl, + IN Inic_AddressOp_t *pAddrs, + IN uint16_t num, + OUT int32_t *pAddrQueryDone ) +{ + Inic_CmdConfigAddresses_t *pConfigAddrsReq; + Inic_ControlPacket_t *pPkt; + uint16_t i; + uint8_t j; + ib_api_status_t ib_status; + + VNIC_ENTER( VNIC_DBG_CTRL ); + + if( pControl->p_viport->errored ) + { + return IB_ERROR; + } + control_initHdr( pControl, CMD_CONFIG_ADDRESSES ); + + pPkt = control_packet( &pControl->sendIo ); + pConfigAddrsReq = &pPkt->cmd.configAddressesReq; + NdisZeroMemory( pConfigAddrsReq, sizeof( Inic_CmdConfigAddresses_t ) ); + pConfigAddrsReq->lanSwitchNum = pControl->lanSwitch.lanSwitchNum; + + for ( i=0, j = 0; ( i < num ) && ( j < 16 ); i++ ) + { + if ( !pAddrs[i].operation ) + continue; + + pConfigAddrsReq->listAddressOps[j].index = hton16(i); + pConfigAddrsReq->listAddressOps[j].operation = INIC_OP_SET_ENTRY; + pConfigAddrsReq->listAddressOps[j].valid = pAddrs[i].valid; + + cl_memcpy( pConfigAddrsReq->listAddressOps[j].address, + pAddrs[i].address, MAC_ADDR_LEN ); + pConfigAddrsReq->listAddressOps[j].vlan = hton16( pAddrs[i].vlan ); + pAddrs[i].operation = 0; + j++; + } + pConfigAddrsReq->numAddressOps = j; + + for ( ; i < num; i++ ) + { + if ( pAddrs[i].operation ) + break; + } + *pAddrQueryDone = (i == num); + + ib_status = control_send( pControl ); + VNIC_EXIT( VNIC_DBG_CTRL ); + return ib_status; +} + + +BOOLEAN +control_configAddrsRsp( + IN Control_t *pControl ) +{ + RecvIo_t *pRecvIo; + Inic_ControlPacket_t *pPkt; + Inic_CmdConfigAddresses_t *pConfigAddrsRsp; + + VNIC_ENTER( VNIC_DBG_CTRL ); + + pRecvIo = control_getRsp( pControl ); + if ( !pRecvIo ) + return FALSE; + + pPkt = control_packet( pRecvIo ); + if ( pPkt->hdr.pktCmd != CMD_CONFIG_ADDRESSES ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("IOC %d: Sent control request:\n", + pControl->p_viport->ioc_num ) ); + + __control_logControlPacket( control_lastReq( pControl ) ); + + VNIC_TRACE_EXIT(VNIC_DBG_ERROR, + ("IOC %d: Received control response:\n", + pControl->p_viport->ioc_num ) ); + + __control_logControlPacket( pPkt ); + + goto failure; + } + +#ifdef _DEBUG_ + VNIC_TRACE( VNIC_DBG_CTRL_PKT, + ("IOC %d: instance %d Sent configADDRS request:\n", + pControl->p_viport->ioc_num, + pControl->p_viport->p_netpath->instance ) ); + __control_logControlPacket( control_lastReq( pControl ) ); + + VNIC_TRACE(VNIC_DBG_CTRL_PKT, + ("IOC %d: instance %d Received configADDRS response:\n", + pControl->p_viport->ioc_num, + pControl->p_viport->p_netpath->instance ) ); + __control_logControlPacket( pPkt ); +#endif + + pConfigAddrsRsp = &pPkt->cmd.configAddressesRsp; + + control_recv( pControl, pRecvIo ); + VNIC_EXIT( VNIC_DBG_CTRL ); + return TRUE; + +failure: + viport_failure( pControl->p_viport ); + return FALSE; +} + + +ib_api_status_t +control_reportStatisticsReq( + IN Control_t *pControl ) +{ + Inic_ControlPacket_t *pPkt; + Inic_CmdReportStatisticsReq_t *pReportStatisticsReq; + ib_api_status_t ib_status; + + VNIC_ENTER( VNIC_DBG_CTRL ); + + control_initHdr( pControl, CMD_REPORT_STATISTICS ); + + pPkt = control_packet( &pControl->sendIo ); + pReportStatisticsReq = &pPkt->cmd.reportStatisticsReq; + pReportStatisticsReq->lanSwitchNum = pControl->lanSwitch.lanSwitchNum; + + ib_status = control_send( pControl ); + VNIC_EXIT( VNIC_DBG_CTRL ); + return ib_status; +} + + +BOOLEAN +control_reportStatisticsRsp( + IN Control_t *pControl, + IN Inic_CmdReportStatisticsRsp_t *pStats ) +{ + RecvIo_t *pRecvIo; + Inic_ControlPacket_t *pPkt; + Inic_CmdReportStatisticsRsp_t *pRepStatRsp; + + VNIC_ENTER( VNIC_DBG_CTRL ); + + pRecvIo = control_getRsp( pControl ); + if (!pRecvIo) + return FALSE; + + pPkt = control_packet( pRecvIo ); + if ( pPkt->hdr.pktCmd != CMD_REPORT_STATISTICS ) + { + VNIC_TRACE(VNIC_DBG_ERROR, + ("IOC %d: Sent control request:\n", + pControl->p_viport->ioc_num ) ); + + __control_logControlPacket( control_lastReq( pControl ) ); + + VNIC_TRACE_EXIT(VNIC_DBG_ERROR, + ("IOC %d: Received control response:\n", + pControl->p_viport->ioc_num ) ); + + __control_logControlPacket( pPkt ); + + goto failure; + } + + pRepStatRsp = &pPkt->cmd.reportStatisticsRsp; + pStats->ifInBroadcastPkts = ntoh64(pRepStatRsp->ifInBroadcastPkts); + pStats->ifInMulticastPkts = ntoh64(pRepStatRsp->ifInMulticastPkts); + pStats->ifInOctets = ntoh64(pRepStatRsp->ifInOctets); + pStats->ifInUcastPkts = ntoh64(pRepStatRsp->ifInUcastPkts); + pStats->ifInNUcastPkts = ntoh64(pRepStatRsp->ifInNUcastPkts); + pStats->ifInUnderrun = ntoh64(pRepStatRsp->ifInUnderrun); + pStats->ifInErrors = ntoh64(pRepStatRsp->ifInErrors); + pStats->ifOutErrors = ntoh64(pRepStatRsp->ifOutErrors); + pStats->ifOutOctets = ntoh64(pRepStatRsp->ifOutOctets); + pStats->ifOutUcastPkts = ntoh64(pRepStatRsp->ifOutUcastPkts); + pStats->ifOutMulticastPkts = ntoh64(pRepStatRsp->ifOutMulticastPkts); + pStats->ifOutBroadcastPkts = ntoh64(pRepStatRsp->ifOutBroadcastPkts); + pStats->ifOutNUcastPkts = ntoh64(pRepStatRsp->ifOutNUcastPkts); + pStats->ifOutOk = ntoh64(pRepStatRsp->ifOutOk); + pStats->ifInOk = ntoh64(pRepStatRsp->ifInOk); + pStats->ifOutUcastBytes = ntoh64(pRepStatRsp->ifOutUcastBytes); + pStats->ifOutMulticastBytes = ntoh64(pRepStatRsp->ifOutMulticastBytes); + pStats->ifOutBroadcastBytes = ntoh64(pRepStatRsp->ifOutBroadcastBytes); + pStats->ifInUcastBytes = ntoh64(pRepStatRsp->ifInUcastBytes); + pStats->ifInMulticastBytes = ntoh64(pRepStatRsp->ifInMulticastBytes); + pStats->ifInBroadcastBytes = ntoh64(pRepStatRsp->ifInBroadcastBytes); + pStats->ethernetStatus = ntoh64(pRepStatRsp->ethernetStatus); + + control_recv(pControl, pRecvIo); + + VNIC_EXIT( VNIC_DBG_CTRL ); + return TRUE; +failure: + viport_failure( pControl->p_viport ); + return FALSE; +} + + +ib_api_status_t +control_resetReq( + IN Control_t *pControl ) +{ + ib_api_status_t ib_status; + + VNIC_ENTER( VNIC_DBG_CTRL ); + + control_initHdr( pControl, CMD_RESET ); + ib_status = control_send( pControl ); + + VNIC_EXIT( VNIC_DBG_CTRL ); + return ib_status; +} + +BOOLEAN +control_resetRsp( + IN Control_t *pControl ) +{ + RecvIo_t *pRecvIo; + Inic_ControlPacket_t *pPkt; + + VNIC_ENTER( VNIC_DBG_CTRL ); + + pRecvIo = control_getRsp( pControl ); + if ( !pRecvIo ) return FALSE; + + pPkt = control_packet( pRecvIo ); + + if ( pPkt->hdr.pktCmd != CMD_RESET ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("IOC %d: Sent control request:\n", + pControl->p_viport->ioc_num ) ); + + __control_logControlPacket( control_lastReq( pControl ) ); + + VNIC_TRACE( VNIC_DBG_ERROR, + ("IOC %d: Received control response:\n", + pControl->p_viport->ioc_num ) ); + + __control_logControlPacket( pPkt ); + + goto failure; + } + + control_recv( pControl, pRecvIo ); + VNIC_EXIT( VNIC_DBG_CTRL ); + return TRUE; +failure: + viport_failure( pControl->p_viport ); + VNIC_EXIT( VNIC_DBG_CTRL ); + return FALSE; +} + + +ib_api_status_t +control_heartbeatReq( + IN Control_t *pControl, + IN uint32_t hbInterval ) +{ + Inic_ControlPacket_t *pPkt; + Inic_CmdHeartbeat_t *pHeartbeatReq; + ib_api_status_t ib_status; + + VNIC_ENTER( VNIC_DBG_CTRL ); + if( pControl->p_viport->errored ) + { + return IB_ERROR; + } + control_initHdr(pControl, CMD_HEARTBEAT); + + pPkt = control_packet(&pControl->sendIo); + pHeartbeatReq = &pPkt->cmd.heartbeatReq; + + /* pass timeout for the target in microseconds */ + pHeartbeatReq->hbInterval = hton32( hbInterval*1000 ); + + ib_status = control_send( pControl ); + VNIC_EXIT( VNIC_DBG_CTRL ); + return ib_status; +} + +BOOLEAN +control_heartbeatRsp( + IN Control_t *pControl ) +{ + RecvIo_t *pRecvIo; + Inic_ControlPacket_t *pPkt; + Inic_CmdHeartbeat_t *pHeartbeatRsp; + + VNIC_ENTER( VNIC_DBG_CTRL ); + + pRecvIo = control_getRsp( pControl ); + + if (!pRecvIo) + return FALSE; + + pPkt = control_packet(pRecvIo); + + if ( pPkt->hdr.pktCmd != CMD_HEARTBEAT ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("IOC %d: Sent control request:\n", + pControl->p_viport->ioc_num ) ); + + __control_logControlPacket( control_lastReq(pControl) ); + + VNIC_TRACE( VNIC_DBG_ERROR, + ("IOC %d: Received control response:\n", + pControl->p_viport->ioc_num ) ); + + __control_logControlPacket( pPkt ); + goto failure; + } + + pHeartbeatRsp = &pPkt->cmd.heartbeatRsp; + + control_recv( pControl, pRecvIo ); + VNIC_EXIT ( VNIC_DBG_CTRL ); + return TRUE; + +failure: + viport_failure( pControl->p_viport ); + VNIC_EXIT ( VNIC_DBG_CTRL ); + return FALSE; +} + +static void +control_recv( + IN Control_t *pControl, + IN RecvIo_t *pRecvIo ) +{ + VNIC_ENTER( VNIC_DBG_CTRL ); + + if ( ibqp_postRecv( &pControl->qp, &pRecvIo->io ) != IB_SUCCESS ) + viport_failure( pControl->p_viport ); + + VNIC_EXIT ( VNIC_DBG_CTRL ); +} + + +static void +control_recvComplete( + IN Io_t *pIo ) +{ + RecvIo_t *pRecvIo = (RecvIo_t *)pIo; + RecvIo_t *pLastRecvIo; + BOOLEAN status = FALSE; + Control_t *pControl = &pIo->pViport->control; + viport_t *p_viport = pIo->pViport; + Inic_ControlPacket_t *pPkt = control_packet(pRecvIo); + Inic_ControlHeader_t *pCHdr = &pPkt->hdr; + + if( p_viport->errored ) + { + return; + } + switch ( pCHdr->pktType ) + { + case TYPE_INFO: + pLastRecvIo = InterlockedExchangePointer( &pControl->pInfo, pRecvIo ); + + control_processAsync( pControl ); + + if ( pLastRecvIo ) + { + control_recv( pControl, pLastRecvIo ); + } + return; + + case TYPE_RSP: + break; + + default: + //TODO: Should we ever reach this? Who processes the list entries? + ASSERT( pCHdr->pktType == TYPE_INFO || pCHdr->pktType == TYPE_RSP ); + ExInterlockedInsertTailList( &pRecvIo->io.listPtrs, + &pControl->failureList, + &pControl->ioLock ); + return; + } + + if( !InterlockedExchange( (volatile LONG*)&pControl->rspExpected, FALSE ) ) + { + VNIC_TRACE_EXIT( VNIC_DBG_ERROR, + ("UNEXPECTED RSP Packet CMD: %d\n", pCHdr->pktCmd ) ); + return; + } + + InterlockedExchangePointer( &pControl->pResponse, pRecvIo ); + + switch ( pCHdr->pktCmd ) + { + case CMD_INIT_INIC: + status = control_initInicRsp( pControl, + &p_viport->featuresSupported, + p_viport->hwMacAddress, + &p_viport->numMacAddresses, + &p_viport->defaultVlan ); + if( status ) + { + InterlockedExchange( + (volatile LONG*)&p_viport->linkState, + (LONG)LINK_INITINICRSP ); + } + InterlockedOr( &p_viport->updates, SYNC_QUERY ); + break; + + case CMD_CONFIG_DATA_PATH: + status = control_configDataPathRsp( pControl, + data_hostPool( &p_viport->data ), + data_eiocPool( &p_viport->data ), + data_hostPoolMax( &p_viport->data ), + data_eiocPoolMax( &p_viport->data ), + data_hostPoolMin( &p_viport->data ), + data_eiocPoolMin( &p_viport->data )); + if( status ) + { + InterlockedExchange( + (volatile LONG*)&p_viport->linkState, + (LONG)LINK_CONFIGDATAPATHRSP ); + } + InterlockedOr( &p_viport->updates, SYNC_QUERY ); + break; + + case CMD_EXCHANGE_POOLS: + status = control_exchangePoolsRsp( &p_viport->control, + data_remotePoolAddr( &p_viport->data ), + data_remotePoolRkey( &p_viport->data ) ); + if( status ) + { + InterlockedExchange( + (volatile LONG*)&p_viport->linkState, + (LONG)LINK_XCHGPOOLRSP ); + } + InterlockedOr( &p_viport->updates, SYNC_QUERY ); + break; + + /* process other responses */ + case CMD_CONFIG_LINK: + status = control_configLinkRsp( &p_viport->control, + &p_viport->flags, + &p_viport->mtu ); + if( status ) + { + InterlockedExchange( + (volatile LONG*)&p_viport->linkState, + (LONG)LINK_CONFIGLINKRSP ); + + if( p_viport->flags & INIC_FLAG_ENABLE_NIC ) + { + /* don't indicate media state yet if in sync query */ + if( ( InterlockedExchange( &p_viport->p_netpath->carrier, TRUE ) == FALSE ) && + !( p_viport->updates & SYNC_QUERY ) ) + { + viport_restartXmit( p_viport ); + //viport_linkUp( p_viport ); + } + } + else if( p_viport->flags & INIC_FLAG_DISABLE_NIC ) + { + if( InterlockedExchange( &p_viport->p_netpath->carrier, FALSE ) == TRUE ) + { + viport_stopXmit( p_viport ); + viport_linkDown( p_viport ); + } + } + InterlockedAnd( &p_viport->updates, ~NEED_LINK_CONFIG ); + } + break; + + case CMD_HEARTBEAT: + status = control_heartbeatRsp( pControl ); + if( status && + !p_viport->errored && + !p_viport->disconnect ) + { + InterlockedExchange( + (volatile LONG*)&p_viport->link_hb_state, + (LONG)LINK_HEARTBEATRSP ); + } + // Don't signal any waiting thread or start processing other updates. + return; + + case CMD_CONFIG_ADDRESSES: + status = control_configAddrsRsp( pControl ); + if( status == TRUE ) + { // need more entries to send? + if( p_viport->addrs_query_done == 0 ) + { + if( !p_viport->errored ) + { + if( control_configAddrsReq( pControl, + p_viport->macAddresses, + p_viport->numMacAddresses, + &p_viport->addrs_query_done ) != IB_SUCCESS ) + { + viport_failure( p_viport ); + } + } + // Don't signal any waiting thread or start processing other updates. + return; + } + + InterlockedAnd( &p_viport->updates, ~NEED_ADDRESS_CONFIG ); + InterlockedExchange( (volatile LONG*)&p_viport->linkState, + (LONG)LINK_CONFIGADDRSRSP ); + } + break; + + case CMD_REPORT_STATISTICS: + status = control_reportStatisticsRsp( pControl, &p_viport->stats ); + if ( status ) + { + if( p_viport->stats.ethernetStatus > 0 && + !p_viport->errored ) + { + viport_linkUp( p_viport ); + } + else + { + viport_linkDown( p_viport ); + } + } + InterlockedAnd( &p_viport->updates, ~NEED_STATS ); + break; + + case CMD_RESET: + status = control_resetRsp( pControl ); + if( status ) + { + status = FALSE; + InterlockedExchange( + (volatile LONG*)&p_viport->linkState, + (LONG)LINK_RESETRSP ); + } + break; + + default: + break; + } + + if( _viport_process_query( p_viport, FALSE ) != NDIS_STATUS_PENDING ) + { + /* Complete any pending set OID. */ + vnic_resume_set_oids( p_viport->p_adapter ); + } + + if( InterlockedAnd( &p_viport->updates, ~SYNC_QUERY ) & SYNC_QUERY ) + cl_event_signal( &p_viport->sync_event ); +} + + +static ib_api_status_t +control_send( + IN Control_t *pControl ) +{ + Inic_ControlPacket_t *pPkt = control_packet(&pControl->sendIo); + + VNIC_ENTER ( VNIC_DBG_CTRL ); + + if ( InterlockedCompareExchange( (volatile LONG*)&pControl->reqOutstanding, + TRUE, FALSE ) == TRUE ) + { + /* IF WE HIT THIS WE ARE HOSED!!! + * by the time we detect this error, the send buffer has been + * overwritten, and if we retry we will send garbage data. + */ + VNIC_TRACE_EXIT( VNIC_DBG_ERROR, + ("IB Send never completed\n" ) ); + goto failure; + } + +#ifdef _DEBUG_ + //__control_logControlPacket( pPkt ); +#endif + InterlockedExchange( (volatile LONG*)&pControl->rspExpected, + (LONG)pPkt->hdr.pktCmd ); + + control_timer( pControl, pControl->p_conf->rspTimeout ); + +#ifdef VNIC_STATISTIC + pControl->statistics.requestTime = cl_get_time_stamp(); +#endif /* VNIC_STATISTIC */ + + if( ( ibqp_postSend( &pControl->qp, &pControl->sendIo.io )) != IB_SUCCESS ) + { + InterlockedExchange((volatile LONG*)&pControl->reqOutstanding, FALSE ); + + VNIC_TRACE( VNIC_DBG_ERROR, + ("IOC %d: Failed to post send\n", pControl->p_viport->ioc_num ) ); + goto failure; + } + + VNIC_EXIT( VNIC_DBG_CTRL ); + return IB_SUCCESS; + +failure: + pControl->p_viport->p_adapter->hung++; + viport_failure( pControl->p_viport ); + VNIC_EXIT( VNIC_DBG_CTRL ); + return IB_ERROR; +} + + +static void +control_sendComplete( + IN Io_t *pIo ) +{ + Control_t *pControl = &pIo->pViport->control; + + VNIC_ENTER( VNIC_DBG_CTRL ); + + InterlockedExchange((volatile LONG*)&pControl->reqOutstanding, FALSE ); + + VNIC_EXIT( VNIC_DBG_CTRL ); + return; +} + +static void +control_timeout( + IN void *p_context ) +{ + Control_t *pControl; + + VNIC_ENTER( VNIC_DBG_CTRL ); + + pControl = (Control_t *)p_context; + + InterlockedExchange( (LONG *)&pControl->timerstate, (LONG)TIMER_EXPIRED ); + + InterlockedExchange( (volatile LONG*)&pControl->rspExpected, FALSE ); + + VNIC_EXIT( VNIC_DBG_CTRL ); + return; +} + +static void +control_timer( + IN Control_t *pControl, + IN int timeout ) +{ + VNIC_ENTER( VNIC_DBG_CTRL ); + + InterlockedExchange( (LONG *)&pControl->timerstate, (LONG)TIMER_ACTIVE ); + + cl_timer_start(&pControl->timer, timeout); + + VNIC_EXIT( VNIC_DBG_CTRL ); + return; +} + +static void +control_timerStop( + IN Control_t *pControl ) +{ + VNIC_ENTER( VNIC_DBG_CTRL ); + + + if ( ( InterlockedExchange( (LONG *)&pControl->timerstate, + (LONG)TIMER_IDLE )) == TIMER_ACTIVE ) + { + cl_timer_stop( &pControl->timer ); + } + + VNIC_EXIT( VNIC_DBG_CTRL ); + return; +} + +static void +control_initHdr( + IN Control_t * pControl, + IN uint8_t cmd ) +{ + ControlConfig_t *p_conf; + Inic_ControlPacket_t *pPkt; + Inic_ControlHeader_t *pHdr; + + VNIC_ENTER( VNIC_DBG_CTRL ); + + p_conf = pControl->p_conf; + + pPkt = control_packet( &pControl->sendIo ); + pHdr = &pPkt->hdr; + + pHdr->pktType = TYPE_REQ; + pHdr->pktCmd = cmd; + pHdr->pktSeqNum = ++pControl->seqNum; + pControl->reqRetryCounter = 0; + pHdr->pktRetryCount = 0; + + VNIC_EXIT( VNIC_DBG_CTRL ); +} + +static RecvIo_t* +control_getRsp( + IN Control_t *pControl ) +{ + RecvIo_t *pRecvIo; + + VNIC_ENTER ( VNIC_DBG_CTRL ); + + pRecvIo = InterlockedExchangePointer( &pControl->pResponse, NULL ); + + if ( pRecvIo != NULL ) + { + control_timerStop(pControl); + return pRecvIo; + } + + if ( ( pControl->timerstate = + InterlockedCompareExchange( (LONG *)&pControl->timerstate, + (LONG)TIMER_IDLE, (LONG)TIMER_EXPIRED )) == TIMER_EXPIRED ) + { + Inic_ControlPacket_t *pPkt = control_packet( &pControl->sendIo ); + Inic_ControlHeader_t *pHdr = &pPkt->hdr; + + VNIC_TRACE( VNIC_DBG_ERROR, + ("IOC %d: No response received from EIOC\n", + pControl->p_viport->ioc_num ) ); +#ifdef VNIC_STATISTIC + pControl->statistics.timeoutNum++; +#endif /* VNIC_STATISTIC */ + + pControl->reqRetryCounter++; + + if ( pControl->reqRetryCounter >= pControl->p_conf->reqRetryCount ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("IOC %d: Control packet retry exceeded\n", + pControl->p_viport->ioc_num ) ); + } + else + { + pHdr->pktRetryCount = pControl->reqRetryCounter; + control_send( pControl ); + } + } + return NULL; +} + +static void +copyRecvPoolConfig( + IN Inic_RecvPoolConfig_t *pSrc, + IN OUT Inic_RecvPoolConfig_t *pDst ) +{ + + pDst->sizeRecvPoolEntry = hton32(pSrc->sizeRecvPoolEntry); + pDst->numRecvPoolEntries = hton32(pSrc->numRecvPoolEntries); + pDst->timeoutBeforeKick = hton32(pSrc->timeoutBeforeKick); + pDst->numRecvPoolEntriesBeforeKick = hton32(pSrc->numRecvPoolEntriesBeforeKick); + pDst->numRecvPoolBytesBeforeKick = hton32(pSrc->numRecvPoolBytesBeforeKick); + pDst->freeRecvPoolEntriesPerUpdate = hton32(pSrc->freeRecvPoolEntriesPerUpdate); + return; +} + +static BOOLEAN +checkRecvPoolConfigValue( + IN void *pSrc, + IN void *pDst, + IN void *pMax, + IN void *pMin, + IN char *name ) +{ + uint32_t value; + uint32_t *p_src = (uint32_t *)pSrc; + uint32_t *p_dst = (uint32_t *)pDst; + uint32_t *p_min = (uint32_t *)pMin; + uint32_t *p_max = (uint32_t *)pMax; + + UNREFERENCED_PARAMETER( name ); + + value = ntoh32( *p_src ); + + if (value > *p_max ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("Value %s too large\n", name) ); + return FALSE; + } + else if (value < *p_min ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("Value %s too small\n", name) ); + return FALSE; + } + + *p_dst = value; + return TRUE; +} + +static BOOLEAN +checkRecvPoolConfig( + IN Inic_RecvPoolConfig_t *pSrc, + IN Inic_RecvPoolConfig_t *pDst, + IN Inic_RecvPoolConfig_t *pMax, + IN Inic_RecvPoolConfig_t *pMin ) +{ + if (!checkRecvPoolConfigValue(&pSrc->sizeRecvPoolEntry, &pDst->sizeRecvPoolEntry, + &pMax->sizeRecvPoolEntry, &pMin->sizeRecvPoolEntry, "sizeRecvPoolEntry") + || !checkRecvPoolConfigValue(&pSrc->numRecvPoolEntries, &pDst->numRecvPoolEntries, + &pMax->numRecvPoolEntries, &pMin->numRecvPoolEntries, "numRecvPoolEntries") + || !checkRecvPoolConfigValue(&pSrc->timeoutBeforeKick, &pDst->timeoutBeforeKick, + &pMax->timeoutBeforeKick, &pMin->timeoutBeforeKick, "timeoutBeforeKick") + || !checkRecvPoolConfigValue(&pSrc->numRecvPoolEntriesBeforeKick, + &pDst->numRecvPoolEntriesBeforeKick, &pMax->numRecvPoolEntriesBeforeKick, + &pMin->numRecvPoolEntriesBeforeKick, "numRecvPoolEntriesBeforeKick") + || !checkRecvPoolConfigValue(&pSrc->numRecvPoolBytesBeforeKick, + &pDst->numRecvPoolBytesBeforeKick, &pMax->numRecvPoolBytesBeforeKick, + &pMin->numRecvPoolBytesBeforeKick, "numRecvPoolBytesBeforeKick") + || !checkRecvPoolConfigValue(&pSrc->freeRecvPoolEntriesPerUpdate, + &pDst->freeRecvPoolEntriesPerUpdate, &pMax->freeRecvPoolEntriesPerUpdate, + &pMin->freeRecvPoolEntriesPerUpdate, "freeRecvPoolEntriesPerUpdate")) + return FALSE; + + if ( !IsPowerOf2( pDst->numRecvPoolEntries ) ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("numRecvPoolEntries (%d) must be power of 2\n", + pDst->numRecvPoolEntries) ); + return FALSE; + } + if ( !IsPowerOf2( pDst->freeRecvPoolEntriesPerUpdate ) ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("freeRecvPoolEntriesPerUpdate (%d) must be power of 2\n", + pDst->freeRecvPoolEntriesPerUpdate) ); + return FALSE; + } + if ( pDst->freeRecvPoolEntriesPerUpdate >= pDst->numRecvPoolEntries ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("freeRecvPoolEntriesPerUpdate (%d) must be less than numRecvPoolEntries (%d)\n", + pDst->freeRecvPoolEntriesPerUpdate, pDst->numRecvPoolEntries) ); + return FALSE; + } + if ( pDst->numRecvPoolEntriesBeforeKick >= pDst->numRecvPoolEntries ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("numRecvPoolEntriesBeforeKick (%d) must be less than numRecvPoolEntries (%d)\n", + pDst->numRecvPoolEntriesBeforeKick, pDst->numRecvPoolEntries) ); + return FALSE; + } + + return TRUE; +} + +static void +__control_logControlPacket( + IN Inic_ControlPacket_t *pPkt ) +{ + char *type; + int i; + + switch( pPkt->hdr.pktType ) + { + case TYPE_INFO: + type = "TYPE_INFO"; + break; + case TYPE_REQ: + type = "TYPE_REQ"; + break; + case TYPE_RSP: + type = "TYPE_RSP"; + break; + case TYPE_ERR: + type = "TYPE_ERR"; + break; + default: + type = "UNKNOWN"; + } + switch( pPkt->hdr.pktCmd ) + { + case CMD_INIT_INIC: + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + ("ControlPacket: pktType = %s, pktCmd = CMD_INIT_INIC\n", type ) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" pktSeqNum = %u, pktRetryCount = %u\n", + pPkt->hdr.pktSeqNum, + pPkt->hdr.pktRetryCount) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" inicMajorVersion = %u, inicMinorVersion = %u\n", + ntoh16(pPkt->cmd.initInicReq.inicMajorVersion), + ntoh16(pPkt->cmd.initInicReq.inicMinorVersion)) ); + if (pPkt->hdr.pktType == TYPE_REQ) + { + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" inicInstance = %u, numDataPaths = %u\n", + pPkt->cmd.initInicReq.inicInstance, + pPkt->cmd.initInicReq.numDataPaths) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" numAddressEntries = %u\n", + ntoh16(pPkt->cmd.initInicReq.numAddressEntries)) ); + } + else + { + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" numLanSwitches = %u, numDataPaths = %u\n", + pPkt->cmd.initInicRsp.numLanSwitches, + pPkt->cmd.initInicRsp.numDataPaths) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" numAddressEntries = %u, featuresSupported = %08x\n", + ntoh16(pPkt->cmd.initInicRsp.numAddressEntries), + ntoh32(pPkt->cmd.initInicRsp.featuresSupported)) ); + if (pPkt->cmd.initInicRsp.numLanSwitches != 0) + { + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + ("lanSwitch[0] lanSwitchNum = %u, numEnetPorts = %08x\n", + pPkt->cmd.initInicRsp.lanSwitch[0].lanSwitchNum, + pPkt->cmd.initInicRsp.lanSwitch[0].numEnetPorts) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" defaultVlan = %u, hwMacAddress = %02x:%02x:%02x:%02x:%02x:%02x\n", + ntoh16(pPkt->cmd.initInicRsp.lanSwitch[0].defaultVlan), + pPkt->cmd.initInicRsp.lanSwitch[0].hwMacAddress[0], + pPkt->cmd.initInicRsp.lanSwitch[0].hwMacAddress[1], + pPkt->cmd.initInicRsp.lanSwitch[0].hwMacAddress[2], + pPkt->cmd.initInicRsp.lanSwitch[0].hwMacAddress[3], + pPkt->cmd.initInicRsp.lanSwitch[0].hwMacAddress[4], + pPkt->cmd.initInicRsp.lanSwitch[0].hwMacAddress[5]) ); + } + } + break; + case CMD_CONFIG_DATA_PATH: + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + ( "ControlPacket: pktType = %s, pktCmd = CMD_CONFIG_DATA_PATH\n", type) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" pktSeqNum = %u, pktRetryCount = %u\n", + pPkt->hdr.pktSeqNum, + pPkt->hdr.pktRetryCount) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" pathIdentifier = %"PRIx64", dataPath = %u\n", + pPkt->cmd.configDataPathReq.pathIdentifier, + pPkt->cmd.configDataPathReq.dataPath) ); + + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + ("Host Config sizeRecvPoolEntry = %u, numRecvPoolEntries = %u\n", + ntoh32(pPkt->cmd.configDataPathReq.hostRecvPoolConfig.sizeRecvPoolEntry), + ntoh32(pPkt->cmd.configDataPathReq.hostRecvPoolConfig.numRecvPoolEntries)) ); + + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" timeoutBeforeKick = %u, numRecvPoolEntriesBeforeKick = %u\n", + ntoh32(pPkt->cmd.configDataPathReq.hostRecvPoolConfig.timeoutBeforeKick), + ntoh32(pPkt->cmd.configDataPathReq.hostRecvPoolConfig.numRecvPoolEntriesBeforeKick)) ); + + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" numRecvPoolBytesBeforeKick = %u, freeRecvPoolEntriesPerUpdate = %u\n", + ntoh32(pPkt->cmd.configDataPathReq.hostRecvPoolConfig.numRecvPoolBytesBeforeKick), + ntoh32(pPkt->cmd.configDataPathReq.hostRecvPoolConfig.freeRecvPoolEntriesPerUpdate)) ); + + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + ("Eioc Config sizeRecvPoolEntry = %u, numRecvPoolEntries = %u\n", + ntoh32(pPkt->cmd.configDataPathReq.eiocRecvPoolConfig.sizeRecvPoolEntry), + ntoh32(pPkt->cmd.configDataPathReq.eiocRecvPoolConfig.numRecvPoolEntries)) ); + + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" timeoutBeforeKick = %u, numRecvPoolEntriesBeforeKick = %u\n", + ntoh32(pPkt->cmd.configDataPathReq.eiocRecvPoolConfig.timeoutBeforeKick), + ntoh32(pPkt->cmd.configDataPathReq.eiocRecvPoolConfig.numRecvPoolEntriesBeforeKick)) ); + + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" numRecvPoolBytesBeforeKick = %u, freeRecvPoolEntriesPerUpdate = %u\n", + ntoh32(pPkt->cmd.configDataPathReq.eiocRecvPoolConfig.numRecvPoolBytesBeforeKick), + ntoh32(pPkt->cmd.configDataPathReq.eiocRecvPoolConfig.freeRecvPoolEntriesPerUpdate)) ); + break; + case CMD_EXCHANGE_POOLS: + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + ("ControlPacket: pktType = %s, pktCmd = CMD_EXCHANGE_POOLS\n", type ) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" pktSeqNum = %u, pktRetryCount = %u\n", + pPkt->hdr.pktSeqNum, + pPkt->hdr.pktRetryCount) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" datapath = %u\n", + pPkt->cmd.exchangePoolsReq.dataPath) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" poolRKey = %08x poolAddr = %"PRIx64"\n", + ntoh32(pPkt->cmd.exchangePoolsReq.poolRKey), + ntoh64(pPkt->cmd.exchangePoolsReq.poolAddr)) ); + break; + case CMD_CONFIG_ADDRESSES: + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + ( "ControlPacket: pktType = %s, pktCmd = CMD_CONFIG_ADDRESSES\n", type ) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" pktSeqNum = %u, pktRetryCount = %u\n", + pPkt->hdr.pktSeqNum, + pPkt->hdr.pktRetryCount) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" numAddressOps = %x, lanSwitchNum = %d\n", + pPkt->cmd.configAddressesReq.numAddressOps, + pPkt->cmd.configAddressesReq.lanSwitchNum) ); + for (i = 0; ( i < pPkt->cmd.configAddressesReq.numAddressOps) && (i < 16); i++) + { + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" listAddressOps[%u].index = %u\n", + i, ntoh16(pPkt->cmd.configAddressesReq.listAddressOps[i].index)) ); + + switch(pPkt->cmd.configAddressesReq.listAddressOps[i].operation) + { + case INIC_OP_GET_ENTRY: + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" listAddressOps[%u].operation = INIC_OP_GET_ENTRY\n", i) ); + break; + case INIC_OP_SET_ENTRY: + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" listAddressOps[%u].operation = INIC_OP_SET_ENTRY\n", i) ); + break; + default: + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" listAddressOps[%u].operation = UNKNOWN(%d)\n", + i, pPkt->cmd.configAddressesReq.listAddressOps[i].operation) ); + break; + } + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" listAddressOps[%u].valid = %u\n", + i, pPkt->cmd.configAddressesReq.listAddressOps[i].valid) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" listAddressOps[%u].address = %02x:%02x:%02x:%02x:%02x:%02x\n", i, + pPkt->cmd.configAddressesReq.listAddressOps[i].address[0], + pPkt->cmd.configAddressesReq.listAddressOps[i].address[1], + pPkt->cmd.configAddressesReq.listAddressOps[i].address[2], + pPkt->cmd.configAddressesReq.listAddressOps[i].address[3], + pPkt->cmd.configAddressesReq.listAddressOps[i].address[4], + pPkt->cmd.configAddressesReq.listAddressOps[i].address[5]) ); + + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" listAddressOps[%u].vlan = %u\n", + i, ntoh16(pPkt->cmd.configAddressesReq.listAddressOps[i].vlan)) ); + } + break; + case CMD_CONFIG_LINK: + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + ("ControlPacket: pktType = %s, pktCmd = CMD_CONFIG_LINK\n", type) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" pktSeqNum = %u, pktRetryCount = %u\n", + pPkt->hdr.pktSeqNum, + pPkt->hdr.pktRetryCount) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" cmdFlags = %x\n", + pPkt->cmd.configLinkReq.cmdFlags) ); + + if ( pPkt->cmd.configLinkReq.cmdFlags & INIC_FLAG_ENABLE_NIC ) + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" INIC_FLAG_ENABLE_NIC\n") ); + + if ( pPkt->cmd.configLinkReq.cmdFlags & INIC_FLAG_DISABLE_NIC ) + + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" INIC_FLAG_DISABLE_NIC\n") ); + + if ( pPkt->cmd.configLinkReq.cmdFlags & INIC_FLAG_ENABLE_MCAST_ALL ) + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" INIC_FLAG_ENABLE_MCAST_ALL\n") ); + + if ( pPkt->cmd.configLinkReq.cmdFlags & INIC_FLAG_DISABLE_MCAST_ALL ) + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" INIC_FLAG_DISABLE_MCAST_ALL\n") ); + + if ( pPkt->cmd.configLinkReq.cmdFlags & INIC_FLAG_ENABLE_PROMISC ) + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" INIC_FLAG_ENABLE_PROMISC\n") ); + + if ( pPkt->cmd.configLinkReq.cmdFlags & INIC_FLAG_DISABLE_PROMISC ) + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" INIC_FLAG_DISABLE_PROMISC\n") ); + if ( pPkt->cmd.configLinkReq.cmdFlags & INIC_FLAG_SET_MTU ) + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" INIC_FLAG_SET_MTU\n") ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" lanSwitchNum = %x, mtuSize = %d\n", + pPkt->cmd.configLinkReq.lanSwitchNum, + ntoh16(pPkt->cmd.configLinkReq.mtuSize)) ); + if ( pPkt->hdr.pktType == TYPE_RSP ) + { + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" defaultVlan = %u, hwMacAddress = %02x:%02x:%02x:%02x:%02x:%02x\n", + ntoh16(pPkt->cmd.configLinkReq.defaultVlan), + pPkt->cmd.configLinkReq.hwMacAddress[0], + pPkt->cmd.configLinkReq.hwMacAddress[1], + pPkt->cmd.configLinkReq.hwMacAddress[2], + pPkt->cmd.configLinkReq.hwMacAddress[3], + pPkt->cmd.configLinkReq.hwMacAddress[4], + pPkt->cmd.configLinkReq.hwMacAddress[5]) ); + } + break; + case CMD_REPORT_STATISTICS: + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + ("ControlPacket: pktType = %s, pktCmd = CMD_REPORT_STATISTICS\n", type ) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" pktSeqNum = %u, pktRetryCount = %u\n", + pPkt->hdr.pktSeqNum, + pPkt->hdr.pktRetryCount) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" lanSwitchNum = %u\n", + pPkt->cmd.reportStatisticsReq.lanSwitchNum) ); + + if (pPkt->hdr.pktType == TYPE_REQ) + break; + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" ifInBroadcastPkts = %"PRIu64, + ntoh64(pPkt->cmd.reportStatisticsRsp.ifInBroadcastPkts)) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" ifInMulticastPkts = %"PRIu64"\n", + ntoh64(pPkt->cmd.reportStatisticsRsp.ifInMulticastPkts)) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" ifInOctets = %"PRIu64, + ntoh64(pPkt->cmd.reportStatisticsRsp.ifInOctets)) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" ifInUcastPkts = %"PRIu64"\n", + ntoh64(pPkt->cmd.reportStatisticsRsp.ifInUcastPkts)) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" ifInNUcastPkts = %"PRIu64, + ntoh64(pPkt->cmd.reportStatisticsRsp.ifInNUcastPkts)) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" ifInUnderrun = %"PRIu64"\n", + ntoh64(pPkt->cmd.reportStatisticsRsp.ifInUnderrun)) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" ifInErrors = %"PRIu64, + ntoh64(pPkt->cmd.reportStatisticsRsp.ifInErrors)) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" ifOutErrors = %"PRIu64"\n", + ntoh64(pPkt->cmd.reportStatisticsRsp.ifOutErrors)) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" ifOutOctets = %"PRIu64, + ntoh64(pPkt->cmd.reportStatisticsRsp.ifOutOctets)) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" ifOutUcastPkts = %"PRIu64"\n", + ntoh64(pPkt->cmd.reportStatisticsRsp.ifOutUcastPkts)) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" ifOutMulticastPkts = %"PRIu64, + ntoh64(pPkt->cmd.reportStatisticsRsp.ifOutMulticastPkts)) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" ifOutBroadcastPkts = %"PRIu64"\n", + ntoh64(pPkt->cmd.reportStatisticsRsp.ifOutBroadcastPkts)) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" ifOutNUcastPkts = %"PRIu64, + ntoh64(pPkt->cmd.reportStatisticsRsp.ifOutNUcastPkts)) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" ifOutOk = %"PRIu64"\n", + ntoh64(pPkt->cmd.reportStatisticsRsp.ifOutOk)) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" ifInOk = %"PRIu64, + ntoh64(pPkt->cmd.reportStatisticsRsp.ifInOk)) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" ifOutUcastBytes = %"PRIu64"\n", + ntoh64(pPkt->cmd.reportStatisticsRsp.ifOutUcastBytes)) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" ifOutMulticastBytes = %"PRIu64, + ntoh64(pPkt->cmd.reportStatisticsRsp.ifOutMulticastBytes)) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" ifOutBroadcastBytes = %"PRIu64"\n", + ntoh64(pPkt->cmd.reportStatisticsRsp.ifOutBroadcastBytes)) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" ifInUcastBytes = %"PRIu64, + ntoh64(pPkt->cmd.reportStatisticsRsp.ifInUcastBytes)) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" ifInMulticastBytes = %"PRIu64"\n", + ntoh64(pPkt->cmd.reportStatisticsRsp.ifInMulticastBytes)) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" ifInBroadcastBytes = %"PRIu64, + ntoh64(pPkt->cmd.reportStatisticsRsp.ifInBroadcastBytes)) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" ethernetStatus = %"PRIu64"\n", + ntoh64(pPkt->cmd.reportStatisticsRsp.ethernetStatus)) ); + break; + case CMD_CLEAR_STATISTICS: + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + ("ControlPacket: pktType = %s, pktCmd = CMD_CLEAR_STATISTICS\n", type ) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" pktSeqNum = %u, pktRetryCount = %u\n", + pPkt->hdr.pktSeqNum, + pPkt->hdr.pktRetryCount) ); + break; + case CMD_REPORT_STATUS: + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + ("ControlPacket: pktType = %s, pktCmd = CMD_REPORT_STATUS\n", + type) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" pktSeqNum = %u, pktRetryCount = %u\n", + pPkt->hdr.pktSeqNum, + pPkt->hdr.pktRetryCount) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" lanSwitchNum = %u, isFatal = %u\n", + pPkt->cmd.reportStatus.lanSwitchNum, + pPkt->cmd.reportStatus.isFatal) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" statusNumber = %u, statusInfo = %u\n", + ntoh32(pPkt->cmd.reportStatus.statusNumber), + ntoh32(pPkt->cmd.reportStatus.statusInfo)) ); + pPkt->cmd.reportStatus.fileName[31] = '\0'; + pPkt->cmd.reportStatus.routine[31] = '\0'; + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" filename = %s, routine = %s\n", + pPkt->cmd.reportStatus.fileName, + pPkt->cmd.reportStatus.routine) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" lineNum = %u, errorParameter = %u\n", + ntoh32(pPkt->cmd.reportStatus.lineNum), + ntoh32(pPkt->cmd.reportStatus.errorParameter)) ); + pPkt->cmd.reportStatus.descText[127] = '\0'; + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" descText = %s\n", + pPkt->cmd.reportStatus.descText) ); + break; + case CMD_RESET: + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + ("ControlPacket: pktType = %s, pktCmd = CMD_RESET\n", type ) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" pktSeqNum = %u, pktRetryCount = %u\n", + pPkt->hdr.pktSeqNum, + pPkt->hdr.pktRetryCount) ); + break; + case CMD_HEARTBEAT: + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + ("ControlPacket: pktType = %s, pktCmd = CMD_HEARTBEAT\n", type ) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" pktSeqNum = %u, pktRetryCount = %u\n", + pPkt->hdr.pktSeqNum, + pPkt->hdr.pktRetryCount) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" hbInterval = %d\n", + ntoh32(pPkt->cmd.heartbeatReq.hbInterval)) ); + break; + default: + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + ("ControlPacket: pktType = %s, pktCmd = UNKNOWN (%u)\n", + type,pPkt->hdr.pktCmd) ); + VNIC_PRINT( VNIC_DBG_CTRL_PKT, + (" pktSeqNum = %u, pktRetryCount = %u\n", + pPkt->hdr.pktSeqNum, + pPkt->hdr.pktRetryCount) ); + break; + } + return; +} diff --git a/trunk/ulp/qlgcvnic/kernel/vnic_control.h b/trunk/ulp/qlgcvnic/kernel/vnic_control.h new file mode 100644 index 00000000..b18372bf --- /dev/null +++ b/trunk/ulp/qlgcvnic/kernel/vnic_control.h @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2007 QLogic Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id$ + */ + +#ifndef _VNIC_CONTROL_H_ +#define _VNIC_CONTROL_H_ + +#include "vnic_controlpkt.h" +#include "vnic_util.h" + +typedef enum { + TIMER_IDLE, + TIMER_ACTIVE, + TIMER_EXPIRED +}timerstate_t; + +typedef struct Control { + struct _viport *p_viport; + struct ControlConfig *p_conf; + IbRegion_t region; + IbQp_t qp; + uint8_t *pLocalStorage; + uint16_t majVer; + uint16_t minVer; + Inic_LanSwitchAttributes_t lanSwitch; + SendIo_t sendIo; + RecvIo_t *pRecvIos; + + timerstate_t timerstate; + cl_timer_t timer; + uint8_t reqRetryCounter; + uint8_t seqNum; + uint32_t reqOutstanding; + uint32_t rspExpected; + RecvIo_t *pResponse; + RecvIo_t *pInfo; + LIST_ENTRY failureList; + KSPIN_LOCK ioLock; + +#ifdef VNIC_STATISTIC + struct { + uint64_t requestTime; /* Intermediate value */ + uint64_t responseTime; + uint32_t responseNum; + uint64_t responseMax; + uint64_t responseMin; + uint32_t timeoutNum; + } statistics; +#endif /* VNIC_STATISTIC */ +} Control_t; + +void +control_construct( + IN Control_t *pControl, + IN struct _viport *pViport ); + +ib_api_status_t control_init(Control_t *pControl, struct _viport *pViport, + struct ControlConfig *p_conf, uint64_t guid); +void control_cleanup(Control_t *pControl); +void control_processAsync(Control_t *pControl); +ib_api_status_t control_initInicReq(Control_t *pControl); +BOOLEAN control_initInicRsp(Control_t *pControl, uint32_t *pFeatures, + uint8_t *pMacAddress, uint16_t *pNumAddrs, uint16_t *pVlan); +ib_api_status_t control_configDataPathReq(Control_t *pControl, uint64_t pathId, + struct Inic_RecvPoolConfig *pHost, + struct Inic_RecvPoolConfig *pEioc); +BOOLEAN control_configDataPathRsp(Control_t *pControl, + struct Inic_RecvPoolConfig *pHost, + struct Inic_RecvPoolConfig *pEioc, + struct Inic_RecvPoolConfig *pMaxHost, + struct Inic_RecvPoolConfig *pMaxEioc, + struct Inic_RecvPoolConfig *pMinHost, + struct Inic_RecvPoolConfig *pMinEioc); +ib_api_status_t control_exchangePoolsReq(Control_t *pControl, uint64_t addr, uint32_t rkey); +BOOLEAN control_exchangePoolsRsp(Control_t *pControl, uint64_t *pAddr, + uint32_t *pRkey); +ib_api_status_t control_configLinkReq(Control_t *pControl, uint8_t flags, uint16_t mtu); +BOOLEAN control_configLinkRsp(Control_t *pControl, uint8_t *pFlags, uint16_t *pMtu); +ib_api_status_t control_configAddrsReq(Control_t *pControl, Inic_AddressOp_t *pAddrs, + uint16_t num, int32_t *pAddrQueryDone); +BOOLEAN control_configAddrsRsp(Control_t *pControl); +ib_api_status_t control_reportStatisticsReq(Control_t *pControl); +BOOLEAN control_reportStatisticsRsp(Control_t *pControl, + struct Inic_CmdReportStatisticsRsp *pStats); +ib_api_status_t control_resetReq( Control_t *pControl ); +BOOLEAN control_resetRsp(Control_t *pControl); +ib_api_status_t control_heartbeatReq(Control_t *pControl, uint32_t hbInterval); +BOOLEAN control_heartbeatRsp(Control_t *pControl); + +#define control_packet(pIo) (Inic_ControlPacket_t *)(LONG_PTR)((pIo)->dsList.vaddr ) +#define control_lastReq(pControl) control_packet(&(pControl)->sendIo) +#define control_features(pControl) (pControl)->featuresSupported +#define control_getMacAddress(pControl,addr) \ + memcpy(addr,(pControl)->lanSwitch.hwMacAddress,MAC_ADDR_LEN) + +#endif /* _VNIC_CONTROL_H_ */ diff --git a/trunk/ulp/qlgcvnic/kernel/vnic_controlpkt.h b/trunk/ulp/qlgcvnic/kernel/vnic_controlpkt.h new file mode 100644 index 00000000..12427267 --- /dev/null +++ b/trunk/ulp/qlgcvnic/kernel/vnic_controlpkt.h @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2007 QLogic Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id$ + */ + +#ifndef _VNIC_CONTROLPKT_H_ +#define _VNIC_CONTROLPKT_H_ + +#include +#define MAX_HOST_NAME_SIZE 64 + +typedef struct Inic_ConnectionData { + uint64_t pathId; + uint8_t inicInstance; + uint8_t pathNum; + uint8_t nodename[MAX_HOST_NAME_SIZE+1]; + uint8_t reserved; + uint32_t featuresSupported; +} Inic_ConnectionData_t; + +typedef struct Inic_ControlHeader { + uint8_t pktType; + uint8_t pktCmd; + uint8_t pktSeqNum; + uint8_t pktRetryCount; + uint32_t reserved; /* for 64-bit alignmnet */ +} Inic_ControlHeader_t; + +/* ptkType values */ +#define TYPE_INFO 0 +#define TYPE_REQ 1 +#define TYPE_RSP 2 +#define TYPE_ERR 3 + +/* ptkCmd values */ +#define CMD_INIT_INIC 1 +#define CMD_CONFIG_DATA_PATH 2 +#define CMD_EXCHANGE_POOLS 3 +#define CMD_CONFIG_ADDRESSES 4 +#define CMD_CONFIG_LINK 5 +#define CMD_REPORT_STATISTICS 6 +#define CMD_CLEAR_STATISTICS 7 +#define CMD_REPORT_STATUS 8 +#define CMD_RESET 9 +#define CMD_HEARTBEAT 10 + +#define MAC_ADDR_LEN HW_ADDR_LEN + +/* pktCmd CMD_INIT_INIC, pktType TYPE_REQ data format */ +typedef struct Inic_CmdInitInicReq { + uint16_t inicMajorVersion; + uint16_t inicMinorVersion; + uint8_t inicInstance; + uint8_t numDataPaths; + uint16_t numAddressEntries; +} Inic_CmdInitInicReq_t; + +/* pktCmd CMD_INIT_INIC, pktType TYPE_RSP subdata format */ +typedef struct Inic_LanSwitchAttributes { + uint8_t lanSwitchNum; + uint8_t numEnetPorts; + uint16_t defaultVlan; + uint8_t hwMacAddress[MAC_ADDR_LEN]; +} Inic_LanSwitchAttributes_t; + +/* pktCmd CMD_INIT_INIC, pktType TYPE_RSP data format */ +typedef struct Inic_CmdInitInicRsp { + uint16_t inicMajorVersion; + uint16_t inicMinorVersion; + uint8_t numLanSwitches; + uint8_t numDataPaths; + uint16_t numAddressEntries; + uint32_t featuresSupported; + Inic_LanSwitchAttributes_t lanSwitch[1]; +} Inic_CmdInitInicRsp_t; + +/* featuresSupported values */ +#define INIC_FEAT_IPV4_HEADERS 0x00000001 +#define INIC_FEAT_IPV6_HEADERS 0x00000002 +#define INIC_FEAT_IPV4_CSUM_RX 0x00000004 +#define INIC_FEAT_IPV4_CSUM_TX 0x00000008 +#define INIC_FEAT_TCP_CSUM_RX 0x00000010 +#define INIC_FEAT_TCP_CSUM_TX 0x00000020 +#define INIC_FEAT_UDP_CSUM_RX 0x00000040 +#define INIC_FEAT_UDP_CSUM_TX 0x00000080 +#define INIC_FEAT_TCP_SEGMENT 0x00000100 +#define INIC_FEAT_IPV4_IPSEC_OFFLOAD 0x00000200 +#define INIC_FEAT_IPV6_IPSEC_OFFLOAD 0x00000400 +#define INIC_FEAT_FCS_PROPAGATE 0x00000800 +#define INIC_FEAT_PF_KICK 0x00001000 +#define INIC_FEAT_PF_FORCE_ROUTE 0x00002000 +#define INIC_FEAT_CHASH_OFFLOAD 0x00004000 +#define INIC_FEAT_RDMA_IMMED 0x00008000 +#define INIC_FEAT_IGNORE_VLAN 0x00010000 +#define INIC_FEAT_INBOUND_IB_MC 0x00200000 + +/* pktCmd CMD_CONFIG_DATA_PATH subdata format */ +typedef struct Inic_RecvPoolConfig { + uint32_t sizeRecvPoolEntry; + uint32_t numRecvPoolEntries; + uint32_t timeoutBeforeKick; + uint32_t numRecvPoolEntriesBeforeKick; + uint32_t numRecvPoolBytesBeforeKick; + uint32_t freeRecvPoolEntriesPerUpdate; +} Inic_RecvPoolConfig_t; + +/* pktCmd CMD_CONFIG_DATA_PATH data format */ +typedef struct Inic_CmdConfigDataPath { + uint64_t pathIdentifier; + uint8_t dataPath; + uint8_t reserved[3]; + Inic_RecvPoolConfig_t hostRecvPoolConfig; + Inic_RecvPoolConfig_t eiocRecvPoolConfig; +} Inic_CmdConfigDataPath_t; + +/* pktCmd CMD_EXCHANGE_POOLS data format */ +typedef struct Inic_CmdExchangePools { + uint8_t dataPath; + uint8_t reserved[3]; + uint32_t poolRKey; + uint64_t poolAddr; +} Inic_CmdExchangePools_t; + +/* pktCmd CMD_CONFIG_ADDRESSES subdata format */ +typedef struct Inic_AddressOp { + uint16_t index; + uint8_t operation; + uint8_t valid; + uint8_t address[6]; + uint16_t vlan; +} Inic_AddressOp_t; + +/* operation values */ +#define INIC_OP_SET_ENTRY 0x01 +#define INIC_OP_GET_ENTRY 0x02 + +/* pktCmd CMD_CONFIG_ADDRESSES data format */ +typedef struct Inic_CmdConfigAddresses { + uint8_t numAddressOps; + uint8_t lanSwitchNum; + Inic_AddressOp_t listAddressOps[1]; +} Inic_CmdConfigAddresses_t; + +/* CMD_CONFIG_LINK data format */ +typedef struct Inic_CmdConfigLink { + uint8_t cmdFlags; + uint8_t lanSwitchNum; + uint16_t mtuSize; + uint16_t defaultVlan; + uint8_t hwMacAddress[6]; +} Inic_CmdConfigLink_t; + +/* cmdFlags values */ +#define INIC_FLAG_ENABLE_NIC 0x01 +#define INIC_FLAG_DISABLE_NIC 0x02 +#define INIC_FLAG_ENABLE_MCAST_ALL 0x04 +#define INIC_FLAG_DISABLE_MCAST_ALL 0x08 +#define INIC_FLAG_ENABLE_PROMISC 0x10 +#define INIC_FLAG_DISABLE_PROMISC 0x20 +#define INIC_FLAG_SET_MTU 0x40 + +/* pktCmd CMD_REPORT_STATISTICS, pktType TYPE_REQ data format */ +typedef struct Inic_CmdReportStatisticsReq { + uint8_t lanSwitchNum; +} Inic_CmdReportStatisticsReq_t; + +/* pktCmd CMD_REPORT_STATISTICS, pktType TYPE_RSP data format */ +typedef struct Inic_CmdReportStatisticsRsp { + uint8_t lanSwitchNum; + uint8_t reserved[7]; /* for 64-bit alignment */ + uint64_t ifInBroadcastPkts; + uint64_t ifInMulticastPkts; + uint64_t ifInOctets; + uint64_t ifInUcastPkts; + uint64_t ifInNUcastPkts; /* ifInBroadcastPkts + ifInMulticastPkts */ + uint64_t ifInUnderrun; /* (OID_GEN_RCV_NO_BUFFER) */ + uint64_t ifInErrors; /* (OID_GEN_RCV_ERROR) */ + uint64_t ifOutErrors; /* (OID_GEN_XMIT_ERROR) */ + uint64_t ifOutOctets; + uint64_t ifOutUcastPkts; + uint64_t ifOutMulticastPkts; + uint64_t ifOutBroadcastPkts; + uint64_t ifOutNUcastPkts; /* ifOutBroadcastPkts + ifOutMulticastPkts */ + uint64_t ifOutOk; /* ifOutNUcastPkts + ifOutUcastPkts (OID_GEN_XMIT_OK)*/ + uint64_t ifInOk; /* ifInNUcastPkts + ifInUcastPkts (OID_GEN_RCV_OK) */ + uint64_t ifOutUcastBytes; /* (OID_GEN_DIRECTED_BYTES_XMT) */ + uint64_t ifOutMulticastBytes; /* (OID_GEN_MULTICAST_BYTES_XMT) */ + uint64_t ifOutBroadcastBytes; /* (OID_GEN_BROADCAST_BYTES_XMT) */ + uint64_t ifInUcastBytes; /* (OID_GEN_DIRECTED_BYTES_RCV) */ + uint64_t ifInMulticastBytes; /* (OID_GEN_MULTICAST_BYTES_RCV) */ + uint64_t ifInBroadcastBytes; /* (OID_GEN_BROADCAST_BYTES_RCV) */ + uint64_t ethernetStatus; /* OID_GEN_MEDIA_CONNECT_STATUS) */ +} Inic_CmdReportStatisticsRsp_t; + +/* pktCmd CMD_CLEAR_STATISTICS data format */ +typedef struct Inic_CmdClearStatistics { + uint8_t lanSwitchNum; +} Inic_CmdClearStatistics_t; + +/* pktCmd CMD_REPORT_STATUS data format */ +typedef struct Inic_CmdReportStatus { + uint8_t lanSwitchNum; + uint8_t isFatal; + uint8_t reserved[2]; /* for 32-bit alignment */ + uint32_t statusNumber; + uint32_t statusInfo; + uint8_t fileName[32]; + uint8_t routine[32]; + uint32_t lineNum; + uint32_t errorParameter; + uint8_t descText[128]; +} Inic_CmdReportStatus_t; + +/* pktCmd CMD_HEARTBEAT data format */ +typedef struct Inic_CmdHeartbeat { + uint32_t hbInterval; +} Inic_CmdHeartbeat_t; + +#define INIC_STATUS_LINK_UP 1 +#define INIC_STATUS_LINK_DOWN 2 +#define INIC_STATUS_ENET_AGGREGATION_CHANGE 3 +#define INIC_STATUS_EIOC_SHUTDOWN 4 +#define INIC_STATUS_CONTROL_ERROR 5 +#define INIC_STATUS_EIOC_ERROR 6 + +#define INIC_MAX_CONTROLPKTSZ 256 +#define INIC_MAX_CONTROLDATASZ \ + (INIC_MAX_CONTROLPKTSZ - sizeof(Inic_ControlHeader_t)) + +typedef struct Inic_ControlPacket { + Inic_ControlHeader_t hdr; + union { + Inic_CmdInitInicReq_t initInicReq; + Inic_CmdInitInicRsp_t initInicRsp; + Inic_CmdConfigDataPath_t configDataPathReq; + Inic_CmdConfigDataPath_t configDataPathRsp; + Inic_CmdExchangePools_t exchangePoolsReq; + Inic_CmdExchangePools_t exchangePoolsRsp; + Inic_CmdConfigAddresses_t configAddressesReq; + Inic_CmdConfigAddresses_t configAddressesRsp; + Inic_CmdConfigLink_t configLinkReq; + Inic_CmdConfigLink_t configLinkRsp; + Inic_CmdReportStatisticsReq_t reportStatisticsReq; + Inic_CmdReportStatisticsRsp_t reportStatisticsRsp; + Inic_CmdClearStatistics_t clearStatisticsReq; + Inic_CmdClearStatistics_t clearStatisticsRsp; + Inic_CmdReportStatus_t reportStatus; + Inic_CmdHeartbeat_t heartbeatReq; + Inic_CmdHeartbeat_t heartbeatRsp; + char cmdData[INIC_MAX_CONTROLDATASZ]; + } cmd; +} Inic_ControlPacket_t; +/* +typedef struct _mac_addr +{ + uint8_t addr[MAC_ADDR_LEN]; +} PACK_SUFFIX mac_addr_t; +*/ +#include + +#endif /* _VNIC_CONTROLPKT_H_ */ diff --git a/trunk/ulp/qlgcvnic/kernel/vnic_data.c b/trunk/ulp/qlgcvnic/kernel/vnic_data.c new file mode 100644 index 00000000..4f39a643 --- /dev/null +++ b/trunk/ulp/qlgcvnic/kernel/vnic_data.c @@ -0,0 +1,1459 @@ +/* + * Copyright (c) 2007 QLogic Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id$ + */ +#include +#include "vnic_driver.h" + +static void data_postRecvs(Data_t *pData); +static void _data_receivedKick(Io_t *pIo); +static void _data_xmitComplete(Io_t *pIo); +static void data_sendKickMessage(Data_t *pData); +static void _data_kickTimeoutHandler( void *context ); +static BOOLEAN data_allocXmitBuffer(Data_t *pData, + BufferPoolEntry_t **ppBpe, RdmaIo_t **ppRdmaIo, BOOLEAN *pLast); +static void data_checkXmitBuffers(Data_t *pData); + +static +ib_api_status_t +data_rdmaPacket( + Data_t *pData, + BufferPoolEntry_t *pBpe, + RdmaIo_t *pRdmaIo ); +static +BOOLEAN +_data_recv_to_ndis_pkt( + Data_t *pData, + RdmaDest_t *pRdmaDest ); + +static void +_data_allocBuffers( + Data_t *pData, + BOOLEAN initialAllocation ); + +static void +_data_addFreeBuffer( + Data_t *pData, + int index, + RdmaDest_t *pRdmaDest ); + +static uint32_t +_data_incomingRecv( + Data_t *pData ); + +static void +_data_sendFreeRecvBuffers( + Data_t *pData ); + +static uint8_t +_tx_chksum_flags( + IN NDIS_PACKET* const p_packet ); + +static void +_data_return_recv( + IN NDIS_PACKET *p_packet ); + +static void +_data_kickTimer_start( + IN Data_t *pData, + IN uint32_t microseconds ); + +static void +_data_kickTimer_stop( + IN Data_t *pData ); + +#define LOCAL_IO(x) PTR64((x)) + +#define INBOUND_COPY + +#ifdef VNIC_STATISTIC +int64_t recvRef; +#endif /* VNIC_STATISTIC */ + +void +data_construct( + IN Data_t *pData, + IN viport_t *pViport ) +{ + VNIC_ENTER( VNIC_DBG_DATA ); + + RtlZeroMemory( pData, sizeof(*pData) ); + + pData->p_viport = pViport; + pData->p_phy_region = &pViport->p_adapter->ca.region; + InitializeListHead( &pData->recvIos ); + KeInitializeSpinLock( &pData->recvListLock ); + NdisAllocateSpinLock( &pData->recvIosLock ); + NdisAllocateSpinLock( &pData->xmitBufLock ); + cl_timer_construct( &pData->kickTimer ); + + ibqp_construct( &pData->qp, pViport ); + + VNIC_EXIT( VNIC_DBG_DATA ); +} + + +ib_api_status_t +data_init( + IN Data_t *pData, + IN DataConfig_t *p_conf, + IN uint64_t guid ) +{ + ib_api_status_t ib_status; + + VNIC_ENTER( VNIC_DBG_DATA ); + + ASSERT( pData->p_viport != NULL ); + pData->p_conf = p_conf; + + cl_timer_init( &pData->kickTimer, _data_kickTimeoutHandler, pData ); + + ib_status = ibqp_init(&pData->qp, guid, &p_conf->ibConfig ); + if( ib_status != IB_SUCCESS ) + VNIC_TRACE( VNIC_DBG_ERROR, ("data ibqp_init failed\n") ); + + VNIC_EXIT( VNIC_DBG_DATA ); + return ib_status; +} + + +ib_api_status_t +data_connect( + IN Data_t *pData ) +{ + NDIS_STATUS status; + ib_api_status_t ib_status; + XmitPool_t *pXmitPool = &pData->xmitPool; + RecvPool_t *pRecvPool = &pData->recvPool; + RecvIo_t *pRecvIo; + SendIo_t *pSendIo; + RdmaIo_t *pRdmaIo; + RdmaDest_t *pRdmaDest; + uint8_t *pRegionData; + int sz, regionSz; + unsigned int i, j; + + VNIC_ENTER( VNIC_DBG_DATA ); + + pRecvPool->poolSz = pData->p_conf->hostRecvPoolEntries; + pRecvPool->eiocPoolSz = pData->hostPoolParms.numRecvPoolEntries; + + if ( pRecvPool->poolSz > pRecvPool->eiocPoolSz ) + { + pRecvPool->poolSz = pData->hostPoolParms.numRecvPoolEntries; + } + pRecvPool->szFreeBundle = + pData->hostPoolParms.freeRecvPoolEntriesPerUpdate; + pRecvPool->numFreeBufs = 0; + pRecvPool->numPostedBufs = 0; + pRecvPool->nextFullBuf = 0; + pRecvPool->nextFreeBuf = 0; + pRecvPool->kickOnFree = FALSE; + pRecvPool->bufferSz = pData->hostPoolParms.sizeRecvPoolEntry; + + pXmitPool->bufferSz = pData->eiocPoolParms.sizeRecvPoolEntry; + pXmitPool->poolSz = pData->eiocPoolParms.numRecvPoolEntries; + pXmitPool->notifyCount = 0; + pXmitPool->notifyBundle = pData->p_conf->notifyBundle; + pXmitPool->nextXmitPool = 0; + +#if LIMIT_OUTSTANDING_SENDS + pXmitPool->numXmitBufs = pXmitPool->notifyBundle * 2; +#else /* !LIMIT_OUTSTANDING_SENDS */ + pXmitPool->numXmitBufs = pXmitPool->poolSz; +#endif /* LIMIT_OUTSTANDING_SENDS */ + + pXmitPool->nextXmitBuf = 0; + pXmitPool->lastCompBuf = pXmitPool->numXmitBufs - 1; + pXmitPool->kickCount = 0; + pXmitPool->kickByteCount = 0; + pXmitPool->sendKicks = + (BOOLEAN)(( pData->eiocPoolParms.numRecvPoolEntriesBeforeKick != 0 ) + || ( pData->eiocPoolParms.numRecvPoolBytesBeforeKick != 0 )); + pXmitPool->kickBundle = + pData->eiocPoolParms.numRecvPoolEntriesBeforeKick; + pXmitPool->kickByteBundle = + pData->eiocPoolParms.numRecvPoolBytesBeforeKick; + pXmitPool->needBuffers = TRUE; + + sz = sizeof(RdmaDest_t) * pRecvPool->poolSz; + sz += sizeof(RecvIo_t) * pData->p_conf->numRecvs; + sz += sizeof(RdmaIo_t) * pXmitPool->numXmitBufs; + + regionSz = 4 * pData->p_conf->numRecvs; + regionSz += sizeof(BufferPoolEntry_t) * pRecvPool->eiocPoolSz; + regionSz += sizeof(BufferPoolEntry_t) * pXmitPool->poolSz; + sz += regionSz; + + status = NdisAllocateMemoryWithTag( &pData->pLocalStorage, + (UINT)sz, + 'grtS' ); + if ( status != NDIS_STATUS_SUCCESS ) + { + VNIC_TRACE_EXIT( VNIC_DBG_ERROR, + ("Failed allocating %d bytes local storage\n", sz ) ); + ib_status = IB_INSUFFICIENT_MEMORY; + goto err1; + } + + NdisZeroMemory( pData->pLocalStorage, sz ); + pData->localStorageSz = sz; + + pRecvPool->pRecvBufs = (RdmaDest_t *)pData->pLocalStorage; + sz = sizeof(RdmaDest_t) * pRecvPool->poolSz; + pRecvIo = (RecvIo_t *)(pData->pLocalStorage + sz); + sz += sizeof(RecvIo_t) * pData->p_conf->numRecvs; + + pXmitPool->pXmitBufs = (RdmaIo_t *)(pData->pLocalStorage + sz); + sz += sizeof(RdmaIo_t) * pXmitPool->numXmitBufs; + + pRegionData = pData->pLocalStorage + sz; + sz += 4 * pData->p_conf->numRecvs; + + pRecvPool->bufPool = (BufferPoolEntry_t *)(pData->pLocalStorage + sz); + sz += sizeof(BufferPoolEntry_t) * pRecvPool->eiocPoolSz; + pXmitPool->bufPool = (BufferPoolEntry_t *)(pData->pLocalStorage + sz); + + ib_status = ibregion_init( pData->p_viport, &pData->region, + pData->p_viport->p_adapter->ca.hPd, pRegionData, regionSz, + ( IB_AC_LOCAL_WRITE | IB_AC_RDMA_WRITE ) ); + if( ib_status != IB_SUCCESS ) + { + VNIC_TRACE_EXIT( VNIC_DBG_ERROR, ("ib_region_init failed\n") ); + goto err2; + } + + pRdmaIo = &pData->freeBufsIo; + pRdmaIo->io.pViport = pData->p_viport; + pRdmaIo->io.pRoutine = NULL; + pRdmaIo->io.wrq.p_next = NULL; + pRdmaIo->io.wrq.wr_type = WR_RDMA_WRITE; + pRdmaIo->io.wrq.wr_id = PTR64( pRdmaIo ); + pRdmaIo->io.wrq.num_ds = 1; + pRdmaIo->io.wrq.ds_array = pRdmaIo->dsList; + pRdmaIo->dsList[0].lkey = pData->region.lkey; + pRdmaIo->io.wrq.send_opt = IB_SEND_OPT_SIGNALED; + + pSendIo = &pData->kickIo; + pSendIo->io.pViport = pData->p_viport; + pSendIo->io.pRoutine = NULL; + pSendIo->io.wrq.p_next = NULL; + pSendIo->io.wrq.wr_type = WR_SEND; + pSendIo->io.wrq.wr_id = PTR64( pSendIo ); + pSendIo->io.wrq.num_ds = 1; + pSendIo->io.wrq.ds_array = &pSendIo->dsList; + + pSendIo->io.wrq.send_opt = IB_SEND_OPT_SIGNALED; + + pSendIo->dsList.length = 0; + pSendIo->dsList.vaddr = PTR64( pRegionData ); + pSendIo->dsList.lkey = pData->region.lkey; + + for ( i = 0; i < pData->p_conf->numRecvs; i++ ) + { + pRecvIo[i].io.pViport = pData->p_viport; + pRecvIo[i].io.pRoutine = _data_receivedKick; + pRecvIo[i].io.r_wrq.wr_id = PTR64( &pRecvIo[i].io ); + pRecvIo[i].io.r_wrq.p_next = NULL; + pRecvIo[i].io.r_wrq.num_ds = 1; + pRecvIo[i].io.r_wrq.ds_array = &pRecvIo[i].dsList; + pRecvIo[i].dsList.length = 4; + pRecvIo[i].dsList.vaddr = PTR64( pRegionData ); + pRecvIo[i].dsList.lkey = pData->region.lkey; + + InitializeListHead( &pRecvIo[i].io.listPtrs ); + ExInterlockedInsertTailList( &pData->recvIos, &pRecvIo[i].io.listPtrs, &pData->recvListLock ); + /* Do not need to move pointer since the receive info + * is not read. Note, we could reduce the amount + * of memory allocated and the size of the region. + * pRegionData += 4; + * */ + } + + sz = pRecvPool->poolSz * pRecvPool->bufferSz; + status = NdisAllocateMemoryWithTag(&pData->p_recv_bufs, + sz, 'fubr'); + if( status != NDIS_STATUS_SUCCESS ) + { + VNIC_TRACE_EXIT( VNIC_DBG_ERROR, + ("Allocate recv buffers failed\n")); + ib_status = IB_INSUFFICIENT_MEMORY; + goto err3; + } + NdisZeroMemory( pData->p_recv_bufs, sz ); + + pData->recv_bufs_sz = sz; + + ib_status = ibregion_init( pData->p_viport, &pData->rbuf_region, + pData->p_viport->p_adapter->ca.hPd, pData->p_recv_bufs, sz, + (IB_AC_LOCAL_WRITE | IB_AC_RDMA_WRITE) ); + if( ib_status != IB_SUCCESS ) + { + goto err4; + } + + NdisAllocatePacketPool( &status, + &pData->h_recv_pkt_pool, + pRecvPool->poolSz, + PROTOCOL_RESERVED_SIZE_IN_PACKET ); + + if( status != NDIS_STATUS_SUCCESS ) + { + VNIC_TRACE_EXIT( VNIC_DBG_ERROR, + ("Allocate packet pool failed status %#x\n", status )); + ib_status = IB_INSUFFICIENT_MEMORY; + goto err5; + } + + NdisAllocateBufferPool( + &status, &pData->h_recv_buf_pool, pRecvPool->poolSz ); + + if( status != NDIS_STATUS_SUCCESS ) + { + VNIC_TRACE_EXIT( VNIC_DBG_ERROR, + ("Allocate packet pool failed status %#x\n", status )); + ib_status = IB_INSUFFICIENT_MEMORY; + goto err6; + } + pData->recvPool.recv_pkt_array = + cl_zalloc( sizeof(NDIS_PACKET*)* pRecvPool->poolSz ); + if( !pData->recvPool.recv_pkt_array ) + { + VNIC_TRACE_EXIT( VNIC_DBG_ERROR, + ("Allocate packet array failed\n" ) ); + ib_status = IB_INSUFFICIENT_MEMORY; + goto err7; + } + + InitializeListHead( &pRecvPool->availRecvBufs ); + + for ( i = 0; i < pRecvPool->poolSz; i++ ) + { + pRdmaDest = &pRecvPool->pRecvBufs[i]; + pRdmaDest->p_viport = pData->p_viport; + pRdmaDest->data = pData->p_recv_bufs + (i * pRecvPool->bufferSz ); + pRdmaDest->region = pData->rbuf_region; + InsertTailList( &pRecvPool->availRecvBufs, &pRdmaDest->listPtrs ); + } + + for ( i = 0; i < pXmitPool->numXmitBufs; i++ ) + { + pRdmaIo = &pXmitPool->pXmitBufs[i]; + pRdmaIo->index = (uint16_t)i; + pRdmaIo->io.pViport = pData->p_viport; + pRdmaIo->io.pRoutine = _data_xmitComplete; + pRdmaIo->io.wrq.p_next = NULL; + pRdmaIo->io.wrq.wr_type = WR_RDMA_WRITE; + pRdmaIo->io.wrq.wr_id = PTR64(pRdmaIo); + pRdmaIo->io.wrq.num_ds = MAX_NUM_SGE; // will set actual number when transmit + pRdmaIo->io.wrq.ds_array = pRdmaIo->dsList; + pRdmaIo->p_trailer = (ViportTrailer_t *)&pRdmaIo->data[0]; + for( j = 0; j < MAX_NUM_SGE; j++ ) + { + pRdmaIo->dsList[j].lkey = pData->p_phy_region->lkey; + } + } + + pXmitPool->rdmaRKey = pData->region.rkey; + pXmitPool->rdmaAddr = PTR64( pXmitPool->bufPool ); + + data_postRecvs( pData ); + + ib_status = ibqp_connect( &pData->qp ); + if( ib_status != IB_SUCCESS ) + { + VNIC_TRACE( VNIC_DBG_ERROR, ("ibqp_connect returned %s\n", + pData->p_viport->p_adapter->ifc.get_err_str( ib_status )) ); +err7: + NdisFreeBufferPool( pData->h_recv_buf_pool ); + pData->h_recv_buf_pool = NULL; +err6: + NdisFreePacketPool( pData->h_recv_pkt_pool ); + pData->h_recv_pkt_pool = NULL; +err5: + ibregion_cleanup( pData->p_viport, &pData->rbuf_region ); +err4: + NdisFreeMemory( pData->p_recv_bufs, pData->recv_bufs_sz, 0 ); + pData->p_recv_bufs = NULL; +err3: + ibregion_cleanup(pData->p_viport, &pData->region ); +err2: + NdisFreeMemory( pData->pLocalStorage, pData->localStorageSz, 0 ); + pData->pLocalStorage = NULL; +err1: + pRecvPool->poolSz = 0; + } + + VNIC_EXIT( VNIC_DBG_DATA ); + return ib_status; +} + + +ib_api_status_t +data_connected( + IN Data_t *pData ) +{ + VNIC_ENTER( VNIC_DBG_DATA ); + + pData->freeBufsIo.io.wrq.remote_ops.rkey = + pData->recvPool.eiocRdmaRkey; + + _data_allocBuffers(pData, TRUE); + _data_sendFreeRecvBuffers(pData); + + if( pData->p_viport->errored ) + { + return IB_ERROR; + } + + pData->connected = TRUE; + + VNIC_EXIT( VNIC_DBG_DATA ); + return IB_SUCCESS; +} + +void +data_disconnect( + IN Data_t *pData ) +{ + RecvPool_t *pRecvPool = &pData->recvPool; + viport_t *p_viport = pData->p_viport; + NDIS_PACKET *p_packet; + NDIS_BUFFER *p_buf; + unsigned int i; + + VNIC_ENTER( VNIC_DBG_DATA ); + + _data_kickTimer_stop ( pData ); + + pData->connected = FALSE; + + ibqp_detach( &pData->qp ); + + ibregion_cleanup( p_viport, &pData->rbuf_region ); + ibregion_cleanup( p_viport, &pData->region ); + + for ( i = 0; i < pRecvPool->poolSz; i++ ) + { + p_packet = pRecvPool->pRecvBufs[i].p_packet; + if ( p_packet != NULL ) + { + pRecvPool->pRecvBufs[i].p_packet = NULL; + NdisUnchainBufferAtFront( p_packet, &p_buf ); + if( p_buf ) + { + /* Return the NDIS packet and NDIS buffer to their pools. */ + NdisFreeBuffer( p_buf ); + } + NdisFreePacket( p_packet ); + } + } + + VNIC_EXIT( VNIC_DBG_DATA ); + return; +} + +BOOLEAN +data_xmitPacket( + IN Data_t *pData, + IN NDIS_PACKET* const p_packet ) +{ + XmitPool_t *p_xmitPool; + RdmaIo_t *pRdmaIo; + BufferPoolEntry_t *pBpe; + BOOLEAN last; + uint8_t *p_buf; + uint32_t buf_len; + uint32_t pkt_size; + NDIS_BUFFER *p_buf_desc; + eth_hdr_t* p_eth_hdr; + int pad; + SCATTER_GATHER_LIST *p_sgl; + uint32_t i; + PHYSICAL_ADDRESS phy_addr; + NDIS_PACKET_8021Q_INFO vlanInfo; + net16_t pri_vlan = 0; + + VNIC_ENTER( VNIC_DBG_DATA ); + + p_sgl = NDIS_PER_PACKET_INFO_FROM_PACKET( p_packet, + ScatterGatherListPacketInfo ); + if ( p_sgl == NULL ) + { + return FALSE; + } + + NdisGetFirstBufferFromPacketSafe( p_packet, + &p_buf_desc, + &p_buf, + &buf_len, + &pkt_size, + NormalPagePriority ); + + if( pkt_size > pData->xmitPool.bufferSz ) + { + VNIC_TRACE_EXIT( VNIC_DBG_ERROR, + ("Outbound packet too large, size = %d\n", pkt_size ) ); + return FALSE; + } + + if ( p_sgl->NumberOfElements > (ULONG)MAX_NUM_SGE - 1 ) + { + VNIC_TRACE( VNIC_DBG_DATA, + (" Xmit packet exceeded SGE limit - %d\n", + p_sgl->NumberOfElements ) ); + return FALSE; + } + + vlanInfo.Value = NDIS_PER_PACKET_INFO_FROM_PACKET( p_packet, Ieee8021QInfo ); + p_eth_hdr = (eth_hdr_t *)p_buf; + + if( vlanInfo.Value ) /* there is VLAN_ID specified the packet */ + { + if( vlanInfo.TagHeader.VlanId != 0 ) + { + /* packet vlanId does not match */ + if( pData->p_viport->p_adapter->vlan_info && + ( pData->p_viport->p_adapter->vlan_info & 0x00000fff ) != vlanInfo.TagHeader.VlanId ) + { + return FALSE; + } + pri_vlan = (uint16_t)vlanInfo.TagHeader.VlanId; + pri_vlan |= (uint16_t)( vlanInfo.TagHeader.UserPriority << 13 ); + } + else if( pData->p_viport->p_adapter->vlan_info ) + { + pri_vlan = (uint16_t)( pData->p_viport->p_adapter->vlan_info ); + } + } + else /* no VLAN_ID info in a packet */ + { + if( pData->p_viport->p_adapter->vlan_info ) + { + pri_vlan = (uint16_t)( pData->p_viport->p_adapter->vlan_info ); + } + } + + if( !data_allocXmitBuffer( pData, &pBpe, &pRdmaIo, &last ) ) + { + return FALSE; + } + + pRdmaIo->p_packet = p_packet; + pRdmaIo->packet_sz = pkt_size; + + pRdmaIo->len = (uint32_t)ROUNDUPP2( + max(MIN_PACKET_LEN, pRdmaIo->packet_sz), VIPORT_TRAILER_ALIGNMENT ); + pad = pRdmaIo->len - pRdmaIo->packet_sz; + + pRdmaIo->p_trailer = (ViportTrailer_t *)&pRdmaIo->data[pad]; + + cl_memclr( pRdmaIo->data, pad + sizeof( ViportTrailer_t ) ); + cl_memcpy( pRdmaIo->p_trailer->destMacAddr, p_eth_hdr->dst.addr, MAC_ADDR_LEN ); + + pRdmaIo->p_trailer->dataLength = + cl_hton16( (uint16_t)max( MIN_PACKET_LEN, pRdmaIo->packet_sz ) ); + + if( pri_vlan ) + { + /* if tagged frame */ + if( *(uint16_t *)(p_buf + 12 ) == ETH_PROT_VLAN_TAG ) + { + /* strip vlan tag from header */ + RtlMoveMemory( p_buf + 4, p_buf, 12 ); + /* adjust data length */ + pRdmaIo->p_trailer->dataLength = + cl_hton16( (uint16_t)max( MIN_PACKET_LEN, pRdmaIo->packet_sz ) - 4 ); + } + pRdmaIo->p_trailer->vLan = cl_hton16( pri_vlan ); + pRdmaIo->p_trailer->pktFlags |= PF_VLAN_INSERT; + } + + for( i=0; i < p_sgl->NumberOfElements; i++ ) + { + pRdmaIo->dsList[i].vaddr = p_sgl->Elements[i].Address.QuadPart; + pRdmaIo->dsList[i].length = p_sgl->Elements[i].Length; + } + if( viport_canTxCsum( pData->p_viport ) && + pData->p_viport->p_adapter->params.UseTxCsum ) + { + pRdmaIo->p_trailer->txChksumFlags = _tx_chksum_flags( p_packet ); + } + else + { + pRdmaIo->p_trailer->txChksumFlags = 0; + } + pRdmaIo->p_trailer->connectionHashAndValid = CHV_VALID; + + if( last ) + pRdmaIo->p_trailer->pktFlags |= PF_KICK; + + /* fill last data segment with trailer and pad */ + phy_addr = MmGetPhysicalAddress( pRdmaIo->data ); + + pRdmaIo->dsList[p_sgl->NumberOfElements].vaddr = phy_addr.QuadPart; + pRdmaIo->dsList[p_sgl->NumberOfElements].length = pRdmaIo->len - + pRdmaIo->packet_sz + + sizeof( ViportTrailer_t ); + + pRdmaIo->io.wrq.num_ds =p_sgl->NumberOfElements + 1; + + if( data_rdmaPacket( pData, pBpe, pRdmaIo ) != IB_SUCCESS ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("RDMA WRITE Failed\n")); + return FALSE; + } + p_xmitPool = &pData->xmitPool; + if( p_xmitPool->sendKicks ) + { + /* EIOC needs kicks to inform it of sent packets */ + + p_xmitPool->kickCount++; + p_xmitPool->kickByteCount += pRdmaIo->packet_sz; + if( ( p_xmitPool->kickCount >= p_xmitPool->kickBundle ) + || ( p_xmitPool->kickByteCount >= p_xmitPool->kickByteBundle ) ) + { + data_sendKickMessage( pData ); + } + else if( p_xmitPool->kickCount == 1 ) + { + _data_kickTimer_start( pData, pData->eiocPoolParms.timeoutBeforeKick ); + } + } + return TRUE; +} + +static uint8_t +_tx_chksum_flags( + IN NDIS_PACKET* const p_packet ) + +{ + NDIS_TCP_IP_CHECKSUM_PACKET_INFO *p_packet_info; + ULONG packet_info; + uint8_t txChksumFlags = 0; + + if( NDIS_PROTOCOL_ID_TCP_IP == NDIS_GET_PACKET_PROTOCOL_TYPE(p_packet) ) + { + packet_info = PtrToUlong( NDIS_PER_PACKET_INFO_FROM_PACKET( p_packet, TcpIpChecksumPacketInfo)); + p_packet_info = ( NDIS_TCP_IP_CHECKSUM_PACKET_INFO *)&packet_info; + + if( p_packet_info ) + { + if( p_packet_info->Transmit.NdisPacketChecksumV4 ) + { + txChksumFlags = TX_CHKSUM_FLAGS_CHECKSUM_V4 + | ( p_packet_info->Transmit.NdisPacketIpChecksum ? TX_CHKSUM_FLAGS_IP_CHECKSUM: 0 ) + | ( p_packet_info->Transmit.NdisPacketTcpChecksum ? TX_CHKSUM_FLAGS_TCP_CHECKSUM: 0 ) + | ( p_packet_info->Transmit.NdisPacketUdpChecksum ? TX_CHKSUM_FLAGS_UDP_CHECKSUM: 0 ); + } + else if( p_packet_info->Transmit.NdisPacketChecksumV6 ) + { + txChksumFlags = TX_CHKSUM_FLAGS_CHECKSUM_V6 + | ( p_packet_info->Transmit.NdisPacketIpChecksum ? TX_CHKSUM_FLAGS_IP_CHECKSUM: 0 ) + | ( p_packet_info->Transmit.NdisPacketTcpChecksum ? TX_CHKSUM_FLAGS_TCP_CHECKSUM: 0 ) + | ( p_packet_info->Transmit.NdisPacketUdpChecksum ? TX_CHKSUM_FLAGS_UDP_CHECKSUM: 0 ); + } + } + } + + VNIC_TRACE( VNIC_DBG_DATA , + ("txChksumFlags = %#x: V4 %c, V6 %c, IP %c, TCP %c, UDP %c\n", + txChksumFlags, + ((txChksumFlags & TX_CHKSUM_FLAGS_CHECKSUM_V4 )? '+': '-'), + ((txChksumFlags & TX_CHKSUM_FLAGS_CHECKSUM_V6 )? '+': '-'), + ((txChksumFlags & TX_CHKSUM_FLAGS_IP_CHECKSUM )? '+': '-'), + ((txChksumFlags & TX_CHKSUM_FLAGS_TCP_CHECKSUM )? '+': '-'), + ((txChksumFlags & TX_CHKSUM_FLAGS_UDP_CHECKSUM )? '+': '-') )); + + return txChksumFlags; +} + +static void +data_postRecvs( + IN Data_t *pData ) +{ + RecvIo_t *pRecvIo; + LIST_ENTRY *p_list_entry; + ib_api_status_t ib_status; + + VNIC_ENTER ( VNIC_DBG_DATA ); + + if( pData->p_viport->errored ) + return; + + while( ( p_list_entry = ExInterlockedRemoveHeadList( &pData->recvIos, &pData->recvListLock ) ) != NULL ) + { + pRecvIo = (RecvIo_t *)p_list_entry; + + ib_status = ibqp_postRecv( &pData->qp, &pRecvIo->io ); + if( ib_status != IB_SUCCESS ) + { + VNIC_TRACE_EXIT( VNIC_DBG_ERROR, ("ibqp_postRecv returned %s\n", + pData->p_viport->p_adapter->ifc.get_err_str( ib_status )) ); + viport_failure( pData->p_viport ); + return; + } + } + + VNIC_EXIT( VNIC_DBG_DATA ); + return; +} + +static void +_data_receivedKick( + IN Io_t *pIo ) +{ + + uint32_t num_pkts = 0; + + VNIC_ENTER( VNIC_DBG_DATA ); + + NdisAcquireSpinLock( &pIo->pViport->data.recvIosLock ); + +#ifdef VNIC_STATISTIC + recvRef = cl_get_tick_count(); +#endif /* VNIC_STATISTIC */ + + ExInterlockedInsertTailList( &pIo->pViport->data.recvIos, + &pIo->listPtrs, + &pIo->pViport->data.recvListLock ); + + data_postRecvs( &pIo->pViport->data ); + +#ifdef VNIC_STATISTIC + pIo->pViport->data.statistics.kickRecvs++; +#endif /* VNIC_STATISTIC */ + + data_checkXmitBuffers( &pIo->pViport->data ); + + num_pkts = _data_incomingRecv( &pIo->pViport->data ); + + NdisReleaseSpinLock(&pIo->pViport->data.recvIosLock ); + + if( num_pkts ) + { + viport_recvPacket( pIo->pViport, + pIo->pViport->data.recvPool.recv_pkt_array, + num_pkts ); + + pIo->pViport->stats.ifInOk += num_pkts; + } + + VNIC_EXIT( VNIC_DBG_DATA ); + return; +} + +static void +_data_xmitComplete( + IN Io_t *pIo ) +{ + + Data_t *pData; + XmitPool_t *p_xmitPool; + NDIS_PACKET *p_packet; + NDIS_STATUS ndis_status; + uint32_t io_index; + + VNIC_ENTER( VNIC_DBG_DATA ); + + NdisAcquireSpinLock( &pIo->pViport->data.xmitBufLock ); + + io_index = ((RdmaIo_t *)pIo)->index; + pData = &pIo->pViport->data; + p_xmitPool = &pData->xmitPool; + + while ( p_xmitPool->lastCompBuf != io_index ) + { + INC(p_xmitPool->lastCompBuf, 1, p_xmitPool->numXmitBufs); + + p_packet = p_xmitPool->pXmitBufs[p_xmitPool->lastCompBuf].p_packet; + + p_xmitPool->pXmitBufs[p_xmitPool->lastCompBuf].p_packet = NULL; + + if( p_packet != NULL ) + { + if( pIo->wc_status != IB_WCS_SUCCESS ) + { + ndis_status = NDIS_STATUS_FAILURE; + pIo->pViport->stats.ifOutErrors++; + pIo->wc_status = IB_WCS_SUCCESS; + } + else + { + ndis_status = NDIS_STATUS_SUCCESS; + pIo->pViport->stats.ifOutOk++; + } + NDIS_SET_PACKET_STATUS( p_packet, ndis_status ); + NdisMSendComplete( pIo->pViport->p_adapter->h_handle, + p_packet, ndis_status ); + } + } + NdisReleaseSpinLock( &pData->xmitBufLock ); + + if( !pData->p_viport->errored ) + { + data_checkXmitBuffers( pData ); + } + VNIC_EXIT( VNIC_DBG_DATA ); + return; +} + +static void +data_sendKickMessage( + IN Data_t *pData ) +{ + XmitPool_t *pPool = &pData->xmitPool; + + VNIC_ENTER( VNIC_DBG_DATA ); + + /* stop timer for BundleTimeout */ + _data_kickTimer_stop( pData ); + + pPool->kickCount = 0; + pPool->kickByteCount = 0; + + /* TBD: Keep track of when kick is outstanding, and + * don't reuse until complete + */ + if ( ibqp_postSend( &pData->qp, &pData->kickIo.io ) != IB_SUCCESS ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("Unable to send kick to EIOC\n") ); + viport_failure( pData->p_viport ); + } + + VNIC_EXIT( VNIC_DBG_DATA ); +} + +static void +_data_kickTimeoutHandler( void * context ) +{ + Data_t* pData = (Data_t *)context; + + VNIC_ENTER( VNIC_DBG_DATA ); + + InterlockedExchange( &pData->kickTimerOn, FALSE ); + data_sendKickMessage( pData ); + + VNIC_EXIT( VNIC_DBG_DATA ); + + return; +} + +static BOOLEAN +data_allocXmitBuffer( + IN Data_t *pData, + OUT BufferPoolEntry_t **ppBpe, + OUT RdmaIo_t **ppRdmaIo, + OUT BOOLEAN *pLast ) +{ + XmitPool_t *p_xmitPool; + + VNIC_ENTER( VNIC_DBG_DATA ); + + NdisAcquireSpinLock( &pData->xmitBufLock ); + + p_xmitPool = &pData->xmitPool; + *pLast = FALSE; + *ppRdmaIo = &p_xmitPool->pXmitBufs[p_xmitPool->nextXmitBuf]; + *ppBpe = &p_xmitPool->bufPool[p_xmitPool->nextXmitPool]; + + if ( (*ppBpe)->valid && p_xmitPool->nextXmitBuf != p_xmitPool->lastCompBuf ) + { + INC(p_xmitPool->nextXmitBuf, 1, p_xmitPool->numXmitBufs); + INC(p_xmitPool->nextXmitPool, 1, p_xmitPool->poolSz); + + if ( !p_xmitPool->bufPool[p_xmitPool->nextXmitPool].valid ) + { + VNIC_TRACE( VNIC_DBG_DATA, + ("Just used the last EIOU receive buffer\n") ); + + *pLast = TRUE; + p_xmitPool->needBuffers = TRUE; + viport_stopXmit( pData->p_viport ); +#ifdef VNIC_STATISTIC + pData->statistics.kickReqs++; +#endif /* VNIC_STATISTIC */ + } + else if ( p_xmitPool->nextXmitBuf == p_xmitPool->lastCompBuf ) + { + VNIC_TRACE( VNIC_DBG_DATA, + ("Just used our last xmit buffer\n") ); + + p_xmitPool->needBuffers = TRUE; + viport_stopXmit( pData->p_viport ); + } + + (*ppBpe)->valid = 0; + + NdisReleaseSpinLock( &pData->xmitBufLock ); + return TRUE; + } + else + { +#ifdef VNIC_STATISTIC + pData->statistics.noXmitBufs++; +#endif /* VNIC_STATISTIC */ + + VNIC_TRACE( VNIC_DBG_ERROR, + ("Out of xmit buffers\n") ); + + viport_stopXmit( pData->p_viport ); + + NdisReleaseSpinLock( &pData->xmitBufLock ); + return FALSE; + } +} + +static void +data_checkXmitBuffers( + IN Data_t *pData ) +{ + VNIC_ENTER( VNIC_DBG_DATA ); + + NdisAcquireSpinLock( &pData->xmitBufLock ); + + if ( pData->xmitPool.needBuffers + && pData->xmitPool.bufPool[pData->xmitPool.nextXmitPool].valid + && pData->xmitPool.nextXmitBuf != pData->xmitPool.lastCompBuf ) + { + pData->xmitPool.needBuffers = FALSE; + viport_restartXmit( pData->p_viport ); + + VNIC_TRACE( VNIC_DBG_DATA, + ("There are free xmit buffers\n") ); + } + + NdisReleaseSpinLock( &pData->xmitBufLock ); + + VNIC_EXIT( VNIC_DBG_DATA ); + return; +} + +static +ib_api_status_t +data_rdmaPacket( + IN Data_t *pData, + IN BufferPoolEntry_t *pBpe, + IN RdmaIo_t *pRdmaIo ) +{ + ib_send_wr_t *pWrq; + uint64_t remote_addr; + + VNIC_ENTER( VNIC_DBG_DATA ); + + pWrq = &pRdmaIo->io.wrq; + + remote_addr = ntoh64( pBpe->remoteAddr ); + remote_addr += pData->xmitPool.bufferSz; + remote_addr -= ( pRdmaIo->len + sizeof(ViportTrailer_t) ); + + pWrq->remote_ops.vaddr = remote_addr; + pWrq->remote_ops.rkey = pBpe->rKey; + + pData->xmitPool.notifyCount++; + + if( pData->xmitPool.notifyCount >= pData->xmitPool.notifyBundle ) + { + pData->xmitPool.notifyCount = 0; + pWrq->send_opt = IB_SEND_OPT_SIGNALED; + } + else + { + pWrq->send_opt &= ~IB_SEND_OPT_SIGNALED; + } + pWrq->send_opt = IB_SEND_OPT_SIGNALED; + + if( pData->p_viport->featuresSupported & INIC_FEAT_RDMA_IMMED ) + { + pWrq->send_opt |= IB_SEND_OPT_IMMEDIATE; + pWrq->immediate_data = 0; + } + + if( ibqp_postSend( &pData->qp, &pRdmaIo->io ) != IB_SUCCESS ) + { + VNIC_TRACE(VNIC_DBG_ERROR, + ("Failed sending data to EIOC\n") ); + return IB_ERROR; + } +#ifdef VNIC_STATISTIC + pData->statistics.xmitNum++; +#endif /* VNIC_STATISTIC */ + + VNIC_EXIT( VNIC_DBG_DATA ); + return IB_SUCCESS; +} + +static BOOLEAN +_data_recv_to_ndis_pkt( + IN Data_t *pData, + IN RdmaDest_t *pRdmaDest ) +{ + struct ViportTrailer *pTrailer; + NDIS_PACKET *p_packet; + NDIS_STATUS ndis_status; + int start; + unsigned int len; + NDIS_TCP_IP_CHECKSUM_PACKET_INFO packet_info; + NDIS_PACKET_8021Q_INFO vlan_info; + uint16_t vlanId; + uint8_t rxChksumFlags; + + VNIC_ENTER( VNIC_DBG_DATA ); + + pTrailer = pRdmaDest->pTrailer; + p_packet = pRdmaDest->p_packet; + + start = (int)data_offset(pData, pTrailer); + len = data_len(pData, pTrailer); + + NdisAllocateBuffer( &ndis_status, + &pRdmaDest->p_buf, + pData->h_recv_buf_pool, + pRdmaDest->data + start, + len ); + + if ( ndis_status != NDIS_STATUS_SUCCESS ) + { + VNIC_TRACE_EXIT( VNIC_DBG_ERROR, + ( "NdisAllocateBuffer failed %#x\n", ndis_status ) ); + return FALSE; + } + + NdisChainBufferAtFront( p_packet, pRdmaDest->p_buf ); + pRdmaDest->buf_sz = len; + + if ( pTrailer->pktFlags & PF_VLAN_INSERT && + !( pData->p_viport->featuresSupported & INIC_FEAT_IGNORE_VLAN ) ) + { + /* handle VLAN tag insertion */ + vlan_info.Value = NDIS_PER_PACKET_INFO_FROM_PACKET( p_packet, Ieee8021QInfo ); + vlanId = cl_ntoh16( pTrailer->vLan ); + + if( !( vlanId & 0xfff ) || + ( ( (vlanId & 0xfff ) != 0 ) && + (vlanId & 0xfff ) == ((uint16_t)pData->p_viport->p_adapter->vlan_info & 0xfff ) )) + { + if( pTrailer->pktFlags & PF_PVID_OVERRIDDEN ) + { + vlan_info.TagHeader.VlanId = 0; + } + else + { + vlan_info.TagHeader.VlanId = vlanId & 0xfff; + } + vlan_info.TagHeader.UserPriority = vlanId & 0xe000; + vlan_info.TagHeader.CanonicalFormatId = 0; + vlan_info.TagHeader.Reserved = 0; + NDIS_PER_PACKET_INFO_FROM_PACKET( p_packet, Ieee8021QInfo ) = vlan_info.Value; + } + } + + if( viport_canRxCsum( pData->p_viport ) && + pData->p_viport->p_adapter->params.UseRxCsum ) + { + rxChksumFlags = pTrailer->rxChksumFlags; + + VNIC_TRACE( VNIC_DBG_DATA, + ("rxChksumFlags = %#x, LOOP = %c, IP = %c, TCP = %c, UDP = %c\n", + rxChksumFlags, + (rxChksumFlags & RX_CHKSUM_FLAGS_LOOPBACK)? 'Y': 'N', + (rxChksumFlags & RX_CHKSUM_FLAGS_IP_CHECKSUM_SUCCEEDED)? 'Y': + (rxChksumFlags & RX_CHKSUM_FLAGS_IP_CHECKSUM_FAILED)? 'N': '-', + (rxChksumFlags & RX_CHKSUM_FLAGS_TCP_CHECKSUM_SUCCEEDED)? 'Y': + (rxChksumFlags & RX_CHKSUM_FLAGS_TCP_CHECKSUM_FAILED)? 'N': '-', + (rxChksumFlags & RX_CHKSUM_FLAGS_UDP_CHECKSUM_SUCCEEDED)? 'Y': + (rxChksumFlags & RX_CHKSUM_FLAGS_UDP_CHECKSUM_FAILED)? 'N': '-') ); + + packet_info.Value = 0; + + if( rxChksumFlags & RX_CHKSUM_FLAGS_IP_CHECKSUM_SUCCEEDED ) + packet_info.Receive.NdisPacketIpChecksumSucceeded = TRUE; + else if( rxChksumFlags & RX_CHKSUM_FLAGS_IP_CHECKSUM_FAILED ) + packet_info.Receive.NdisPacketIpChecksumFailed = TRUE; + + if( rxChksumFlags & RX_CHKSUM_FLAGS_TCP_CHECKSUM_SUCCEEDED ) + packet_info.Receive.NdisPacketTcpChecksumSucceeded = TRUE; + else if( rxChksumFlags & RX_CHKSUM_FLAGS_TCP_CHECKSUM_FAILED ) + packet_info.Receive.NdisPacketTcpChecksumFailed = TRUE; + + if( rxChksumFlags & RX_CHKSUM_FLAGS_TCP_CHECKSUM_SUCCEEDED ) + packet_info.Receive.NdisPacketUdpChecksumSucceeded = TRUE; + else if( rxChksumFlags & RX_CHKSUM_FLAGS_TCP_CHECKSUM_FAILED ) + packet_info.Receive.NdisPacketUdpChecksumFailed = TRUE; + + NDIS_PER_PACKET_INFO_FROM_PACKET( p_packet, TcpIpChecksumPacketInfo )= + (void *)(uintn_t)packet_info.Value; + } + + NDIS_SET_PACKET_STATUS( p_packet, NDIS_STATUS_SUCCESS ); + NDIS_SET_PACKET_HEADER_SIZE( p_packet, sizeof(eth_hdr_t) ); + VNIC_RECV_FROM_PACKET( p_packet ) = pRdmaDest; + + VNIC_EXIT( VNIC_DBG_DATA ); + return TRUE; +} + +/* NOTE: This routine is not reentrant */ +static void +_data_allocBuffers( + IN Data_t *pData, + IN BOOLEAN initialAllocation ) +{ + NDIS_STATUS ndis_status; + RecvPool_t *p_recvPool = &pData->recvPool; + RdmaDest_t *pRdmaDest; + LIST_ENTRY *p_list_entry; + int index; + + VNIC_ENTER( VNIC_DBG_DATA ); + + index = ADD(p_recvPool->nextFreeBuf, p_recvPool->numFreeBufs, p_recvPool->eiocPoolSz); + + while ( !IsListEmpty( &p_recvPool->availRecvBufs ) ) + { + p_list_entry = RemoveHeadList( &p_recvPool->availRecvBufs ); + pRdmaDest = (RdmaDest_t*)p_list_entry; + + if( initialAllocation ) + { + pRdmaDest->buf_sz = p_recvPool->bufferSz; + pRdmaDest->pTrailer = + (struct ViportTrailer*)(pRdmaDest->data + pRdmaDest->buf_sz + - sizeof(struct ViportTrailer)); + pRdmaDest->pTrailer->connectionHashAndValid = 0; + + NdisAllocatePacket( &ndis_status, + &pRdmaDest->p_packet, + pData->h_recv_pkt_pool ); + + if ( ndis_status != NDIS_STATUS_SUCCESS ) + { + VNIC_TRACE_EXIT( VNIC_DBG_ERROR, + ( "NdisAllocatePacket failed %#x\n", ndis_status ) ); + return; + } + } + + _data_addFreeBuffer( pData, index, pRdmaDest ); + index = NEXT(index,p_recvPool->eiocPoolSz); + } + + VNIC_EXIT( VNIC_DBG_DATA ); + return; +} + +static void +_data_addFreeBuffer( + IN Data_t *pData, + IN int index, + IN RdmaDest_t *pRdmaDest ) +{ + RecvPool_t *p_recvPool = &pData->recvPool; + BufferPoolEntry_t *pBpe; + + pRdmaDest->pTrailer->connectionHashAndValid = 0; + pBpe = &p_recvPool->bufPool[index]; + + pBpe->rKey = pRdmaDest->region.rkey; + pBpe->remoteAddr = hton64( PTR64( pRdmaDest->data ) ); + pBpe->valid = (uint32_t)(pRdmaDest - &p_recvPool->pRecvBufs[0]) + 1; + ++p_recvPool->numFreeBufs; + + return; +} + +static uint32_t +_data_incomingRecv( + IN Data_t *pData ) +{ + RecvPool_t *p_recvPool = &pData->recvPool; + RdmaDest_t *pRdmaDest; + ViportTrailer_t *pTrailer; + BufferPoolEntry_t *pBpe; + uint32_t idx = 0; + BOOLEAN status = FALSE; + + VNIC_ENTER( VNIC_DBG_DATA ); + + while( !status ) + { + if ( p_recvPool->nextFullBuf == p_recvPool->nextFreeBuf ) + return idx; + + pBpe = &p_recvPool->bufPool[p_recvPool->nextFullBuf]; + + CL_ASSERT(pBpe->valid != 0 ); + + pRdmaDest = &p_recvPool->pRecvBufs[pBpe->valid - 1]; + pTrailer = pRdmaDest->pTrailer; + + if ( ( pTrailer != NULL ) && + ( pTrailer->connectionHashAndValid & CHV_VALID ) ) + { + /* received a packet */ + if ( pTrailer->pktFlags & PF_KICK ) + { + p_recvPool->kickOnFree = TRUE; + } + /* we do not want to indicate packet if filter is not set */ + if( pData->p_viport->p_adapter->xmitStarted && + pData->p_viport->p_adapter->packet_filter && + p_recvPool->numPostedBufs > 0 ) + { + if ( _data_recv_to_ndis_pkt( pData, pRdmaDest ) ) + { + p_recvPool->recv_pkt_array[idx++] = pRdmaDest->p_packet; + } + } + else + { /* put back to free buffers pool */ + InsertTailList( &p_recvPool->availRecvBufs, + &pRdmaDest->listPtrs ); + } + pBpe->valid = 0; + INC( p_recvPool->nextFullBuf, 1, p_recvPool->eiocPoolSz ); + p_recvPool->numPostedBufs--; +#ifdef VNIC_STATISTIC + pData->statistics.recvNum++; +#endif /* VNIC_STATISTIC */ + } + else + break; + } + return idx; +} + + +void +vnic_return_packet( + IN NDIS_HANDLE adapter_context, + IN NDIS_PACKET * const p_packet ) +{ + + RdmaDest_t *p_rdma_dest; + viport_t *p_viport; + + VNIC_ENTER( VNIC_DBG_DATA ); + + UNREFERENCED_PARAMETER( adapter_context ); + + p_rdma_dest = VNIC_RECV_FROM_PACKET( p_packet ); + p_viport = p_rdma_dest->p_viport; + + ASSERT( p_rdma_dest->p_packet == p_packet ); + + NdisAcquireSpinLock( &p_viport->data.recvIosLock ); + + _data_return_recv( p_packet ); + + NdisReinitializePacket( p_packet ); + + InsertTailList( &p_viport->data.recvPool.availRecvBufs, + &p_rdma_dest->listPtrs ); + _data_allocBuffers( &p_viport->data, FALSE ); + _data_sendFreeRecvBuffers( &p_viport->data ); + + NdisReleaseSpinLock(&p_viport->data.recvIosLock ); + + VNIC_EXIT( VNIC_DBG_DATA ); +} +static void +_data_return_recv( + IN NDIS_PACKET *p_packet ) +{ + NDIS_BUFFER *p_buf; + PNDIS_PACKET_OOB_DATA p_oob_data; + + /* Unchain the NDIS buffer. */ + NdisUnchainBufferAtFront( p_packet, &p_buf ); + if( p_buf ) + { + /* Return the NDIS packet and NDIS buffer to their pools. */ + NdisFreeBuffer( p_buf ); + } + /* take care of OOB_DATA block since NdisReinitializePacket doesn't */ + p_oob_data = NDIS_OOB_DATA_FROM_PACKET( p_packet ); + NdisZeroMemory( p_oob_data, sizeof( NDIS_PACKET_OOB_DATA )); +} + +static void +_data_sendFreeRecvBuffers( + IN Data_t *pData ) +{ + RecvPool_t *p_recvPool = &pData->recvPool; + ib_send_wr_t *pWrq = &pData->freeBufsIo.io.wrq; + BOOLEAN bufsSent = FALSE; + uint64_t rdmaAddr; + uint32_t offset; + uint32_t sz; + unsigned int numToSend, + nextIncrement; + + VNIC_ENTER( VNIC_DBG_DATA ); + + for ( numToSend = p_recvPool->szFreeBundle; + numToSend <= p_recvPool->numFreeBufs; + numToSend += p_recvPool->szFreeBundle ) + { + + /* Handle multiple bundles as one when possible. */ + nextIncrement = numToSend + p_recvPool->szFreeBundle; + if (( nextIncrement <= p_recvPool->numFreeBufs ) + && ( p_recvPool->nextFreeBuf + nextIncrement <= p_recvPool->eiocPoolSz ) ) + { + continue; + } + + offset = p_recvPool->nextFreeBuf * sizeof(BufferPoolEntry_t); + sz = numToSend * sizeof(BufferPoolEntry_t); + rdmaAddr = p_recvPool->eiocRdmaAddr + offset; + + pWrq->ds_array->length = sz; + pWrq->ds_array->vaddr = PTR64((uint8_t *)p_recvPool->bufPool + offset); + pWrq->remote_ops.vaddr = rdmaAddr; + + if ( ibqp_postSend( &pData->qp, &pData->freeBufsIo.io ) != IB_SUCCESS ) + { + VNIC_TRACE(VNIC_DBG_ERROR, + ("Unable to rdma free buffers to EIOC\n") ); + + viport_failure( pData->p_viport ); + break; + } + + INC( p_recvPool->nextFreeBuf, numToSend, p_recvPool->eiocPoolSz ); + p_recvPool->numFreeBufs -= numToSend; + p_recvPool->numPostedBufs += numToSend; + bufsSent = TRUE; + } + + if( bufsSent ) + { + if( p_recvPool->kickOnFree ) + { + data_sendKickMessage( pData ); + } + } + if( p_recvPool->numPostedBufs == 0 ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("IOC %d: Unable to allocate receive buffers NumFreeBufs: %d nextFreeBuf: %d nextFullBuf %d eiocPoolSz: %d\n", + pData->p_viport->ioc_num, p_recvPool->numFreeBufs, + p_recvPool->nextFreeBuf, p_recvPool->nextFullBuf, + p_recvPool->eiocPoolSz ) ); + + //viport_failure( pData->p_viport ); + } + VNIC_EXIT( VNIC_DBG_DATA ); +} + + +void +data_cleanup( + IN Data_t *pData ) +{ + VNIC_ENTER( VNIC_DBG_DATA ); + + VNIC_TRACE(VNIC_DBG_DATA, + ("IOC[%d]data cleanup\n", pData->p_viport->ioc_num )); + + if( pData->p_recv_bufs ) + { + NdisFreeMemory( pData->p_recv_bufs, pData->recv_bufs_sz, 0 ); + pData->p_recv_bufs = NULL; + } + + if( pData->recvPool.recv_pkt_array ) + { + cl_free( pData->recvPool.recv_pkt_array ); + pData->recvPool.recv_pkt_array = NULL; + pData->recvPool.poolSz = 0; + } + + if ( pData->pLocalStorage ) + { + NdisFreeMemory( pData->pLocalStorage, pData->localStorageSz, 0 ); + pData->pLocalStorage = NULL; + } + + if( pData->h_recv_buf_pool ) + { + NdisFreeBufferPool( pData->h_recv_buf_pool ); + pData->h_recv_buf_pool = NULL; + } + + if ( pData->h_recv_pkt_pool ) + { + if( NdisPacketPoolUsage(pData->h_recv_pkt_pool) != 0) + { + VNIC_TRACE( VNIC_DBG_WARN, + ("Recv packet pool is not empty!!!\n") ); + } + NdisFreePacketPool( pData->h_recv_pkt_pool ); + pData->h_recv_pkt_pool = NULL; + } + // clear Qp struct for reuse + cl_memclr( &pData->qp, sizeof( IbQp_t) ); + + cl_timer_destroy( &pData->kickTimer ); + + VNIC_EXIT( VNIC_DBG_DATA ); +} + + +static void +_data_kickTimer_start( + IN Data_t *pData, + IN uint32_t microseconds ) +{ + VNIC_ENTER( VNIC_DBG_DATA ); + + InterlockedExchange( (LONG *)&pData->kickTimerOn, TRUE ); + + usec_timer_start(&pData->kickTimer, microseconds ); + + VNIC_EXIT( VNIC_DBG_DATA ); + return; +} + +static void +_data_kickTimer_stop( + IN Data_t *pData ) +{ + VNIC_ENTER( VNIC_DBG_DATA ); + + if( InterlockedExchange( &pData->kickTimerOn, FALSE ) == TRUE ) + { + cl_timer_stop( &pData->kickTimer ); + } + + VNIC_EXIT( VNIC_DBG_DATA ); +} diff --git a/trunk/ulp/qlgcvnic/kernel/vnic_data.h b/trunk/ulp/qlgcvnic/kernel/vnic_data.h new file mode 100644 index 00000000..14bc0c1b --- /dev/null +++ b/trunk/ulp/qlgcvnic/kernel/vnic_data.h @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2007 QLogic Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id$ + */ + +#ifndef _VNIC_DATA_H_ +#define _VNIC_DATA_H_ + +#include "vnic_trailer.h" + +typedef struct RdmaDest { + LIST_ENTRY listPtrs; + IbRegion_t region; + struct _viport *p_viport; + NDIS_PACKET *p_packet; + NDIS_BUFFER *p_buf; + uint32_t buf_sz; + uint8_t *data; + struct ViportTrailer *pTrailer; +} RdmaDest_t; + +typedef struct BufferPoolEntry { + uint64_t remoteAddr; + net32_t rKey; + uint32_t valid; +} BufferPoolEntry_t; + +typedef struct RecvPool { + uint32_t bufferSz; + uint32_t poolSz; + uint32_t eiocPoolSz; + uint32_t eiocRdmaRkey; + uint64_t eiocRdmaAddr; + uint32_t nextFullBuf; + uint32_t nextFreeBuf; + uint32_t numFreeBufs; + uint32_t numPostedBufs; + uint32_t szFreeBundle; + BOOLEAN kickOnFree; + BufferPoolEntry_t *bufPool; + RdmaDest_t *pRecvBufs; + LIST_ENTRY availRecvBufs; + NDIS_PACKET **recv_pkt_array; +} RecvPool_t; + +typedef struct XmitPool { + uint32_t bufferSz; + uint32_t poolSz; + uint32_t notifyCount; + uint32_t notifyBundle; + uint32_t nextXmitBuf; + uint32_t lastCompBuf; + uint32_t numXmitBufs; + uint32_t nextXmitPool; + uint32_t kickCount; + uint32_t kickByteCount; + uint32_t kickBundle; + uint32_t kickByteBundle; + BOOLEAN needBuffers; + BOOLEAN sendKicks; + uint32_t rdmaRKey; + uint64_t rdmaAddr; + BufferPoolEntry_t *bufPool; + RdmaIo_t *pXmitBufs; +} XmitPool_t; + +typedef struct Data { + struct _viport *p_viport; + DataConfig_t *p_conf; + IbRegion_t *p_phy_region; + IbRegion_t region; + IbRegion_t rbuf_region; + IbQp_t qp; + uint8_t *pLocalStorage; + uint32_t localStorageSz; + uint8_t *p_recv_bufs; + uint32_t recv_bufs_sz; + Inic_RecvPoolConfig_t hostPoolParms; + Inic_RecvPoolConfig_t eiocPoolParms; + RecvPool_t recvPool; + XmitPool_t xmitPool; + RdmaIo_t freeBufsIo; + SendIo_t kickIo; + LIST_ENTRY recvIos; + KSPIN_LOCK recvListLock; + NDIS_SPIN_LOCK recvIosLock; + NDIS_SPIN_LOCK xmitBufLock; + volatile LONG kickTimerOn; + BOOLEAN connected; + cl_timer_t kickTimer; + NDIS_HANDLE h_recv_pkt_pool; + NDIS_HANDLE h_recv_buf_pool; +#ifdef VNIC_STATISTIC + struct { + uint32_t xmitNum; + uint32_t recvNum; + uint32_t freeBufSends; + uint32_t freeBufNum; + uint32_t freeBufMin; + uint32_t kickRecvs; + uint32_t kickReqs; + uint32_t noXmitBufs; + uint64_t noXmitBufTime; + } statistics; +#endif /* VNIC_STATISTIC */ +} Data_t; + +void +vnic_return_packet( + IN NDIS_HANDLE adapter_context, + IN NDIS_PACKET* const p_packet ); + +void +data_construct( + IN Data_t *pData, + IN struct _viport *pViport ); + +ib_api_status_t +data_init( + Data_t *pData, + DataConfig_t *p_conf, + uint64_t guid ); + +ib_api_status_t +data_connect( + Data_t *pData ); + +ib_api_status_t +data_connected( + Data_t *pData ); + +void +data_disconnect( + Data_t *pData ); + +BOOLEAN +data_xmitPacket( + Data_t *pData, + NDIS_PACKET* const p_pkt ); + +void +data_cleanup( + Data_t *pData ); + +#define data_pathId(pData) (pData)->p_conf->pathId +#define data_eiocPool(pData) &(pData)->eiocPoolParms +#define data_hostPool(pData) &(pData)->hostPoolParms +#define data_eiocPoolMin(pData) &(pData)->p_conf->eiocMin +#define data_hostPoolMin(pData) &(pData)->p_conf->hostMin +#define data_eiocPoolMax(pData) &(pData)->p_conf->eiocMax +#define data_hostPoolMax(pData) &(pData)->p_conf->hostMax +#define data_localPoolAddr(pData) (pData)->xmitPool.rdmaAddr +#define data_localPoolRkey(pData) (pData)->xmitPool.rdmaRKey +#define data_remotePoolAddr(pData) &(pData)->recvPool.eiocRdmaAddr +#define data_remotePoolRkey(pData) &(pData)->recvPool.eiocRdmaRkey +#define data_maxMtu(pData) MAX_PAYLOAD(min((pData)->recvPool.bufferSz, (pData)->xmitPool.bufferSz)) - ETH_VLAN_HLEN +#define data_len(pData, pTrailer) ntoh16(pTrailer->dataLength) +#define data_offset(pData, pTrailer) \ + pData->recvPool.bufferSz - sizeof(struct ViportTrailer) \ + - (uint32_t)ROUNDUPP2(data_len(pData, pTrailer), VIPORT_TRAILER_ALIGNMENT) \ + + pTrailer->dataAlignmentOffset + + +/* The following macros manipulate ring buffer indexes. + * The ring buffer size must be a power of 2. + */ +#define ADD(index, increment, size) (((index) + (increment))&((size) - 1)) +#define NEXT(index, size) ADD(index, 1, size) +#define INC(index, increment, size) (index) = ADD(index, increment, size) + +#define VNIC_RECV_FROM_PACKET( P ) \ + (((RdmaDest_t **)P->MiniportReservedEx)[1]) + +#define VNIC_LIST_ITEM_FROM_PACKET( P ) \ + ((LIST_ENTRY *)P->MiniportReservedEx) + +#define VNIC_PACKET_FROM_LIST_ITEM( I ) \ + (PARENT_STRUCT( I, NDIS_PACKET, MiniportReservedEx )) + +#endif /* _VNIC_DATA_H_ */ diff --git a/trunk/ulp/qlgcvnic/kernel/vnic_debug.h b/trunk/ulp/qlgcvnic/kernel/vnic_debug.h new file mode 100644 index 00000000..a5df64f3 --- /dev/null +++ b/trunk/ulp/qlgcvnic/kernel/vnic_debug.h @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2007 QLogic Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id$ + */ + + +#ifndef _VNIC_DEBUG_H_ +#define _VNIC_DEBUG_H_ + + +#include + +/* + * Debug macros + */ +extern uint32_t g_vnic_dbg_lvl; + + +#define VNIC_DBG_INIT ( ( VNIC_DBG_INFO ) | 0x00000001 ) +#define VNIC_DBG_PNP ( ( VNIC_DBG_INFO ) | 0x00000002 ) +#define VNIC_DBG_SEND ( ( VNIC_DBG_INFO ) | 0x00000004 ) +#define VNIC_DBG_RECV ( ( VNIC_DBG_INFO ) | 0x00000008 ) +#define VNIC_DBG_STATUS ( ( VNIC_DBG_INFO ) | 0x00000010 ) +#define VNIC_DBG_IB ( ( VNIC_DBG_INFO ) | 0x00000020 ) +#define VNIC_DBG_BUF ( ( VNIC_DBG_INFO ) | 0x00000040 ) +#define VNIC_DBG_MCAST ( ( VNIC_DBG_INFO ) | 0x00000080 ) +#define VNIC_DBG_ALLOC ( ( VNIC_DBG_INFO ) | 0x00000100 ) +#define VNIC_DBG_OID ( ( VNIC_DBG_INFO ) | 0x00000200 ) +#define VNIC_DBG_DATA ( ( VNIC_DBG_INFO ) | 0x00000400 ) +#define VNIC_DBG_CTRL ( ( VNIC_DBG_INFO ) | 0x00000800 ) +#define VNIC_DBG_CTRL_PKT ( ( VNIC_DBG_INFO ) | 0x00001000 ) +#define VNIC_DBG_CONF ( ( VNIC_DBG_INFO ) | 0x00002000 ) +#define VNIC_DBG_VIPORT ( ( VNIC_DBG_INFO ) | 0x00004000 ) +#define VNIC_DBG_ADAPTER ( ( VNIC_DBG_INFO ) | 0x00008000 ) +#define VNIC_DBG_NETPATH ( ( VNIC_DBG_INFO ) | 0x00010000 ) + +#define VNIC_DBG_FUNC (0x10000000) /* For function entry/exit */ +#define VNIC_DBG_INFO (0x20000000) /* For verbose information */ +#define VNIC_DBG_WARN (0x40000000) /* For warnings. */ +#define VNIC_DBG_ERROR CL_DBG_ERROR +#define VNIC_DBG_ALL CL_DBG_ALL + +#define VNIC_DEBUG_FLAGS ( VNIC_DBG_ERROR | VNIC_DBG_WARN | VNIC_DBG_INFO ) +/* Enter and exit macros automatically add VNIC_DBG_FUNC bit */ +#define VNIC_ENTER( lvl ) \ + CL_ENTER( (lvl | VNIC_DBG_FUNC), g_vnic_dbg_lvl ) + +#define VNIC_EXIT( lvl ) \ + CL_EXIT( (lvl | VNIC_DBG_FUNC), g_vnic_dbg_lvl ) + +#if defined FREE_BUILD_DBG +#define VNIC_TRACE( lvl, msg ) \ + { \ + switch( (lvl) & VNIC_DBG_ERROR ) \ + { \ + case VNIC_DBG_ERROR: \ + cl_msg_out msg; \ + default: \ + CL_TRACE( (lvl), g_vnic_dbg_lvl, msg ); \ + } \ + } + +#define VNIC_TRACE_EXIT( lvl, msg ) \ + { \ + switch( (lvl) & VNIC_DBG_ERROR ) \ + { \ + case VNIC_DBG_ERROR: \ + cl_msg_out msg; \ + default: \ + CL_TRACE_EXIT( (lvl), g_vnic_dbg_lvl, msg ); \ + } \ + } + +#else // ! FREE_BUILD_DBG + +#define VNIC_TRACE( lvl, msg ) \ + CL_TRACE( (lvl), g_vnic_dbg_lvl, msg ) + +#define VNIC_TRACE_EXIT( lvl, msg ) \ + CL_TRACE_EXIT( (lvl), g_vnic_dbg_lvl, msg ) + +#endif // FREE_BUILD_DBG + +#define VNIC_PRINT( lvl, msg ) \ + CL_PRINT ( (lvl), g_vnic_dbg_lvl, msg ) + +#define VNIC_TRACE_BYTES( lvl, ptr, len ) \ + { \ + size_t _loop_; \ + for (_loop_ = 0; _loop_ < (len); ++_loop_) \ + { \ + CL_PRINT( (lvl), g_vnic_dbg_lvl, ("0x%.2X ", ((uint8_t*)(ptr))[_loop_])); \ + if ((_loop_ + 1)% 16 == 0) \ + { \ + CL_PRINT( (lvl), g_vnic_dbg_lvl, ("\n") ); \ + } \ + else if ((_loop_ % 4 + 1) == 0) \ + { \ + CL_PRINT( (lvl), g_vnic_dbg_lvl, (" ") ); \ + } \ + } \ + CL_PRINT( (lvl), g_vnic_dbg_lvl, ("\n") ); \ + } + + +#endif /* _VNIC_DEBUG_H_ */ diff --git a/trunk/ulp/qlgcvnic/kernel/vnic_driver.c b/trunk/ulp/qlgcvnic/kernel/vnic_driver.c new file mode 100644 index 00000000..942fa571 --- /dev/null +++ b/trunk/ulp/qlgcvnic/kernel/vnic_driver.c @@ -0,0 +1,2156 @@ +/* + * Copyright (c) 2007 QLogic Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id$ + */ + + + +#include +#include "vnic_driver.h" + + +vnic_globals_t g_vnic; + +g_registry_params_t reg_array[VNIC_REGISTRY_TBL_SIZE] = { + {L"", 0}, + {L"MinHostPoolSz", ENTRY_INIT_VALUE}, + {L"HostRecvPoolEntries", ENTRY_INIT_VALUE}, + {L"MinEiocPoolSz", ENTRY_INIT_VALUE}, + {L"MaxEiocPoolSz", ENTRY_INIT_VALUE}, + {L"MinHostKickTimeout", ENTRY_INIT_VALUE}, + {L"MaxHostKickTimeout", ENTRY_INIT_VALUE}, + {L"MinHostKickEntries", ENTRY_INIT_VALUE}, + {L"MaxHostKickEntries", ENTRY_INIT_VALUE}, + {L"MinHostKickBytes", ENTRY_INIT_VALUE}, + {L"MaxHostKickBytes", ENTRY_INIT_VALUE}, + {L"MinHostUpdateSz", ENTRY_INIT_VALUE}, + {L"MaxHostUpdateSz", ENTRY_INIT_VALUE}, + {L"MinEiocUpdateSz", ENTRY_INIT_VALUE}, + {L"MaxEiocUpdateSz", ENTRY_INIT_VALUE}, + {L"HeartbeatTimeout", ENTRY_INIT_VALUE}, +}; + +#define DEFAULT_HOST_NAME "VNIC Host" + +uint32_t g_vnic_dbg_lvl = VNIC_DEBUG_FLAGS; + +static void +_vnic_complete_query( + IN vnic_adapter_t* const p_adapter, + IN pending_oid_t* const p_oid_info, + IN const NDIS_STATUS status, + IN const void* const p_buf, + IN const ULONG buf_len ); + +static NDIS_STATUS +__vnic_get_tcp_task_offload( + IN vnic_adapter_t* p_adapter, + IN pending_oid_t* const p_oid_info ); + +static NDIS_STATUS +__vnic_set_tcp_task_offload( + IN vnic_adapter_t* p_adapter, + IN void* const p_info_buf, + IN ULONG* const p_info_len ); + +static NDIS_STATUS +_vnic_process_packet_filter( + IN vnic_adapter_t* const p_adapter, + IN ULONG pkt_filter ); + +static void +__vnic_read_machine_name( void ); + +static NTSTATUS +__vnic_read_service_registry( + IN UNICODE_STRING* const p_registry_path ); + +static NDIS_STATUS +__vnic_set_machine_name( + IN VOID *p_uni_array, + IN USHORT buf_size ); + +/* +p_drv_obj + Pointer to Driver Object for this device driver +p_registry_path + Pointer to unicode string containing path to this driver's registry area +return + STATUS_SUCCESS, NDIS_STATUS_BAD_CHARACTERISTICS, NDIS_STATUS_BAD_VERSION, + NDIS_STATUS_RESOURCES, or NDIS_STATUS_FAILURE +IRQL = PASSIVE_LEVEL +*/ +NTSTATUS +DriverEntry( + IN PDRIVER_OBJECT p_drv_obj, + IN PUNICODE_STRING p_registry_path ) +{ + NDIS_STATUS status; + NDIS_MINIPORT_CHARACTERISTICS characteristics; + + VNIC_ENTER( VNIC_DBG_INIT ); + +#ifdef _DEBUG_ + PAGED_CODE(); +#endif +/* + status = CL_INIT; + + if( !NT_SUCCESS( status ) ) + { + VNIC_TRACE_EXIT( VNIC_DBG_ERROR, + ("cl_init failed.\n") ); + return status; + } +*/ + status = NDIS_STATUS_SUCCESS; + + g_vnic.ndis_handle = NULL; + g_vnic.shutdown = 0; + g_vnic.p_params = NULL; + + NdisMInitializeWrapper( &g_vnic.ndis_handle, p_drv_obj, p_registry_path, NULL ); + + if ( g_vnic.ndis_handle == NULL ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("NdisMInitializeWrapper failed\n")); + CL_DEINIT; + return NDIS_STATUS_FAILURE; + } + + cl_memclr( &characteristics, sizeof(characteristics) ); + + characteristics.MajorNdisVersion = MAJOR_NDIS_VERSION; + characteristics.MinorNdisVersion = MINOR_NDIS_VERSION; + characteristics.CheckForHangHandler = vnic_check_for_hang; + characteristics.HaltHandler = vnic_halt; + characteristics.InitializeHandler = vnic_initialize; + characteristics.QueryInformationHandler = vnic_oid_query_info; + characteristics.ResetHandler = vnic_reset; + characteristics.SetInformationHandler = vnic_oid_set_info; + characteristics.ReturnPacketHandler = vnic_return_packet; + characteristics.SendPacketsHandler = vnic_send_packets; + +#ifdef NDIS51_MINIPORT + characteristics.CancelSendPacketsHandler = vnic_cancel_xmit; + characteristics.PnPEventNotifyHandler = vnic_pnp_notify; + characteristics.AdapterShutdownHandler = vnic_shutdown; +#endif + + status = NdisMRegisterMiniport( + g_vnic.ndis_handle, &characteristics, sizeof(characteristics) ); + + if( status != NDIS_STATUS_SUCCESS ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("NdisMRegisterMiniport failed with status of %d\n", status) ); + NdisTerminateWrapper( g_vnic.ndis_handle, NULL ); + CL_DEINIT; + } + else + { + NdisMRegisterUnloadHandler( g_vnic.ndis_handle, vnic_unload ); + + __vnic_read_machine_name(); + __vnic_read_service_registry( p_registry_path ); + +#if ( LBFO_ENABLED ) + cl_qlist_init( &g_vnic.primary_list ); + cl_qlist_init( &g_vnic.secondary_list ); +#endif + } + + VNIC_EXIT( VNIC_DBG_INIT ); + return status; +} + + +VOID +vnic_unload( + IN PDRIVER_OBJECT p_drv_obj ) +{ + VNIC_ENTER( VNIC_DBG_INIT ); + + UNREFERENCED_PARAMETER( p_drv_obj ); + + VNIC_TRACE_EXIT( VNIC_DBG_INFO, + (" Driver Unloaded....\n")); + //CL_DEINIT; +} + + +//! Initialization function called for each IOC discovered +/* The MiniportInitialize function is a required function that sets up a +NIC (or virtual NIC) for network I/O operations, claims all hardware +resources necessary to the NIC in the registry, and allocates resources +the driver needs to carry out network I/O operations. +IRQL = PASSIVE_LEVEL + +@param p_open_status Pointer to a status field set if this function returns NDIS_STATUS_OPEN_ERROR +@param p_selected_medium_index Pointer to unsigned integer noting index into medium_array for this NIC +@param medium_array Array of mediums for this NIC +@param medium_array_size Number of elements in medium_array +@param h_handle Handle assigned by NDIS for this NIC +@param wrapper_config_context Handle used for Ndis initialization functions +@return NDIS_STATUS_SUCCESS, NDIS_STATUS_UNSUPPORTED_MEDIA, NDIS_STATUS_RESOURCES, +NDIS_STATUS_NOT_SUPPORTED +*/ +NDIS_STATUS +vnic_initialize( + OUT PNDIS_STATUS p_open_status, + OUT PUINT p_selected_medium_index, + IN PNDIS_MEDIUM medium_array, + IN UINT medium_array_size, + IN NDIS_HANDLE h_handle, + IN NDIS_HANDLE wrapper_config_context ) +{ + NDIS_STATUS status = NDIS_STATUS_SUCCESS; + ib_api_status_t ib_status; + ib_pnp_req_t pnp_req; + UINT medium_index; + vnic_adapter_t *p_adapter; + + VNIC_ENTER( VNIC_DBG_INIT ); + +#ifdef _DEBUG_ + PAGED_CODE(); +#endif + + UNUSED_PARAM( p_open_status ); + + /* Search for our medium */ + for( medium_index = 0; medium_index < medium_array_size; ++medium_index ) + { + /* Check to see if we found our medium */ + if( medium_array[medium_index] == NdisMedium802_3 ) + break; + } + + if( medium_index == medium_array_size ) /* Never found it */ + { + VNIC_TRACE_EXIT( VNIC_DBG_ERROR, ("No supported media.\n") ); + return NDIS_STATUS_UNSUPPORTED_MEDIA; + } + + *p_selected_medium_index = medium_index; + + /* Create the adapter */ + ib_status = vnic_create_adapter( h_handle, wrapper_config_context, &p_adapter ); + if( ib_status != IB_SUCCESS ) + { + VNIC_TRACE_EXIT( VNIC_DBG_ERROR, + ("returned status %x\n", ib_status ) ); + return NDIS_STATUS_FAILURE; + } + + /* set NDIS features we support */ + NdisMSetAttributesEx( h_handle, + (NDIS_HANDLE)p_adapter, + 0, /*check for hung timeout, 2 sec */ + NDIS_ATTRIBUTE_BUS_MASTER | + NDIS_ATTRIBUTE_DESERIALIZE | + NDIS_ATTRIBUTE_SURPRISE_REMOVE_OK | + NDIS_ATTRIBUTE_USES_SAFE_BUFFER_APIS, + NdisInterfacePNPBus ); + + /* Register for IOC events */ + pnp_req.pfn_pnp_cb = __vnic_pnp_cb; + pnp_req.pnp_class = IB_PNP_IOC | IB_PNP_FLAG_REG_SYNC; + pnp_req.pnp_context = (const void *)p_adapter; + + ib_status = p_adapter->ifc.reg_pnp( p_adapter->h_al, &pnp_req, &p_adapter->h_pnp ); + + if( ib_status != IB_SUCCESS ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("ib_reg_pnp returned %s\n", p_adapter->ifc.get_err_str( ib_status )) ); + NdisWriteErrorLogEntry( h_handle, + NDIS_ERROR_CODE_OUT_OF_RESOURCES, 0); + status = NDIS_STATUS_FAILURE; + } + else if( p_adapter->state != INIC_REGISTERED ) + { + status = NDIS_STATUS_OPEN_FAILED; + *p_open_status = NDIS_STATUS_DEVICE_FAILED; + + VNIC_TRACE( VNIC_DBG_ERROR, + ("IOC[%d] ADAPTER Initialization Failed\n", p_adapter->ioc_num ) ); + NdisWriteErrorLogEntry( h_handle, + NDIS_ERROR_CODE_HARDWARE_FAILURE, 1, p_adapter->ioc_num ); + } + + if( status != NDIS_STATUS_SUCCESS ) + { + vnic_destroy_adapter( p_adapter ); + } + + VNIC_EXIT( VNIC_DBG_INIT ); + return status; + +} + + +//! Deallocates resources when the NIC is removed and halts the NIC.. +/* IRQL = DISPATCH_LEVEL + +@param adapter_context The adapter context allocated at start +*/ +void +vnic_halt( + IN NDIS_HANDLE adapter_context ) +{ + VNIC_ENTER( VNIC_DBG_INIT ); + CL_ASSERT( adapter_context ); + + vnic_destroy_adapter( (vnic_adapter_t*)adapter_context ); + + VNIC_EXIT( VNIC_DBG_INIT ); +} + + +//! Reports the state of the NIC, or monitors the responsiveness of an underlying device driver. +/* IRQL = DISPATCH_LEVEL + +@param adapter_context The adapter context allocated at start +@return TRUE if the driver determines that its NIC is not operating +*/ + +BOOLEAN +vnic_check_for_hang( + IN NDIS_HANDLE adapter_context ) +{ + vnic_adapter_t *p_adapter; + + CL_ASSERT( adapter_context ); + p_adapter = (vnic_adapter_t*)adapter_context; + + /* current path is Ok */ + if( netpath_is_connected( p_adapter->p_currentPath ) ) + { + return FALSE; + } + + if( p_adapter->hung != 0 && + p_adapter->hung >= p_adapter->num_paths ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("IOC[%d] Adapter Hung: %d NumPath: %d\n", + p_adapter->ioc_num, p_adapter->hung, p_adapter->num_paths ) ); + return TRUE; + } + + return FALSE; +} + + +//! Returns information about the capabilities and status of the driver and/or its NIC. +/* IRQL = DISPATCH_LEVEL + +@param adapter_context The adapter context allocated at start +@param oid Object ID representing the query operation to be carried out +@param info_buf Buffer containing any input for this query and location for output +@param info_buf_len Number of bytes available in info_buf +@param p_bytes_written Pointer to number of bytes written into info_buf +@param p_bytes_needed Pointer to number of bytes needed to satisfy this oid +@return NDIS_STATUS_SUCCESS, NDIS_STATUS_PENDING, NDIS_STATUS_INVALID_OID, +NDIS_STATUS_INVALID_LENGTH, NDIS_STATUS_NOT_ACCEPTED, NDIS_STATUS_NOT_SUPPORTED, +NDIS_STATUS_RESOURCES +*/ +NDIS_STATUS +vnic_oid_query_info( + IN NDIS_HANDLE adapter_context, + IN NDIS_OID oid, + IN PVOID info_buf, + IN ULONG info_buf_len, + OUT PULONG p_bytes_written, + OUT PULONG p_bytes_needed ) +{ + vnic_adapter_t *p_adapter; + Netpath_t *p_netpath; + + NDIS_STATUS status; + USHORT version; + uint32_t info32 = 0; + uint64_t info64 = 0; + PVOID src_buf; + ULONG buf_len; + pending_oid_t oid_info; + + VNIC_ENTER( VNIC_DBG_OID ); + + oid_info.oid = oid; + oid_info.p_buf = info_buf; + oid_info.buf_len = info_buf_len; + oid_info.p_bytes_used = p_bytes_written; + oid_info.p_bytes_needed = p_bytes_needed; + + CL_ASSERT( adapter_context ); + p_adapter = (vnic_adapter_t *)adapter_context; + + CL_ASSERT( p_bytes_written ); + CL_ASSERT( p_bytes_needed ); + + status = NDIS_STATUS_SUCCESS; + src_buf = &info32; + buf_len = sizeof(info32); + + if( g_vnic.shutdown != 0 ) + { + *p_bytes_written = 0; + return NDIS_STATUS_NOT_ACCEPTED; + } + + p_netpath = p_adapter->p_currentPath; + if( !p_netpath || !p_netpath->carrier ) + { + status = NDIS_STATUS_NOT_ACCEPTED; + goto complete; + } + + switch( oid ) + { + /* Required General */ + case OID_GEN_SUPPORTED_LIST: + VNIC_TRACE( VNIC_DBG_OID, + ("received query for OID_GEN_SUPPORTED_LIST\n") ); + src_buf = (PVOID)SUPPORTED_OIDS; + buf_len = sizeof(SUPPORTED_OIDS); + break; + + case OID_GEN_HARDWARE_STATUS: + VNIC_TRACE( VNIC_DBG_OID, + ("received query for OID_GEN_HARDWARE_STATUS\n") ); + + if( p_netpath->carrier ) + { + VNIC_TRACE( VNIC_DBG_OID, + ("returning NdisHardwareStatusReady\n") ); + info32 = NdisHardwareStatusReady; + } + else + { + VNIC_TRACE( VNIC_DBG_OID, + ("returning NdisHardwareStatusInitializing\n") ); + info32 = NdisHardwareStatusNotReady; + } + break; + + case OID_GEN_MEDIA_SUPPORTED: + case OID_GEN_MEDIA_IN_USE: + VNIC_TRACE( VNIC_DBG_OID, + ("received query for OID_GEN_MEDIA_SUPPORTED " + "or OID_GEN_MEDIA_IN_USE\n") ); + info32 = NdisMedium802_3; + break; + + case OID_GEN_MAXIMUM_TOTAL_SIZE: /* frame size inlcuding header */ + info32 = sizeof( eth_hdr_t ); + case OID_GEN_MAXIMUM_FRAME_SIZE: /* wihout header */ + VNIC_TRACE( VNIC_DBG_OID, + ("received query for OID_GEN_MAXIMUM_FRAME_SIZE\n") ); + if( !p_netpath->carrier ) + { + info32 += MIN_MTU; + } + else + { + info32 += p_adapter->p_currentPath->pViport->mtu; + } + break; + + case OID_GEN_LINK_SPEED: + VNIC_TRACE( VNIC_DBG_OID, + ("received query for OID_GEN_LINK_SPEED\n") ); + + if( p_netpath->carrier ) + { + /* if we get link speed value - it is in Mbps units - have to convert to 100bps*/ + info32 = ( p_adapter->link_speed )? + ( p_adapter->link_speed * LINK_SPEED_1MBIT_x100BPS ): + DEFAULT_LINK_SPEED_x100BPS; + } + else + { + status = NDIS_STATUS_NOT_ACCEPTED; + } + break; + + case OID_GEN_TRANSMIT_BUFFER_SPACE: + VNIC_TRACE( VNIC_DBG_OID, + ("received query for OID_GEN_TRANSMIT_BUFFER_SPACE\n") ); + if ( !p_netpath->carrier ) + { + status= NDIS_STATUS_NOT_ACCEPTED; + } + else + { + info32 = p_netpath->pViport->data.xmitPool.bufferSz * + p_netpath->pViport->data.xmitPool.poolSz; + } + break; + + case OID_GEN_RECEIVE_BUFFER_SPACE: + VNIC_TRACE( VNIC_DBG_OID, + ("received query for OID_GEN_RECEIVE_BUFFER_SPACE " + "or OID_GEN_RECEIVE_BUFFER_SPACE\n") ); + if ( !p_netpath->carrier ) + { + status = NDIS_STATUS_NOT_ACCEPTED; + } + else + { + info32 = p_netpath->pViport->data.recvPool.bufferSz * + p_netpath->pViport->data.recvPool.poolSz; + } + break; + case OID_GEN_MAXIMUM_LOOKAHEAD: + case OID_GEN_CURRENT_LOOKAHEAD: + case OID_GEN_TRANSMIT_BLOCK_SIZE: + case OID_GEN_RECEIVE_BLOCK_SIZE: + VNIC_TRACE( VNIC_DBG_OID, + ("received query for OID_GEN_MAXIMUM_LOOKAHEAD " + "or OID_GEN_CURRENT_LOOKAHEAD or " + "OID_GEN_TRANSMIT_BLOCK_SIZE or " + "OID_GEN_RECEIVE_BLOCK_SIZE\n") ); + if( !p_netpath->carrier ) + { + info32 = MIN_MTU; + } + else + { + info32 = p_adapter->p_currentPath->pViport->mtu; + } + /*TODO: add VLAN tag size if support requested */ + info32 += sizeof(eth_hdr_t); + break; + + case OID_GEN_VENDOR_ID: + VNIC_TRACE( VNIC_DBG_OID, + ("received query for OID_GEN_VENDOR_ID\n") ); + + src_buf = (void*)VENDOR_ID; + buf_len = sizeof(VENDOR_ID); + break; + + case OID_GEN_VENDOR_DESCRIPTION: + VNIC_TRACE( VNIC_DBG_OID, + ("received query for OID_GEN_VENDOR_DESCRIPTION\n") ); + src_buf = VENDOR_DESCRIPTION; + buf_len = sizeof(VENDOR_DESCRIPTION); + break; + + case OID_GEN_VENDOR_DRIVER_VERSION: + VNIC_TRACE( VNIC_DBG_OID, + (" received query for OID_GEN_VENDOR_DRIVER_VERSION\n" ) ); + src_buf = &version; + buf_len = sizeof(version); + //TODO: Figure out what the right version is. + version = INIC_MAJORVERSION << 8 | INIC_MINORVERSION; + break; + + case OID_GEN_PHYSICAL_MEDIUM: + VNIC_TRACE( VNIC_DBG_OID, + (" received query for OID_GEN_PHYSICAL_MEDIUM\n" ) ); + info32 = NdisPhysicalMediumUnspecified; + break; + + case OID_GEN_CURRENT_PACKET_FILTER: + VNIC_TRACE( VNIC_DBG_OID, + (" received query for OID_GEN_CURRENT_PACKET_FILTER\n" ) ); + info32 = p_adapter->packet_filter; + break; + + case OID_GEN_DRIVER_VERSION: + VNIC_TRACE( VNIC_DBG_OID, + (" received query for OID_GEN_DRIVER_VERSION\n" ) ); + src_buf = &version; + buf_len = sizeof(version); + version = MAJOR_NDIS_VERSION << 8 | MINOR_NDIS_VERSION; + break; + + case OID_GEN_MAC_OPTIONS: + VNIC_TRACE( VNIC_DBG_OID, + (" received query for OID_GEN_MAC_OPTIONS\n" ) ); + info32 = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | + NDIS_MAC_OPTION_TRANSFERS_NOT_PEND | + NDIS_MAC_OPTION_NO_LOOPBACK | + NDIS_MAC_OPTION_FULL_DUPLEX | + NDIS_MAC_OPTION_8021P_PRIORITY | + NDIS_MAC_OPTION_8021Q_VLAN; + + break; + + case OID_GEN_MEDIA_CONNECT_STATUS: + VNIC_TRACE( VNIC_DBG_OID, + (" received query for OID_GEN_MEDIA_CONNECT_STATUS\n" ) ); + + info32 = ( p_adapter->carrier )? + NdisMediaStateConnected : + NdisMediaStateDisconnected; + break; + + case OID_GEN_MAXIMUM_SEND_PACKETS: + VNIC_TRACE( VNIC_DBG_OID, + (" received query for OID_GEN_MAXIMUM_SEND_PACKETS\n" ) ); + info32 = MAXLONG; // NDIS ignored it anyway + break; + + /* Required General Statistics */ + case OID_GEN_XMIT_OK: + VNIC_TRACE( VNIC_DBG_OID, + (" received query for OID_GEN_XMIT_OK\n" ) ); + if ( !p_netpath->carrier ) + { + info32 = 0; + } + else + { + info64 = p_netpath->pViport->stats.ifOutOk; + src_buf = &info64; + buf_len = sizeof(info64); + } + break; + + case OID_GEN_RCV_OK: + VNIC_TRACE( VNIC_DBG_OID, + (" received query for OID_GEN_RCV_OK\n" ) ); + if ( !p_netpath->carrier) + { + info32 = 0; + break; + } + if ( info_buf_len == sizeof(info32) ) + { + info32 = (uint32_t)p_netpath->pViport->stats.ifInOk; + } + else + { + info64 = p_netpath->pViport->stats.ifInOk; + src_buf = &info64; + buf_len = sizeof(info64); + } + break; + + case OID_GEN_XMIT_ERROR: + VNIC_TRACE( VNIC_DBG_OID, + (" received query for OID_GEN_XMIT_ERROR\n" ) ); + if ( !p_netpath->carrier ) + { + info32 = 0; + } + else + { + info64 = p_netpath->pViport->stats.ifOutErrors; + src_buf = &info64; + buf_len = sizeof(info64); + } + break; + + case OID_GEN_RCV_ERROR: + VNIC_TRACE( VNIC_DBG_OID, + (" received query for OID_GEN_RCV_ERROR\n" ) ); + if ( !p_netpath->carrier ) + { + info32 = 0; + } + else + { + info64 = p_netpath->pViport->stats.ifInErrors; + src_buf = &info64; + buf_len = sizeof(info64); + } + break; + + case OID_GEN_RCV_NO_BUFFER: + VNIC_TRACE( VNIC_DBG_OID, + (" received query for OID_GEN_RCV_NO_BUFFER\n" ) ); + info32 = 0; + break; + + case OID_GEN_DIRECTED_BYTES_XMIT: + VNIC_TRACE( VNIC_DBG_OID, + (" received query for OID_GEN_DIRECTED_BYTES_XMIT\n" ) ); + if ( !p_netpath->carrier ) + { + info32 = 0; + } + else + { + info64 = p_netpath->pViport->stats.ifOutUcastBytes; + src_buf = &info64; + buf_len = sizeof(info64); + } + break; + + case OID_GEN_DIRECTED_FRAMES_XMIT: + VNIC_TRACE( VNIC_DBG_OID, + (" received query for OID_GEN_DIRECTED_FRAMES_XMIT\n" ) ); + if ( !p_netpath->carrier ) + { + info32 = 0; + } + else + { + info64 = p_netpath->pViport->stats.ifOutNUcastPkts; + src_buf = &info64; + buf_len = sizeof(info64); + } + break; + + case OID_GEN_MULTICAST_BYTES_XMIT: + VNIC_TRACE( VNIC_DBG_OID, + (" received query for OID_GEN_MULTICAST_BYTES_XMIT\n" ) ); + if ( !p_netpath->carrier ) + { + info32 = 0; + } + else + { + info64 = p_netpath->pViport->stats.ifOutMulticastBytes; + src_buf = &info64; + buf_len = sizeof(info64); + } + break; + + case OID_GEN_MULTICAST_FRAMES_XMIT: + VNIC_TRACE( VNIC_DBG_OID, + (" received query for OID_GEN_MULTICAST_FRAMES_XMIT\n" ) ); + if ( !p_netpath->carrier ) + { + info32 = 0; + } + else + { + info64 = p_netpath->pViport->stats.ifOutMulticastPkts; + src_buf = &info64; + buf_len = sizeof(info64); + } + break; + + case OID_GEN_BROADCAST_BYTES_XMIT: + VNIC_TRACE( VNIC_DBG_OID, + (" received query for OID_GEN_BROADCAST_BYTES_XMIT\n" ) ); + if ( !p_netpath->carrier ) + { + info32 = 0; + } + else + { + info64 = p_netpath->pViport->stats.ifOutBroadcastBytes; + src_buf = &info64; + buf_len = sizeof(info64); + } + break; + + case OID_GEN_BROADCAST_FRAMES_XMIT: + VNIC_TRACE( VNIC_DBG_OID, + (" received query for OID_GEN_BROADCAST_FRAMES_XMIT\n" ) ); + if ( !p_netpath->carrier ) + { + info32 = 0; + } + else + { + info64 = p_netpath->pViport->stats.ifOutBroadcastPkts; + src_buf = &info64; + buf_len = sizeof(info64); + } + break; + case OID_GEN_DIRECTED_BYTES_RCV: + VNIC_TRACE( VNIC_DBG_OID, + (" received query for OID_GEN_DIRECTED_BYTES_RCV\n" ) ); + if ( !p_netpath->carrier ) + { + info32 = 0; + } + else + { + info64 = p_netpath->pViport->stats.ifInUcastBytes; + src_buf = &info64; + buf_len = sizeof(info64); + } + break; + + case OID_GEN_DIRECTED_FRAMES_RCV: + VNIC_TRACE( VNIC_DBG_OID, + (" received query for OID_GEN_DIRECTED_FRAMES_RCV\n" ) ); + if ( !p_netpath->carrier ) + { + info32 = 0; + } + else + { + info64 = p_netpath->pViport->stats.ifInNUcastPkts; + src_buf = &info64; + buf_len = sizeof(info64); + } + break; + + case OID_GEN_MULTICAST_BYTES_RCV: + VNIC_TRACE( VNIC_DBG_OID, + (" received query for OID_GEN_MULTICAST_BYTES_RCV\n" ) ); + if ( !p_netpath->carrier ) + { + info32 = 0; + } + else + { + info64 = p_netpath->pViport->stats.ifInMulticastBytes; + src_buf = &info64; + buf_len = sizeof(info64); + } + break; + + case OID_GEN_MULTICAST_FRAMES_RCV: + VNIC_TRACE( VNIC_DBG_OID, + (" received query for OID_GEN_MULTICAST_FRAMES_RCV\n" ) ); + if ( !p_netpath->carrier ) + { + info32 = 0; + } + else + { + info64 = p_netpath->pViport->stats.ifInMulticastPkts; + src_buf = &info64; + buf_len = sizeof(info64); + } + break; + + case OID_GEN_BROADCAST_BYTES_RCV: + VNIC_TRACE( VNIC_DBG_OID, + (" received query for OID_GEN_BROADCAST_BYTES_RCV\n" ) ); + if ( !p_netpath->carrier ) + { + info32 = 0; + } + else + { + info64 = p_netpath->pViport->stats.ifInBroadcastBytes; + src_buf = &info64; + buf_len = sizeof(info64); + } + break; + + case OID_GEN_BROADCAST_FRAMES_RCV: + VNIC_TRACE( VNIC_DBG_OID, + (" received query for OID_GEN_BROADCAST_FRAMES_RCV\n" ) ); + if ( !p_netpath->carrier ) + { + info32 = 0; + } + else + { + info64 = p_netpath->pViport->stats.ifInBroadcastPkts; + src_buf = &info64; + buf_len = sizeof(info64); + } + break; + + /* Required Ethernet operational characteristics */ + case OID_802_3_PERMANENT_ADDRESS: + case OID_802_3_CURRENT_ADDRESS: +#if defined( _DEBUG_ ) + if( oid == OID_802_3_PERMANENT_ADDRESS ) + { + VNIC_TRACE( VNIC_DBG_OID, + (" received query for OID_802_3_PERMANENT_ADDRESS\n" ) ); + } + else + { + VNIC_TRACE( VNIC_DBG_OID, + (" received query for OID_802_3_CURRENT_ADDRESS\n" ) ); + } +#endif /* defined( _DEBUG_ )*/ + if( !p_netpath->pViport || + p_netpath->pViport->errored || + p_netpath->pViport->disconnect ) + { + status = NDIS_STATUS_NOT_ACCEPTED; + break; + } + if ( !p_adapter->macSet ) + { + p_adapter->pending_query = TRUE; + p_adapter->query_oid = oid_info; + + VNIC_TRACE( VNIC_DBG_OID, + ("returning NDIS_STATUS_PENDING\n") ); + status = NDIS_STATUS_PENDING; + } + else + { + src_buf = &p_netpath->pViport->hwMacAddress; + buf_len = HW_ADDR_LEN; + } + break; + + case OID_802_3_MULTICAST_LIST: + VNIC_TRACE( VNIC_DBG_OID, + (" received query for OID_802_3_MULTICAST_LIST\n" ) ); + + if( !p_netpath->carrier || + !(p_netpath->pViport->flags & INIC_FLAG_ENABLE_NIC) ) + { +/* p_adapter->pending_query = TRUE; + p_adapter->query_oid = oid_info; + + VNIC_TRACE( VNIC_DBG_OID, + ("returning NDIS_STATUS_PENDING\n") ); + status = NDIS_STATUS_PENDING; +*/ + status = NDIS_STATUS_NOT_ACCEPTED; + break; + } + if( p_adapter->mc_count > 0 ) + { + buf_len = p_adapter->mc_count * sizeof( mac_addr_t ); + src_buf = &p_adapter->mcast_array; + } + else + { + info32 = 0; + } + break; + + case OID_802_3_MAXIMUM_LIST_SIZE: + VNIC_TRACE( VNIC_DBG_OID, + (" received query for OID_802_3_MAXIMUM_LIST_SIZE\n" ) ); + if ( !p_adapter->macSet ) + { + info32 = MAX_MCAST; + } + else + { + info32 = p_netpath->pViport->numMacAddresses - MCAST_ADDR_START; + } + break; + case OID_802_3_MAC_OPTIONS: + VNIC_TRACE( VNIC_DBG_OID, + (" received query for OID_802_3_MAC_OPTIONS\n" ) ); + info32 = 0; + break; + + /* Required Ethernet stats */ + case OID_802_3_RCV_ERROR_ALIGNMENT: + case OID_802_3_XMIT_ONE_COLLISION: + case OID_802_3_XMIT_MORE_COLLISIONS: + VNIC_TRACE( VNIC_DBG_OID, + (" received query for OID_802_3_RCV_ERROR_ALIGNMENT or " + "OID_802_3_XMIT_ONE_COLLISION or " + "OID_802_3_XMIT_MORE_COLLISIONS\n" ) ); + info32 = 0; + break; + + case OID_TCP_TASK_OFFLOAD: + VNIC_TRACE( VNIC_DBG_OID, + (" received query for OID_TCP_TASK_OFFLOAD\n" ) ); + + src_buf = NULL; + status = __vnic_get_tcp_task_offload( p_adapter, &oid_info ); + break; + + case OID_GEN_VLAN_ID: + /* return current vlan info */ + info32 =( p_adapter->vlan_info & 0x00000fff ); + break; + /* Optional General */ + case OID_GEN_SUPPORTED_GUIDS: + /* Optional General Stats */ + case OID_GEN_RCV_CRC_ERROR: + case OID_GEN_TRANSMIT_QUEUE_LENGTH: + + /* Optional Ethernet Stats */ + case OID_802_3_XMIT_DEFERRED: + case OID_802_3_XMIT_MAX_COLLISIONS: + case OID_802_3_RCV_OVERRUN: + case OID_802_3_XMIT_UNDERRUN: + case OID_802_3_XMIT_HEARTBEAT_FAILURE: + case OID_802_3_XMIT_TIMES_CRS_LOST: + case OID_802_3_XMIT_LATE_COLLISIONS: + case OID_PNP_CAPABILITIES: + status = NDIS_STATUS_NOT_SUPPORTED; + VNIC_TRACE( VNIC_DBG_OID, + (" received an unsupported oid of 0x%.8X!\n" , oid) ); + break; + + case OID_GEN_PROTOCOL_OPTIONS: + case OID_GEN_TRANSPORT_HEADER_OFFSET: +#ifdef NDIS51_MINIPORT + case OID_GEN_MACHINE_NAME: + case OID_GEN_RNDIS_CONFIG_PARAMETER: +#endif + default: + status = NDIS_STATUS_INVALID_OID; + VNIC_TRACE( VNIC_DBG_OID, + (" received an invalid oid of 0x%.8X!\n" , oid) ); + break; + } + + /* + * Complete the request as if it was handled asynchronously to maximize + * code reuse for when we really handle the requests asynchronously. + * Note that this requires the QueryInformation entry point to always + * return NDIS_STATUS_PENDING + */ +complete: + if( status != NDIS_STATUS_PENDING ) + { + _vnic_complete_query( + p_adapter, &oid_info, status, src_buf, buf_len ); + } + + VNIC_EXIT( VNIC_DBG_OID ); + return NDIS_STATUS_PENDING; +} + + +static void +_vnic_complete_query( + IN vnic_adapter_t* const p_adapter, + IN pending_oid_t* const p_oid_info, + IN const NDIS_STATUS status, + IN const void* const p_buf, + IN const ULONG buf_len ) +{ + NDIS_STATUS oid_status = status; + + VNIC_ENTER( VNIC_DBG_OID ); + + CL_ASSERT( status != NDIS_STATUS_PENDING ); + + if( status == NDIS_STATUS_SUCCESS ) + { + if( p_oid_info->buf_len < buf_len ) + { + VNIC_TRACE( VNIC_DBG_OID, + ("Insufficient buffer space. " + "Returning NDIS_STATUS_INVALID_LENGTH.\n") ); + oid_status = NDIS_STATUS_INVALID_LENGTH; + *p_oid_info->p_bytes_needed = buf_len; + *p_oid_info->p_bytes_used = 0; + } + else if( p_oid_info->p_buf ) + { + /* Only copy if we have a distinct source buffer. */ + if( p_buf ) + { + NdisMoveMemory( p_oid_info->p_buf, p_buf, buf_len ); + *p_oid_info->p_bytes_used = buf_len; + } + } + else + { + VNIC_TRACE( VNIC_DBG_OID, + ("Returning NDIS_NOT_ACCEPTED") ); + oid_status = NDIS_STATUS_NOT_ACCEPTED; + } + } + else + { + *p_oid_info->p_bytes_used = 0; + } + + p_adapter->pending_query = FALSE; + + NdisMQueryInformationComplete( p_adapter->h_handle, oid_status ); + + VNIC_EXIT( VNIC_DBG_OID ); +} + + +static NDIS_STATUS +__vnic_get_tcp_task_offload( + IN vnic_adapter_t* p_adapter, + IN pending_oid_t* const p_oid_info ) +{ + NDIS_TASK_OFFLOAD_HEADER *p_offload_hdr; + NDIS_TASK_OFFLOAD *p_offload_task; + NDIS_TASK_TCP_IP_CHECKSUM *p_offload_chksum; + + ULONG buf_len; + uint32_t enabled_TxCsum; + uint32_t enabled_RxCsum; + + buf_len = sizeof(NDIS_TASK_OFFLOAD_HEADER) + + sizeof(NDIS_TASK_OFFLOAD) + + sizeof(NDIS_TASK_TCP_IP_CHECKSUM) - 1; + + *(p_oid_info->p_bytes_needed) = buf_len; + + if( p_oid_info->buf_len < buf_len ) + return NDIS_STATUS_INVALID_LENGTH; + + p_offload_hdr = (NDIS_TASK_OFFLOAD_HEADER*)p_oid_info->p_buf; + if( p_offload_hdr->Version != NDIS_TASK_OFFLOAD_VERSION ) + return NDIS_STATUS_INVALID_DATA; + + if( p_offload_hdr->EncapsulationFormat.Encapsulation != + IEEE_802_3_Encapsulation ) + { + return NDIS_STATUS_INVALID_DATA; + } + /* too early, we didn't get response on CMD_INIT_INIC yet */ + if( !netpath_is_connected( p_adapter->p_currentPath ) ) + { + return NDIS_STATUS_NOT_ACCEPTED; + } + enabled_RxCsum = + (uint32_t)( p_adapter->params.UseRxCsum && + netpath_canRxCsum( p_adapter->p_currentPath ) ); + + enabled_TxCsum = + (uint32_t)( p_adapter->params.UseTxCsum && + netpath_canTxCsum( p_adapter->p_currentPath ) ); + + p_offload_hdr->OffsetFirstTask = sizeof(NDIS_TASK_OFFLOAD_HEADER); + p_offload_task = (NDIS_TASK_OFFLOAD*)(p_offload_hdr + 1); + p_offload_task->Version = NDIS_TASK_OFFLOAD_VERSION; + p_offload_task->Size = sizeof(NDIS_TASK_OFFLOAD); + p_offload_task->Task = TcpIpChecksumNdisTask; + p_offload_task->OffsetNextTask = 0; + p_offload_task->TaskBufferLength = sizeof(NDIS_TASK_TCP_IP_CHECKSUM); + p_offload_chksum = + (NDIS_TASK_TCP_IP_CHECKSUM*)p_offload_task->TaskBuffer; + + p_offload_chksum->V4Transmit.IpOptionsSupported = enabled_TxCsum; + p_offload_chksum->V4Transmit.TcpOptionsSupported = enabled_TxCsum; + p_offload_chksum->V4Transmit.TcpChecksum = enabled_TxCsum; + p_offload_chksum->V4Transmit.UdpChecksum = enabled_TxCsum; + p_offload_chksum->V4Transmit.IpChecksum = enabled_TxCsum; + + p_offload_chksum->V4Receive.IpOptionsSupported = enabled_RxCsum; + p_offload_chksum->V4Receive.TcpOptionsSupported = enabled_RxCsum; + p_offload_chksum->V4Receive.TcpChecksum = enabled_RxCsum; + p_offload_chksum->V4Receive.UdpChecksum = enabled_RxCsum; + p_offload_chksum->V4Receive.IpChecksum = enabled_RxCsum; + + p_offload_chksum->V6Transmit.IpOptionsSupported = enabled_TxCsum; + p_offload_chksum->V6Transmit.TcpOptionsSupported = enabled_TxCsum; + p_offload_chksum->V6Transmit.TcpChecksum = enabled_TxCsum; + p_offload_chksum->V6Transmit.UdpChecksum = enabled_TxCsum; + + p_offload_chksum->V6Receive.IpOptionsSupported = enabled_RxCsum; + p_offload_chksum->V6Receive.TcpOptionsSupported = enabled_RxCsum; + p_offload_chksum->V6Receive.TcpChecksum = enabled_RxCsum; + p_offload_chksum->V6Receive.UdpChecksum = enabled_RxCsum; + + *(p_oid_info->p_bytes_used) = buf_len; + + return NDIS_STATUS_SUCCESS; +} + +static NDIS_STATUS +__vnic_set_tcp_task_offload( + IN vnic_adapter_t* p_adapter, + IN void* const p_info_buf, + IN ULONG* const p_info_len ) +{ + NDIS_TASK_OFFLOAD_HEADER *p_offload_hdr; + NDIS_TASK_OFFLOAD *p_offload_task; + NDIS_TASK_TCP_IP_CHECKSUM *p_offload_chksum; + + ULONG enabled_TxCsum; + ULONG enabled_RxCsum; + + VNIC_ENTER( VNIC_DBG_OID ); + + if( !netpath_is_connected( p_adapter->p_currentPath ) ) + { + return NDIS_STATUS_NOT_ACCEPTED; + } + + p_offload_hdr = (NDIS_TASK_OFFLOAD_HEADER*)p_info_buf; + + if( *p_info_len < sizeof(NDIS_TASK_OFFLOAD_HEADER) ) + return NDIS_STATUS_INVALID_LENGTH; + + if( p_offload_hdr->Version != NDIS_TASK_OFFLOAD_VERSION ) + return NDIS_STATUS_INVALID_DATA; + + if( p_offload_hdr->Size != sizeof(NDIS_TASK_OFFLOAD_HEADER) ) + return NDIS_STATUS_INVALID_LENGTH; + + if( !p_offload_hdr->OffsetFirstTask ) + return NDIS_STATUS_SUCCESS; + + if( p_offload_hdr->EncapsulationFormat.Encapsulation != + IEEE_802_3_Encapsulation ) + { + return NDIS_STATUS_INVALID_DATA; + } + + p_offload_task = (NDIS_TASK_OFFLOAD*) + (((UCHAR*)p_offload_hdr) + p_offload_hdr->OffsetFirstTask); + + if( *p_info_len < sizeof(NDIS_TASK_OFFLOAD_HEADER) + + offsetof( NDIS_TASK_OFFLOAD, TaskBuffer ) + + sizeof(NDIS_TASK_TCP_IP_CHECKSUM) ) + { + return NDIS_STATUS_INVALID_LENGTH; + } + + if( p_offload_task->Version != NDIS_TASK_OFFLOAD_VERSION ) + return NDIS_STATUS_INVALID_DATA; + p_offload_chksum = + (NDIS_TASK_TCP_IP_CHECKSUM*)p_offload_task->TaskBuffer; + + enabled_TxCsum = + ( p_adapter->params.UseTxCsum && + netpath_canTxCsum( p_adapter->p_currentPath ) ); + enabled_RxCsum = + ( p_adapter->params.UseRxCsum && + netpath_canRxCsum( p_adapter->p_currentPath ) ); + + if( !enabled_TxCsum && + (p_offload_chksum->V4Transmit.IpOptionsSupported || + p_offload_chksum->V4Transmit.TcpOptionsSupported || + p_offload_chksum->V4Transmit.TcpChecksum || + p_offload_chksum->V4Transmit.UdpChecksum || + p_offload_chksum->V4Transmit.IpChecksum || + p_offload_chksum->V6Transmit.IpOptionsSupported || + p_offload_chksum->V6Transmit.TcpOptionsSupported || + p_offload_chksum->V6Transmit.TcpChecksum || + p_offload_chksum->V6Transmit.UdpChecksum ) ) + { + return NDIS_STATUS_NOT_SUPPORTED; + } + + if( !enabled_RxCsum && + (p_offload_chksum->V4Receive.IpOptionsSupported || + p_offload_chksum->V4Receive.TcpOptionsSupported || + p_offload_chksum->V4Receive.TcpChecksum || + p_offload_chksum->V4Receive.UdpChecksum || + p_offload_chksum->V4Receive.IpChecksum || + p_offload_chksum->V6Receive.IpOptionsSupported || + p_offload_chksum->V6Receive.TcpOptionsSupported || + p_offload_chksum->V6Receive.TcpChecksum || + p_offload_chksum->V6Receive.UdpChecksum ) ) + { + return NDIS_STATUS_NOT_SUPPORTED; + } + + VNIC_EXIT( VNIC_DBG_OID ); + + return NDIS_STATUS_SUCCESS; +} + + +//! Issues a hardware reset to the NIC and/or resets the driver's software state. +/* Tear down the connection and start over again. This is only called when there is a problem. +For example, if a send, query info, or set info had a time out. MiniportCheckForHang will +be called first. +IRQL = DISPATCH_LEVEL + +@param p_addr_resetPointer to BOOLLEAN that is set to TRUE if the NDIS +library should call MiniportSetInformation to restore addressing information to the current values. +@param adapter_context The adapter context allocated at start +@return NDIS_STATUS_SUCCESS, NDIS_STATUS_PENDING, NDIS_STATUS_NOT_RESETTABLE, +NDIS_STATUS_RESET_IN_PROGRESS, NDIS_STATUS_SOFT_ERRORS, NDIS_STATUS_HARD_ERRORS +*/ +NDIS_STATUS +vnic_reset( + OUT PBOOLEAN p_addr_reset, + IN NDIS_HANDLE adapter_context) +{ + vnic_adapter_t* p_adapter; + ib_api_status_t status; + + VNIC_ENTER( VNIC_DBG_INIT ); + + CL_ASSERT( p_addr_reset ); + CL_ASSERT( adapter_context ); + + p_adapter = (vnic_adapter_t*)adapter_context; + + status = adapter_reset( p_adapter ); + VNIC_EXIT( VNIC_DBG_INIT ); + switch( status ) + { + case IB_SUCCESS: + *p_addr_reset = TRUE; + return NDIS_STATUS_SUCCESS; + + case IB_NOT_DONE: + return NDIS_STATUS_PENDING; + + case IB_INVALID_STATE: + return NDIS_STATUS_RESET_IN_PROGRESS; + + default: + return NDIS_STATUS_HARD_ERRORS; + } +} + +//! Request changes in the state information that the miniport driver maintains +/* For example, this is used to set multicast addresses and the packet filter. +IRQL = DISPATCH_LEVEL + +@param adapter_context The adapter context allocated at start +@param oid Object ID representing the set operation to be carried out +@param info_buf Buffer containing input for this set and location for any output +@param info_buf_len Number of bytes available in info_buf +@param p_bytes_read Pointer to number of bytes read from info_buf +@param p_bytes_needed Pointer to number of bytes needed to satisfy this oid +@return NDIS_STATUS_SUCCESS, NDIS_STATUS_PENDING, NDIS_STATUS_INVALID_OID, +NDIS_STATUS_INVALID_LENGTH, NDIS_STATUS_INVALID_DATA, NDIS_STATUS_NOT_ACCEPTED, +NDIS_STATUS_NOT_SUPPORTED, NDIS_STATUS_RESOURCES +*/ +NDIS_STATUS +vnic_oid_set_info( + IN NDIS_HANDLE adapter_context, + IN NDIS_OID oid, + IN PVOID info_buf, + IN ULONG info_buf_len, + OUT PULONG p_bytes_read, + OUT PULONG p_bytes_needed ) +{ + vnic_adapter_t* p_adapter; + Netpath_t* p_netpath; + NDIS_STATUS status; + ULONG buf_len; + pending_oid_t oid_info; + + VNIC_ENTER( VNIC_DBG_OID ); + + CL_ASSERT( adapter_context ); + p_adapter = (vnic_adapter_t*)adapter_context; + p_netpath= p_adapter->p_currentPath; + + CL_ASSERT( p_bytes_read ); + CL_ASSERT( p_bytes_needed ); + CL_ASSERT( !p_adapter->pending_set ); + + status = NDIS_STATUS_SUCCESS; + *p_bytes_needed = 0; + buf_len = sizeof(ULONG); + + oid_info.oid = oid; + oid_info.p_buf = info_buf; + oid_info.buf_len = info_buf_len; + oid_info.p_bytes_used = p_bytes_read; + oid_info.p_bytes_needed = p_bytes_needed; + + /* do not set anything until IB path initialized and NIC is enabled */ + if( !p_adapter->p_currentPath->carrier ) + { + *p_bytes_read = 0; + return NDIS_STATUS_NOT_ACCEPTED; + } + + switch( oid ) + { + /* Required General */ + case OID_GEN_CURRENT_PACKET_FILTER: + VNIC_TRACE( VNIC_DBG_OID, + (" IOC %d received set for OID_GEN_CURRENT_PACKET_FILTER, %#x\n", + p_adapter->p_currentPath->pViport->ioc_num, + *(uint32_t*)info_buf )); +// if ( !p_adapter->p_currentPath->carrier ) +// { +// status = NDIS_STATUS_NOT_ACCEPTED; +// break; +// } + if( info_buf_len < sizeof( p_adapter->packet_filter ) ) + { + status = NDIS_STATUS_INVALID_LENGTH; + } + else if( !info_buf ) + { + status = NDIS_STATUS_INVALID_DATA; + } + else + { + p_adapter->set_oid = oid_info; + status = _vnic_process_packet_filter( p_adapter, *((ULONG*)info_buf) ); + } + break; + + case OID_GEN_CURRENT_LOOKAHEAD: + VNIC_TRACE( VNIC_DBG_OID, + (" received set for OID_GEN_CURRENT_LOOKAHEAD\n" )); + if( info_buf_len < buf_len ) + status = NDIS_STATUS_INVALID_LENGTH; + break; + + case OID_GEN_PROTOCOL_OPTIONS: + VNIC_TRACE( VNIC_DBG_OID, + (" received set for OID_GEN_PROTOCOL_OPTIONS\n" )); + if( info_buf_len < buf_len ) + status = NDIS_STATUS_INVALID_LENGTH; + break; + +#ifdef NDIS51_MINIPORT + case OID_GEN_MACHINE_NAME: + VNIC_TRACE( VNIC_DBG_OID, + (" received set for OID_GEN_MACHINE_NAME\n" ) ); + if( info_buf_len < buf_len ) + status = NDIS_STATUS_INVALID_LENGTH; + // else + // status = __vnic_set_machine_name( info_buf, + // (USHORT)info_buf_len ); + break; +#endif + + /* Required Ethernet operational characteristics */ + case OID_802_3_MULTICAST_LIST: + if( !p_adapter->p_currentPath->carrier ) + { + status = NDIS_STATUS_NOT_ACCEPTED; + break; + } + VNIC_TRACE( VNIC_DBG_OID, + (" IOC %d received set for OID_802_3_MULTICAST_LIST\n", + p_adapter->p_currentPath->pViport->ioc_num ) ); + if( info_buf_len > MAX_MCAST * sizeof(mac_addr_t) ) + { + VNIC_TRACE( VNIC_DBG_OID, + (" OID_802_3_MULTICAST_LIST - Multicast list full.\n" ) ); + status = NDIS_STATUS_MULTICAST_FULL; + *p_bytes_needed = MAX_MCAST * sizeof(mac_addr_t); + } + else if( info_buf_len % sizeof(mac_addr_t) ) + { + VNIC_TRACE( VNIC_DBG_OID, + (" OID_802_3_MULTICAST_LIST - Invalid input buffer length.\n" ) ); + status = NDIS_STATUS_INVALID_DATA; + } + else if( info_buf == NULL && info_buf_len != 0 ) + { + VNIC_TRACE( VNIC_DBG_OID, + (" OID_802_3_MULTICAST_LIST - Invalid input buffer.\n" ) ); + status = NDIS_STATUS_INVALID_DATA; + } + else + { + p_adapter->set_oid = oid_info; + status = adapter_set_mcast( p_adapter, (mac_addr_t*)info_buf, + (uint8_t)(info_buf_len / sizeof(mac_addr_t)) ); + } + break; + + case OID_TCP_TASK_OFFLOAD: + VNIC_TRACE( VNIC_DBG_OID, + (" received set for OID_TCP_TASK_OFFLOAD\n" ) ); + buf_len = info_buf_len; + status = __vnic_set_tcp_task_offload( p_adapter, info_buf, &buf_len ); + break; + + /* Optional General */ + case OID_GEN_TRANSPORT_HEADER_OFFSET: + VNIC_TRACE( VNIC_DBG_OID, + ("Set for OID_GEN_TRANSPORT_HEADER_OFFSET\n") ); + break; + case OID_GEN_VLAN_ID: + if( info_buf_len != 4 ) + { + status = NDIS_STATUS_INVALID_LENGTH; + break; + } + if( *(( uint32_t *)info_buf) < 4095 ) + { + p_adapter->vlan_info = *((uint32_t*)info_buf ); + } + else + { + status = NDIS_STATUS_INVALID_DATA; + } + break; + + case OID_GEN_SUPPORTED_LIST: + case OID_GEN_HARDWARE_STATUS: + case OID_GEN_MEDIA_SUPPORTED: + case OID_GEN_MEDIA_IN_USE: + case OID_GEN_MAXIMUM_FRAME_SIZE: + case OID_GEN_LINK_SPEED: + case OID_GEN_TRANSMIT_BUFFER_SPACE: + case OID_GEN_RECEIVE_BUFFER_SPACE: + case OID_GEN_MAXIMUM_LOOKAHEAD: + case OID_GEN_TRANSMIT_BLOCK_SIZE: + case OID_GEN_RECEIVE_BLOCK_SIZE: + case OID_GEN_MAXIMUM_TOTAL_SIZE: + case OID_GEN_VENDOR_ID: + case OID_GEN_VENDOR_DESCRIPTION: + case OID_GEN_VENDOR_DRIVER_VERSION: + case OID_GEN_DRIVER_VERSION: + case OID_GEN_MAC_OPTIONS: + case OID_GEN_MEDIA_CONNECT_STATUS: + case OID_GEN_MAXIMUM_SEND_PACKETS: + case OID_GEN_SUPPORTED_GUIDS: + case OID_GEN_PHYSICAL_MEDIUM: + default: + status = NDIS_STATUS_INVALID_OID; + VNIC_TRACE( VNIC_DBG_OID, + (" received an invalid oid of 0x%.8X!\n" , oid)); + break; + } + + if( status == NDIS_STATUS_SUCCESS ) + { + *p_bytes_read = buf_len; + } + else + { + if( status == NDIS_STATUS_INVALID_LENGTH ) + { + if ( !*p_bytes_needed ) + { + *p_bytes_needed = buf_len; + } + } + + *p_bytes_read = 0; + } + + VNIC_EXIT( VNIC_DBG_OID ); + return status; +} + + +//! Transfers some number of packets, specified as an array of packet pointers, over the network. +/* For a deserialized driver, these packets are completed asynchronously +using NdisMSendComplete. +IRQL <= DISPATCH_LEVEL + +@param adapter_context Pointer to vnic_adapter_t structure with per NIC state +@param packet_array Array of packets to send +@param numPackets Number of packets in the array +*/ +void +vnic_send_packets( + IN NDIS_HANDLE adapter_context, + IN PPNDIS_PACKET packet_array, + IN UINT num_packets ) +{ + vnic_adapter_t* const p_adapter =(vnic_adapter_t* const )adapter_context; + UINT packet_num; + + VNIC_ENTER( VNIC_DBG_SEND ); + + CL_ASSERT( adapter_context ); + + for( packet_num = 0; packet_num < num_packets; ++packet_num ) + { + netpath_xmitPacket( p_adapter->p_currentPath, + packet_array[packet_num] ); + } + VNIC_EXIT( VNIC_DBG_SEND ); +} + +void vnic_cancel_xmit( + IN NDIS_HANDLE adapter_context, + IN PVOID cancel_id ) +{ + vnic_adapter_t* const p_adapter =(vnic_adapter_t* const )adapter_context; + + if( p_adapter && + p_adapter->p_currentPath ) + { + netpath_cancel_xmit( p_adapter->p_currentPath, cancel_id ); + } +} + +void +vnic_pnp_notify( + IN NDIS_HANDLE adapter_context, + IN NDIS_DEVICE_PNP_EVENT pnp_event, + IN PVOID info_buf, + IN ULONG info_buf_len ) +{ + vnic_adapter_t *p_adapter; + + VNIC_ENTER( VNIC_DBG_PNP ); + + UNUSED_PARAM( info_buf ); + UNUSED_PARAM( info_buf_len ); + + p_adapter = (vnic_adapter_t*)adapter_context; + + CL_ASSERT( p_adapter ); + + VNIC_TRACE( VNIC_DBG_PNP, ("Event %d for IOC[%d] in state %#x\n", + pnp_event, p_adapter->ioc_num, p_adapter->pnp_state ) ); + + switch ( pnp_event ) + { + case NdisDevicePnPEventPowerProfileChanged: + break; + case NdisDevicePnPEventQueryRemoved: + case NdisDevicePnPEventRemoved: + case NdisDevicePnPEventSurpriseRemoved: + case NdisDevicePnPEventQueryStopped: + case NdisDevicePnPEventStopped: + case NdisDevicePnPEventMaximum: + + if( InterlockedExchange( (volatile LONG*)&p_adapter->pnp_state, IB_PNP_IOC_REMOVE ) == IB_PNP_IOC_ADD ) + { + if( netpath_is_valid( p_adapter->p_currentPath ) ) + { + netpath_stopXmit( p_adapter->p_currentPath ); + InterlockedExchange( &p_adapter->p_currentPath->carrier, (LONG)FALSE ); + netpath_linkDown( p_adapter->p_currentPath ); + __pending_queue_cleanup( p_adapter ); + } + } + vnic_resume_oids( p_adapter ); + break; + } + + VNIC_EXIT( VNIC_DBG_PNP ); +} + + +void +vnic_shutdown( + IN PVOID adapter_context ) +{ + vnic_adapter_t *p_adapter; + Netpath_t *p_netpath; + + VNIC_ENTER( VNIC_DBG_INIT ); + p_adapter = (vnic_adapter_t *)adapter_context; + + if( p_adapter ) + { + g_vnic.shutdown = p_adapter->ioc_num; + VNIC_TRACE( VNIC_DBG_INIT, + ("IOC[%d] going to Shutdown\n", p_adapter->ioc_num )); + p_netpath = p_adapter->p_currentPath; + + if( p_netpath && p_netpath->pViport ) + { + netpath_stopXmit( p_netpath ); + InterlockedExchange( &p_netpath->carrier, (LONG)FALSE ); + netpath_linkDown( p_netpath ); + } + + vnic_destroy_adapter( p_adapter ); + } + + VNIC_EXIT( VNIC_DBG_INIT ); +} + + +void +vnic_resume_set_oids( + IN vnic_adapter_t* const p_adapter ) +{ + NDIS_STATUS status = NDIS_STATUS_SUCCESS; + BOOLEAN pending_set; + pending_oid_t set_oid = {0}; + + Netpath_t* p_netpath; + VNIC_ENTER( VNIC_DBG_OID ); + + if( !p_adapter->pending_set ) + { + VNIC_EXIT( VNIC_DBG_OID ); + return; + } + NdisAcquireSpinLock( &p_adapter->lock ); + p_netpath = p_adapter->p_currentPath; + VNIC_TRACE( VNIC_DBG_OID, + ("IOC[%d]Resume Set OID %#x\n", + p_adapter->ioc_num, p_adapter->set_oid.oid )); + /* + * Set the status depending on our state. Fail OID requests that + * are pending while we reset the adapter. + */ + if( p_adapter->pnp_state != IB_PNP_IOC_REMOVE && + netpath_is_connected( p_netpath ) ) + { + status = NDIS_STATUS_SUCCESS; + } + else + { + status = NDIS_STATUS_NOT_ACCEPTED; + if( p_adapter->pending_set ) + { + VNIC_TRACE( VNIC_DBG_PNP, + ("IOC[%d]Pending set OID %#x while removing \n", + p_adapter->ioc_num, p_adapter->set_oid.oid )); + } + } + + pending_set = p_adapter->pending_set; + if( pending_set ) + { + set_oid = p_adapter->set_oid; + p_adapter->pending_set = FALSE; + } + NdisReleaseSpinLock( &p_adapter->lock ); + + ASSERT( KeGetCurrentIrql() == DISPATCH_LEVEL ); + + if( pending_set && status == NDIS_STATUS_SUCCESS ) + { + switch( set_oid.oid ) + { + case OID_GEN_CURRENT_PACKET_FILTER: + VNIC_TRACE( VNIC_DBG_OID, + (" IOC %d resume PACKET_FILTER set \n", + p_netpath->pViport->ioc_num ) ); + /* Validation already performed in the SetInformation path. */ + p_adapter->packet_filter = *(PULONG)set_oid.p_buf; + break; + + case OID_GEN_MACHINE_NAME: + status = __vnic_set_machine_name ( p_adapter->set_oid.p_buf, (USHORT)p_adapter->set_oid.buf_len ); + break; + + case OID_802_3_MULTICAST_LIST: + VNIC_TRACE( VNIC_DBG_OID, + (" IOC %d resume MULTICAST_LIST\n", + p_netpath->pViport->ioc_num ) ); + break; + + default: + CL_ASSERT( set_oid.oid && 0 ); + break; + } + } + + if( !netpath_is_connected( p_netpath ) ) + { + NdisMSetInformationComplete( p_adapter->h_handle, + NDIS_STATUS_NOT_ACCEPTED ); + } + else + NdisMSetInformationComplete( p_adapter->h_handle, status ); + + VNIC_EXIT( VNIC_DBG_OID ); +} + + +void +vnic_resume_oids( + IN vnic_adapter_t* const p_adapter ) +{ + ULONG info; + NDIS_STATUS status = NDIS_STATUS_SUCCESS; + BOOLEAN pending_query; + pending_oid_t query_oid = {0}; + KIRQL irql; + + Netpath_t* p_netpath = p_adapter->p_currentPath; + + uint8_t mac[HW_ADDR_LEN]; + + VNIC_ENTER( VNIC_DBG_OID ); + + NdisAcquireSpinLock( &p_adapter->lock ); + /* + * Set the status depending on our state. Fail OID requests that + * are pending while we reset the adapter. + */ + if( !netpath_is_connected( p_netpath ) ) + { + status = NDIS_STATUS_NOT_ACCEPTED; + } + + switch( p_adapter->pnp_state ) + { + case IB_PNP_IOC_ADD: + break; + + case IB_PNP_IOC_REMOVE: + default: + status = NDIS_STATUS_NOT_ACCEPTED; + break; + } + + pending_query = p_adapter->pending_query; + + if( pending_query ) + { + query_oid = p_adapter->query_oid; + p_adapter->pending_query = FALSE; + } + NdisReleaseSpinLock( &p_adapter->lock ); + + KeRaiseIrql( DISPATCH_LEVEL, &irql ); + + /* + * If we had a pending OID request for OID_GEN_LINK_SPEED, + * complete it now. Note that we hold the object lock since + * NdisMQueryInformationComplete is called at DISPATCH_LEVEL. + */ + if( pending_query ) + { + switch( query_oid.oid ) + { + case OID_802_3_CURRENT_ADDRESS: + case OID_802_3_PERMANENT_ADDRESS: + if ( status == NDIS_STATUS_SUCCESS ) + { + cl_memcpy( mac, p_netpath->pViport->hwMacAddress, HW_ADDR_LEN ); + } + _vnic_complete_query( p_adapter, + &query_oid, + status, + mac, + HW_ADDR_LEN ); + break; + case OID_GEN_LINK_SPEED: + info = DEFAULT_LINK_SPEED_x100BPS; + _vnic_complete_query( p_adapter, + &query_oid, + status, + &info, + sizeof( info ) ); + break; + + case OID_GEN_MEDIA_CONNECT_STATUS: + info = ( p_adapter->carrier )? NdisMediaStateConnected : + NdisMediaStateDisconnected; + _vnic_complete_query( p_adapter, + &query_oid, + status, + &info, + sizeof( info ) ); + break; + case OID_802_3_MULTICAST_LIST: + _vnic_complete_query( p_adapter, + &query_oid, + status, + p_netpath->p_adapter->mcast_array, + p_adapter->mc_count * sizeof( mac_addr_t ) ); + break; + case OID_GEN_TRANSMIT_BUFFER_SPACE: + if( status == NDIS_STATUS_SUCCESS ) + { + info = p_netpath->pViport->data.xmitPool.bufferSz * + p_netpath->pViport->data.xmitPool.numXmitBufs; + } + else + { + info = 0; + } + _vnic_complete_query( p_adapter, + &query_oid, + status, + &info, + sizeof( info ) ); + break; + case OID_GEN_RECEIVE_BUFFER_SPACE: + if( status == NDIS_STATUS_SUCCESS ) + { + info = p_netpath->pViport->data.recvPool.bufferSz * + p_netpath->pViport->data.recvPool.poolSz; + } + else + { + info = 0; + } + _vnic_complete_query( p_adapter, + &query_oid, + status, + &info, + sizeof( info ) ); + break; + default: + CL_ASSERT( query_oid.oid == OID_GEN_LINK_SPEED || + query_oid.oid == OID_GEN_MEDIA_CONNECT_STATUS || + query_oid.oid == OID_802_3_MULTICAST_LIST || + query_oid.oid == OID_802_3_CURRENT_ADDRESS || + query_oid.oid == OID_802_3_PERMANENT_ADDRESS || + query_oid.oid == OID_GEN_RECEIVE_BUFFER_SPACE || + query_oid.oid == OID_GEN_TRANSMIT_BUFFER_SPACE ); + break; + } + } + + vnic_resume_set_oids( p_adapter ); + + KeLowerIrql( irql ); + + VNIC_EXIT( VNIC_DBG_OID ); +} + +static NDIS_STATUS +__vnic_set_machine_name( + IN VOID *p_uni_array, + IN USHORT buf_size ) +{ + NDIS_STATUS status = NDIS_STATUS_SUCCESS; + uint8_t *p_src_buf = (uint8_t *)p_uni_array; + uint32_t i; + + VNIC_ENTER( VNIC_DBG_OID ); + + if( buf_size > 0 ) + { + cl_memclr(g_vnic.host_name, sizeof( g_vnic.host_name ) ); + for( i = 0; i < min( ( buf_size > 1 ), sizeof( g_vnic.host_name ) ); i++ ) + { + g_vnic.host_name[i] = *(p_src_buf + i*2); + } + } + + return status; +} + +static void +__vnic_read_machine_name( void ) +{ + /* this code is borrowed from the bus_driver */ + + NTSTATUS nt_status; + /* Remember the terminating entry in the table below. */ + RTL_QUERY_REGISTRY_TABLE table[2]; + UNICODE_STRING hostNamePath; + UNICODE_STRING hostNameW; + ANSI_STRING hostName; + + VNIC_ENTER( VNIC_DBG_INIT ); + + /* Get the host name. */ + RtlInitUnicodeString( &hostNamePath, L"ComputerName\\ComputerName" ); + RtlInitUnicodeString( &hostNameW, NULL ); + + /* + * Clear the table. This clears all the query callback pointers, + * and sets up the terminating table entry. + */ + cl_memclr( table, sizeof(table) ); + + /* Setup the table entries. */ + table[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; + table[0].Name = L"ComputerName"; + table[0].EntryContext = &hostNameW; + table[0].DefaultType = REG_SZ; + table[0].DefaultData = &hostNameW; + table[0].DefaultLength = 0; + + /* Have at it! */ + nt_status = RtlQueryRegistryValues( RTL_REGISTRY_CONTROL, + hostNamePath.Buffer, table, NULL, NULL ); + if( NT_SUCCESS( nt_status ) ) + { + /* Convert the UNICODE host name to UTF-8 (ASCII). */ + hostName.Length = 0; + hostName.MaximumLength = sizeof(g_vnic.host_name) - 1; + hostName.Buffer = (PCHAR)g_vnic.host_name; + nt_status = RtlUnicodeStringToAnsiString( &hostName, &hostNameW, FALSE ); + RtlFreeUnicodeString( &hostNameW ); + } + else + { + VNIC_TRACE(VNIC_DBG_ERROR , ("Failed to get host name from registry\n") ); + /* Use the default name... */ + cl_memcpy( g_vnic.host_name, + DEFAULT_HOST_NAME, + min (sizeof( g_vnic.host_name), sizeof(DEFAULT_HOST_NAME) ) ); + } + + VNIC_EXIT( VNIC_DBG_INIT ); +} + +/* function: usec_timer_start + uses cl_timer* functionality (init/destroy/stop/start ) + except it takes expiration time parameter in microseconds. +*/ +cl_status_t +usec_timer_start( + IN cl_timer_t* const p_timer, + IN const uint32_t time_usec ) +{ + LARGE_INTEGER due_time; + + CL_ASSERT( p_timer ); + CL_ASSERT( p_timer->pfn_callback ); + CL_ASSERT( KeGetCurrentIrql() <= DISPATCH_LEVEL ); + + /* Due time is in 100 ns increments. Negative for relative time. */ + due_time.QuadPart = -(int64_t)(((uint64_t)time_usec) * 10); + + /* Store the timeout time in the timer object. in microseconds */ + p_timer->timeout_time = cl_get_time_stamp() + (((uint64_t)time_usec)); + + KeSetTimer( &p_timer->timer, due_time, &p_timer->dpc ); + return( CL_SUCCESS ); +} + + +static NDIS_STATUS +_vnic_process_packet_filter( + IN vnic_adapter_t* const p_adapter, + IN ULONG pkt_filter ) +{ + NDIS_STATUS status = NDIS_STATUS_SUCCESS; + viport_t *p_viport; + ULONG need_updates = 0; + + VNIC_ENTER(VNIC_DBG_FUNC ); + + ASSERT( p_adapter ); + + p_viport = p_adapter->p_currentPath->pViport; + + ASSERT( p_viport ); + ASSERT( !( p_viport->updates & SYNC_QUERY ) ); + + if( ( InterlockedExchange( + (volatile LONG*)&p_adapter->packet_filter, pkt_filter )) == (LONG)pkt_filter ) + { + InterlockedExchange( &p_viport->updates, 0 ); + return status; + } + + ASSERT( (p_viport->updates & ~MCAST_OVERFLOW) == 0 ); + + if( pkt_filter ) + { + if( !( p_viport->flags & INIC_FLAG_ENABLE_NIC ) ) + { + p_viport->newFlags &= ~INIC_FLAG_DISABLE_NIC; + p_viport->newFlags |= INIC_FLAG_ENABLE_NIC | INIC_FLAG_SET_MTU; + p_viport->newMtu = (uint16_t)p_adapter->params.MinMtu; + InterlockedOr( (volatile LONG*)&need_updates, NEED_LINK_CONFIG ); + } + + if( pkt_filter & NDIS_PACKET_TYPE_ALL_MULTICAST ) + { + if( !( p_viport->flags & INIC_FLAG_ENABLE_MCAST_ALL ) ) + { + p_viport->newFlags &= ~INIC_FLAG_DISABLE_MCAST_ALL; + p_viport->newFlags |= INIC_FLAG_ENABLE_MCAST_ALL; + InterlockedOr( (volatile LONG*)&need_updates, + NEED_LINK_CONFIG | MCAST_OVERFLOW ); + } + } + else + { + if( p_viport->flags & NDIS_PACKET_TYPE_ALL_MULTICAST ) + { + p_viport->newFlags &= ~INIC_FLAG_ENABLE_MCAST_ALL; + p_viport->newFlags |= INIC_FLAG_DISABLE_MCAST_ALL; + InterlockedOr( (volatile LONG*)&need_updates, NEED_LINK_CONFIG ); + } + } + + if ( pkt_filter & NDIS_PACKET_TYPE_PROMISCUOUS ) + { + if( !( p_viport->flags & INIC_FLAG_ENABLE_PROMISC ) ) + { + p_viport->newFlags &= ~INIC_FLAG_DISABLE_PROMISC; + p_viport->newFlags |= INIC_FLAG_ENABLE_PROMISC; + InterlockedOr( (volatile LONG*)&need_updates, NEED_LINK_CONFIG ); + } + } + else + { + if( p_viport->flags & INIC_FLAG_ENABLE_PROMISC ) + { + p_viport->newFlags &= ~INIC_FLAG_ENABLE_PROMISC; + p_viport->newFlags |= INIC_FLAG_DISABLE_PROMISC; + InterlockedOr( (volatile LONG*)&need_updates, NEED_LINK_CONFIG ); + } + } + } + + /* ENABLE NIC, BROADCAST and MULTICAST flags set on start */ + if( need_updates ) + { + p_adapter->pending_set = TRUE; + InterlockedOr( &p_viport->updates, need_updates ); + + status = _viport_process_query( p_viport, FALSE ); + VNIC_TRACE( VNIC_DBG_OID, + ("LINK CONFIG status %x\n", status )); + if( status != NDIS_STATUS_PENDING ) + { + p_adapter->pending_set = FALSE; + } + } + + VNIC_EXIT( VNIC_DBG_FUNC ); + return status; +} + +static NTSTATUS +__vnic_read_service_registry( + IN UNICODE_STRING* const p_registry_path ) +{ + NTSTATUS status; + RTL_QUERY_REGISTRY_TABLE table[VNIC_REGISTRY_TBL_SIZE + 1]; + UNICODE_STRING param_path; + ULONG _reg_dbg_lvl = 0; + int i; + + RtlInitUnicodeString( ¶m_path, NULL ); + param_path.MaximumLength = + p_registry_path->Length + sizeof(L"\\Parameters"); + + param_path.Buffer = cl_zalloc( param_path.MaximumLength ); + if( !param_path.Buffer ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("Failed to allocate parameters path buffer.\n") ); + return STATUS_INSUFFICIENT_RESOURCES; + } + + RtlAppendUnicodeStringToString( ¶m_path, p_registry_path ); + RtlAppendUnicodeToString( ¶m_path, L"\\Parameters" ); + + cl_memclr( table, sizeof(table) ); + + /* init debug flags entry */ + table[0].Flags = RTL_QUERY_REGISTRY_DIRECT; + table[0].Name = L"DebugFlags"; + table[0].EntryContext = &_reg_dbg_lvl; + table[0].DefaultType = REG_DWORD; + table[0].DefaultData = &_reg_dbg_lvl; + table[0].DefaultLength = sizeof(ULONG); + + /* Setup the rest of table entries. */ + for ( i = 1; i < VNIC_REGISTRY_TBL_SIZE; i++ ) + { + table[i].Flags = RTL_QUERY_REGISTRY_DIRECT; + table[i].Name = reg_array[i].name; + table[i].EntryContext = ®_array[i].value; + table[i].DefaultType = REG_DWORD; + table[i].DefaultData = ®_array[i].value; + table[i].DefaultLength = sizeof(ULONG); + } + + status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE, + param_path.Buffer, table, NULL, NULL ); + + if( status == STATUS_SUCCESS ) + { + g_vnic_dbg_lvl |= _reg_dbg_lvl; + VNIC_TRACE(VNIC_DBG_INFO, ("DebugFlags Set %#x\n",g_vnic_dbg_lvl )); + g_vnic.p_params = reg_array; + } + + cl_free( param_path.Buffer ); + + return status; +} diff --git a/trunk/ulp/qlgcvnic/kernel/vnic_driver.h b/trunk/ulp/qlgcvnic/kernel/vnic_driver.h new file mode 100644 index 00000000..fe1ab950 --- /dev/null +++ b/trunk/ulp/qlgcvnic/kernel/vnic_driver.h @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2007 QLogic Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id$ + */ + +#ifndef _VNIC_DRIVER_H_ +#define _VNIC_DRIVER_H_ + +#include "vnic_adapter.h" +#include "vnic_debug.h" + + +#if defined(NDIS50_MINIPORT) +#define MAJOR_NDIS_VERSION 5 +#define MINOR_NDIS_VERSION 0 +#elif defined (NDIS51_MINIPORT) +#define MAJOR_NDIS_VERSION 5 +#define MINOR_NDIS_VERSION 1 +#else +#error NDIS Version not defined, try defining NDIS50_MINIPORT or NDIS51_MINIPORT +#endif + +#include + +static const NDIS_OID SUPPORTED_OIDS[] = +{ + OID_GEN_SUPPORTED_LIST, + OID_GEN_HARDWARE_STATUS, + OID_GEN_MEDIA_SUPPORTED, + OID_GEN_MEDIA_IN_USE, + OID_GEN_MAXIMUM_LOOKAHEAD, + OID_GEN_MAXIMUM_FRAME_SIZE, + OID_GEN_LINK_SPEED, + OID_GEN_TRANSMIT_BUFFER_SPACE, + OID_GEN_RECEIVE_BUFFER_SPACE, + OID_GEN_TRANSMIT_BLOCK_SIZE, + OID_GEN_RECEIVE_BLOCK_SIZE, + OID_GEN_VENDOR_ID, + OID_GEN_VENDOR_DESCRIPTION, + OID_GEN_CURRENT_PACKET_FILTER, + OID_GEN_CURRENT_LOOKAHEAD, + OID_GEN_DRIVER_VERSION, + OID_GEN_MAXIMUM_TOTAL_SIZE, + OID_GEN_PROTOCOL_OPTIONS, // ? + OID_GEN_MAC_OPTIONS, + OID_GEN_MEDIA_CONNECT_STATUS, + OID_GEN_MAXIMUM_SEND_PACKETS, + OID_GEN_VENDOR_DRIVER_VERSION, + OID_GEN_PHYSICAL_MEDIUM, + OID_GEN_XMIT_OK, + OID_GEN_RCV_OK, + OID_GEN_XMIT_ERROR, + OID_GEN_RCV_ERROR, + OID_GEN_RCV_NO_BUFFER, + OID_GEN_DIRECTED_BYTES_XMIT, + OID_GEN_DIRECTED_FRAMES_XMIT, + OID_GEN_MULTICAST_BYTES_XMIT, + OID_GEN_MULTICAST_FRAMES_XMIT, + OID_GEN_BROADCAST_BYTES_XMIT, + OID_GEN_BROADCAST_FRAMES_XMIT, + OID_GEN_DIRECTED_BYTES_RCV, + OID_GEN_DIRECTED_FRAMES_RCV, + OID_GEN_MULTICAST_BYTES_RCV, + OID_GEN_MULTICAST_FRAMES_RCV, + OID_GEN_BROADCAST_BYTES_RCV, + OID_GEN_BROADCAST_FRAMES_RCV, + OID_GEN_VLAN_ID, + OID_802_3_PERMANENT_ADDRESS, + OID_802_3_CURRENT_ADDRESS, + OID_802_3_MULTICAST_LIST, + OID_802_3_MAXIMUM_LIST_SIZE, + OID_802_3_MAC_OPTIONS, + OID_802_3_RCV_ERROR_ALIGNMENT, + OID_802_3_XMIT_ONE_COLLISION, + OID_802_3_XMIT_MORE_COLLISIONS, + OID_TCP_TASK_OFFLOAD +}; + +static const unsigned char VENDOR_ID[] = {0x00, 0x06, 0x6A, 0x00}; +#define VENDOR_DESCRIPTION "Virtual Ethernet over InfiniBand" +#define DEFAULT_VNIC_NAME "VNIC" + +NTSTATUS +DriverEntry( + IN PDRIVER_OBJECT p_drv_obj, + IN PUNICODE_STRING p_reg_path ); + +VOID +vnic_unload( + IN PDRIVER_OBJECT p_drv_obj ); + +NDIS_STATUS +vnic_initialize( + OUT PNDIS_STATUS p_open_err_status, + OUT PUINT p_selected_medium_index, + IN PNDIS_MEDIUM medium_array, + IN UINT medium_array_size, + IN NDIS_HANDLE h_handle, + IN NDIS_HANDLE wrapper_configuration_context ); + +BOOLEAN +vnic_check_for_hang( + IN NDIS_HANDLE adapter_context ); + +void +vnic_halt( + IN NDIS_HANDLE adapter_context ); + +NDIS_STATUS +vnic_oid_query_info( + IN NDIS_HANDLE adapter_context, + IN NDIS_OID oid, + IN PVOID info_buf, + IN ULONG info_buf_len, + OUT PULONG p_bytes_written, + OUT PULONG p_bytes_needed ); + +NDIS_STATUS +vnic_reset( + OUT PBOOLEAN p_addressing_reset, + IN NDIS_HANDLE adapter_context ); + +NDIS_STATUS +vnic_oid_set_info( + IN NDIS_HANDLE adapter_context, + IN NDIS_OID oid, + IN PVOID info_buf, + IN ULONG info_buf_length, + OUT PULONG p_bytes_read, + OUT PULONG p_bytes_needed ); + +void +vnic_send_packets( + IN NDIS_HANDLE adapter_context, + IN PPNDIS_PACKET packet_array, + IN UINT num_packets ); + +void +vnic_cancel_xmit( + IN NDIS_HANDLE adapter_context, + IN PVOID cancel_id ); +void +vnic_pnp_notify( + IN NDIS_HANDLE adapter_context, + IN NDIS_DEVICE_PNP_EVENT pnp_event, + IN PVOID info_buf, + IN ULONG info_buf_len ); + +void +vnic_shutdown( + IN PVOID adapter_context ); + +NDIS_STATUS +vnic_get_agapter_interface( + IN NDIS_HANDLE h_handle, + IN vnic_adapter_t *p_adapter); + + +/* same as cl_timer_start() except it takes timeout param in usec */ +/* need to run kicktimer */ +cl_status_t +usec_timer_start( + IN cl_timer_t* const p_timer, + IN const uint32_t time_usec ); + +#endif /* _VNIC_DRIVER_H_ */ diff --git a/trunk/ulp/qlgcvnic/kernel/vnic_ib.c b/trunk/ulp/qlgcvnic/kernel/vnic_ib.c new file mode 100644 index 00000000..31f2884b --- /dev/null +++ b/trunk/ulp/qlgcvnic/kernel/vnic_ib.c @@ -0,0 +1,922 @@ +/* + * Copyright (c) 2007 QLogic Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id$ + */ +#include "vnic_adapter.h" +#include "vnic_util.h" + +#ifndef max_t +#define max_t(type,x,y) \ + ({ type __x = (x); type __y = (y); __x > __y ? __x: __y; }) +#endif + + +static int inicIbInited = 0; + +extern struct _vnic_globals g_vnic; + +void +ib_asyncEvent( + ib_async_event_rec_t *pEventRecord ); + +static void +_ib_qpCompletion( + IN IbQp_t *pQp); +static void +_ibqp_connect_cb( + IN ib_cm_rep_rec_t *p_cm_rep ); + +static void +_ibqp_detach_cb( + IN ib_cm_drep_rec_t *p_drep_rec ); + +static void +_ibqp_dreq_cb( + IN ib_cm_dreq_rec_t *p_dreq_rec ); + +static void +_ibqp_mra_cb( + IN ib_cm_mra_rec_t *p_mra_rec ); + +static void +_ibqp_rej_cb( + IN ib_cm_rej_rec_t *p_rej_rec ); +static +void ib_workCompletion( + IN ib_cq_handle_t h_cq, + IN void *cqContext ); + + +uint8_t +ibca_findPortNum( + struct _viport *p_viport, + uint64_t guid ) +{ + uint8_t port; + + for (port = 0; port < p_viport->p_adapter->ca.numPorts; port++ ) + { + if (p_viport->p_adapter->ca.portGuids[port] == guid ) + { + return port+1; + } + } + return 0; +} + +ib_api_status_t +ibregion_physInit( + IN struct _vnic_adapter* p_adapter, + IN IbRegion_t *pRegion, + IN ib_pd_handle_t hPd, + IN uint64_t *p_vaddr, + IN uint64_t len ) +{ + ib_phys_create_t phys_mem; + ib_phys_range_t phys_range; + ib_api_status_t ib_status = IB_SUCCESS; + uint64_t vaddr = 0; + VNIC_ENTER ( VNIC_DBG_IB ); + + UNUSED_PARAM( p_vaddr ); + + phys_range.base_addr = *(p_vaddr); + phys_range.size = len; + phys_mem.access_ctrl = ( IB_AC_LOCAL_WRITE | IB_AC_RDMA_WRITE ); + phys_mem.buf_offset = 0; + phys_mem.hca_page_size = PAGE_SIZE; + phys_mem.length = len; + phys_mem.num_ranges = 1; + phys_mem.range_array = &phys_range; + + ib_status = p_adapter->ifc.reg_phys( hPd, + &phys_mem, + &vaddr, + &pRegion->lkey, + &pRegion->rkey, + &pRegion->h_mr ); + + if ( ib_status != IB_SUCCESS ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("ib_reg_phys failed status %s(%d)\n", + p_adapter->ifc.get_err_str(ib_status), ib_status ) ); + pRegion->h_mr = NULL; + } + else + { + pRegion->virtAddress = vaddr; + pRegion->len = len; + } + + VNIC_EXIT( VNIC_DBG_IB ); + return ib_status; +} + +ib_api_status_t +ibregion_init ( + IN viport_t *p_viport, + IN OUT IbRegion_t *pRegion, + IN ib_pd_handle_t hPd, + IN void* __ptr64 vaddr, + IN uint64_t len, + IN ib_access_t access_ctrl ) +{ + ib_api_status_t ib_status; + ib_mr_create_t create_mem; + + VNIC_ENTER ( VNIC_DBG_IB ); + + create_mem.length = len; + create_mem.vaddr = vaddr; + create_mem.access_ctrl = access_ctrl; + + ib_status = p_viport->p_adapter->ifc.reg_mem( hPd, + &create_mem, + &pRegion->lkey, + &pRegion->rkey, + &pRegion->h_mr ); + if ( ib_status != IB_SUCCESS ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("ib_reg_mem failed status %s(%d)\n", + p_viport->p_adapter->ifc.get_err_str( ib_status ), ib_status )); + pRegion->h_mr = NULL; + } + else + { + pRegion->len = len; + pRegion->virtAddress = (uint64_t)( vaddr ); + } + VNIC_EXIT ( VNIC_DBG_IB ); + return ib_status; +} + +void +ibregion_cleanup( + IN viport_t *p_viport, + IN IbRegion_t *pRegion ) +{ + ib_api_status_t ib_status; + + VNIC_ENTER( VNIC_DBG_IB ); + + if( pRegion->h_mr != NULL ) + { + ib_status = p_viport->p_adapter->ifc.dereg_mr( pRegion->h_mr ); + if ( ib_status != IB_SUCCESS ) + { + VNIC_TRACE_EXIT( VNIC_DBG_ERROR, + ("Dereg MR failed status (%d)\n", ib_status )); + } + pRegion->h_mr = NULL; + } + + VNIC_EXIT( VNIC_DBG_IB ); +} + + +void +ibqp_construct( + IN OUT IbQp_t *pQp, + IN viport_t *pViport ) +{ + VNIC_ENTER ( VNIC_DBG_IB ); + + ASSERT( pQp->qpState == IB_UNINITTED ); + + pQp->qp = NULL; + pQp->cq = NULL; + pQp->pViport = pViport; + pQp->pCa = &pViport->p_adapter->ca; + + NdisAllocateSpinLock( &pQp->qpLock ); + + InitializeListHead( &pQp->listPtrs); +} + + +ib_api_status_t +ibqp_init( + IN OUT IbQp_t *pQp, + IN uint64_t guid, + IN IbConfig_t *p_conf ) +{ + ib_qp_create_t attribCreate; + ib_qp_mod_t attribMod; + ib_qp_attr_t qpAttribs; + + ib_cq_create_t cq_create; + ib_cq_handle_t h_cq; + + ib_api_status_t ib_status = IB_SUCCESS; + + VNIC_ENTER ( VNIC_DBG_IB ); + + if (pQp->qpState != IB_UNINITTED && pQp->qpState != IB_DETACHED ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("ibqp_init: out of state (%d)\n", pQp->qpState) ); + return IB_ERROR; + } + + InterlockedExchange( &pQp->qpState, IB_UNINITTED ); + + pQp->p_conf = p_conf; + + cq_create.size = p_conf->numSends + p_conf->numRecvs; + cq_create.pfn_comp_cb = ib_workCompletion; + cq_create.h_wait_obj = NULL; + + ib_status = pQp->pViport->p_adapter->ifc.create_cq( + pQp->pViport->p_adapter->h_ca, &cq_create, pQp, ib_asyncEvent, &h_cq ); + + if( ib_status != IB_SUCCESS ) + { + VNIC_TRACE_EXIT( VNIC_DBG_ERROR, + ("Failed allocating completion queue\n") ); + goto err1; + } + + pQp->cq = h_cq; + + cl_memclr( &attribCreate, sizeof(attribCreate) ); + + attribCreate.qp_type = IB_QPT_RELIABLE_CONN; + attribCreate.sq_depth = p_conf->numSends; + attribCreate.rq_depth = p_conf->numRecvs; + attribCreate.sq_sge = p_conf->sendGather; + attribCreate.rq_sge = p_conf->recvScatter; + attribCreate.h_sq_cq = pQp->cq; + attribCreate.h_rq_cq = pQp->cq; + attribCreate.sq_signaled = FALSE; + + ib_status = pQp->pViport->p_adapter->ifc.create_qp( + pQp->pViport->p_adapter->ca.hPd, + &attribCreate, + pQp, + ib_asyncEvent, + &pQp->qp ); + if( ib_status != IB_SUCCESS ) + { + VNIC_TRACE_EXIT( VNIC_DBG_IB, ("Create QP failed %s\n", + pQp->pViport->p_adapter->ifc.get_err_str( ib_status )) ); + goto err2; + } + ib_status = pQp->pViport->p_adapter->ifc.query_qp(pQp->qp, &qpAttribs); + if( ib_status != IB_SUCCESS ) + { + VNIC_TRACE( VNIC_DBG_ERROR, ("Query QP failed %s\n", + pQp->pViport->p_adapter->ifc.get_err_str( ib_status )) ); + goto err3; + } + pQp->qpNumber = qpAttribs.num; + pQp->portGuid = guid; + cl_memclr( &attribMod, sizeof(attribMod) ); + + attribMod.req_state = IB_QPS_INIT; + attribMod.state.init.primary_port = ibca_findPortNum( pQp->pViport, guid ); + attribMod.state.init.pkey_index = 0; + attribMod.state.init.access_ctrl = IB_AC_LOCAL_WRITE; + attribMod.state.init.access_ctrl |= (p_conf->sendGather > 1) ? IB_AC_RDMA_WRITE : 0; + + ib_status = pQp->pViport->p_adapter->ifc.modify_qp( pQp->qp, &attribMod ); + if( ib_status != IB_SUCCESS ) + { + VNIC_TRACE_EXIT( VNIC_DBG_IB, ("Init QP failed %s\n", + pQp->pViport->p_adapter->ifc.get_err_str( ib_status )) ); + +err3: + pQp->pViport->p_adapter->ifc.destroy_qp( pQp->qp, NULL ); +err2: + pQp->pViport->p_adapter->ifc.destroy_cq( pQp->cq, NULL ); + } + else + { + InterlockedExchange( &pQp->qpState, IB_INITTED ); + } + +err1: + VNIC_EXIT ( VNIC_DBG_IB ); + return ib_status; +} + + +ib_api_status_t +ibqp_connect( + IN IbQp_t *pQp) +{ + IbCa_t *pCa; + viport_t *p_viport; + IbConfig_t *p_conf; + ib_api_status_t ib_status = IB_SUCCESS; + ib_cm_req_t conn_req; + + VNIC_ENTER( VNIC_DBG_IB ); + + if ( pQp->qpState != IB_INITTED ) + { + VNIC_TRACE_EXIT( VNIC_DBG_IB, + ("ibqp_connect: out of state (%d)\n",pQp->qpState) ); + return IB_INVALID_STATE; + } + + p_viport = pQp->pViport; + pCa = pQp->pCa; + p_conf = pQp->p_conf; + +#ifdef VNIC_STATISTIC + pQp->statistics.connectionTime = cl_get_time_stamp(); +#endif + + cl_memclr( &conn_req, sizeof(conn_req)); + + conn_req.h_al = p_viport->p_adapter->h_al; + conn_req.qp_type = IB_QPT_RELIABLE_CONN; + conn_req.h_qp = pQp->qp; + conn_req.p_req_pdata = (uint8_t*)&pQp->p_conf->connData; + conn_req.req_length = sizeof( Inic_ConnectionData_t ); + conn_req.svc_id = pQp->p_conf->sid; + conn_req.pkey = pQp->p_conf->pathInfo.pkey; + + conn_req.p_primary_path = &pQp->p_conf->pathInfo; + + conn_req.retry_cnt = (uint8_t)pQp->p_conf->retryCount; + conn_req.rnr_nak_timeout = pQp->p_conf->minRnrTimer; + conn_req.rnr_retry_cnt = (uint8_t)pQp->p_conf->rnrRetryCount; + conn_req.max_cm_retries = 5; + conn_req.remote_resp_timeout = ib_path_rec_pkt_life( &pQp->p_conf->pathInfo ) + 1; + conn_req.local_resp_timeout = ib_path_rec_pkt_life( &pQp->p_conf->pathInfo ) + 1; + + conn_req.compare_length = 0; + conn_req.resp_res = 0; + + conn_req.flow_ctrl = TRUE; + + conn_req.pfn_cm_req_cb = NULL; + conn_req.pfn_cm_rep_cb = _ibqp_connect_cb; + conn_req.pfn_cm_mra_cb = _ibqp_mra_cb; + conn_req.pfn_cm_rej_cb = _ibqp_rej_cb; + + InterlockedExchange( &pQp->qpState, IB_ATTACHING ); + + ib_status = p_viport->p_adapter->ifc.cm_req ( &conn_req ); + if ( ib_status != IB_SUCCESS && ib_status != IB_PENDING ) + { + VNIC_TRACE_EXIT( VNIC_DBG_ERROR, + ("Connect request return status %s\n", + p_viport->p_adapter->ifc.get_err_str( ib_status )) ); + InterlockedExchange( &pQp->qpState, IB_DETACHED ); + return ib_status; + } + + if( cl_event_wait_on( + &p_viport->sync_event, EVENT_NO_TIMEOUT, FALSE ) != CL_SUCCESS ) + { + VNIC_TRACE_EXIT( VNIC_DBG_ERROR, ("conn event timeout!\n") ); + return IB_TIMEOUT; + } + + if( pQp->qpState != IB_ATTACHED ) + { + VNIC_TRACE( VNIC_DBG_ERROR, ("QP connect failed\n") ); + ib_status = IB_ERROR; + } + + VNIC_EXIT( VNIC_DBG_IB ); + return ib_status; +} + + +static void +_ibqp_detach_cb( + IN ib_cm_drep_rec_t *p_drep_rec ) +{ + IbQp_t *pQp = (IbQp_t * __ptr64 )p_drep_rec->qp_context; + VNIC_ENTER( VNIC_DBG_IB ); + CL_ASSERT( p_drep_rec ); + + InterlockedExchange( &pQp->qpState, IB_DETACHED ); + viport_failure( pQp->pViport ); + + VNIC_EXIT( VNIC_DBG_IB ); +} + +static void +_ibqp_rej_cb( + IN ib_cm_rej_rec_t *p_rej_rec ) +{ + IbQp_t *pQp = (IbQp_t * __ptr64 )p_rej_rec->qp_context; + CL_ASSERT(p_rej_rec ); + + InterlockedExchange( &pQp->qpState, IB_DETACHED ); + switch ( p_rej_rec->rej_status ) + { + case IB_REJ_USER_DEFINED: + + VNIC_TRACE ( VNIC_DBG_IB | VNIC_DBG_ERROR, + ("Conn req user reject status %d\nARI: %s\n", + cl_ntoh16( p_rej_rec->rej_status ), + p_rej_rec->p_ari )); + break; + default: + VNIC_TRACE( VNIC_DBG_IB | VNIC_DBG_ERROR, + ("Conn req reject status %d\n", + cl_ntoh16( p_rej_rec->rej_status )) ); + } + + pQp->pViport->p_adapter->hung++; + cl_event_signal( &pQp->pViport->sync_event ); +} + +static void +_ibqp_mra_cb( + IN ib_cm_mra_rec_t *p_mra_rec ) +{ + VNIC_ENTER( VNIC_DBG_IB ); + CL_ASSERT( p_mra_rec ); + UNREFERENCED_PARAMETER( p_mra_rec ); + VNIC_EXIT( VNIC_DBG_IB ); +} + +static void +_ibqp_dreq_cb( + IN ib_cm_dreq_rec_t *p_dreq_rec ) +{ + ib_api_status_t ib_status = IB_SUCCESS; + ib_cm_drep_t cm_drep; + IbQp_t *pQp = (IbQp_t * __ptr64 )p_dreq_rec->qp_context; + + VNIC_ENTER( VNIC_DBG_IB ); + CL_ASSERT( p_dreq_rec ); + + cm_drep.drep_length = 0; + cm_drep.p_drep_pdata = NULL; + + ib_status = pQp->pViport->p_adapter->ifc.cm_drep( + p_dreq_rec->h_cm_dreq, &cm_drep ); + if ( ib_status != IB_SUCCESS ) + { + VNIC_TRACE_EXIT( VNIC_DBG_ERROR, + ("dreq_cb failed status %s(%d)\n", + pQp->pViport->p_adapter->ifc.get_err_str( ib_status ), ib_status)); + return; + } + + InterlockedExchange (&pQp->qpState, IB_DETACHED ); + pQp->pViport->p_adapter->hung++; + viport_failure( pQp->pViport ); + + VNIC_EXIT( VNIC_DBG_IB ); +} + +void +ibqp_detach( + IN IbQp_t *pQp ) +{ + ib_cm_dreq_t cm_dreq; + ib_api_status_t ib_status = IB_SUCCESS; + + VNIC_ENTER( VNIC_DBG_IB ); + + if( InterlockedCompareExchange( &pQp->qpState, + IB_DETACHING, IB_ATTACHED ) == IB_ATTACHED ) + { + NdisAcquireSpinLock( &pQp->qpLock ); + + cm_dreq.h_qp = pQp->qp; + cm_dreq.qp_type = IB_QPT_RELIABLE_CONN; + cm_dreq.p_dreq_pdata = NULL; + cm_dreq.dreq_length = 0; + cm_dreq.pfn_cm_drep_cb = _ibqp_detach_cb; + ib_status = pQp->pViport->p_adapter->ifc.cm_dreq( &cm_dreq ); + if ( ib_status != IB_SUCCESS ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + (" cm_dreq failed status %s\n", + pQp->pViport->p_adapter->ifc.get_err_str( ib_status ))); + } + + NdisReleaseSpinLock( &pQp->qpLock ); + + ib_status = pQp->pViport->p_adapter->ifc.destroy_qp( pQp->qp, NULL ); + if ( ib_status != IB_SUCCESS ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + (" QP destroy failed status %s\n", + pQp->pViport->p_adapter->ifc.get_err_str( ib_status ))); + } + } + + VNIC_EXIT( VNIC_DBG_IB ); + return; +} + +void +ibqp_cleanup( + IN IbQp_t *pQp ) +{ + ib_api_status_t ib_status = IB_SUCCESS; + LONG qp_state; + + VNIC_ENTER( VNIC_DBG_IB ); + + qp_state = InterlockedExchange( &pQp->qpState, IB_UNINITTED ); + if ( qp_state != IB_UNINITTED && + qp_state != IB_DETACHED && + qp_state != IB_DETACHING ) + { + ib_status = pQp->pViport->p_adapter->ifc.destroy_qp( pQp->qp, NULL ); + if ( ib_status != IB_SUCCESS ) + { + VNIC_TRACE_EXIT( VNIC_DBG_ERROR, + ("destroy_qp failed status %s\n", + pQp->pViport->p_adapter->ifc.get_err_str( ib_status )) ); + } + } + + VNIC_EXIT( VNIC_DBG_IB ); + return; +} + +ib_api_status_t ibqp_postSend(IbQp_t *pQp, Io_t *pIo) +{ + ib_api_status_t ib_status; + +#ifdef VNIC_STATISTIC + int64_t postTime; +#endif /* VNIC_STATISTIC */ + + VNIC_ENTER( VNIC_DBG_IB ); + + NdisAcquireSpinLock( &pQp->qpLock ); + + if( pQp->qpState != IB_ATTACHED ) + { + ib_status = IB_INVALID_STATE; + goto failure; + } + +#ifdef VNIC_STATISTIC + pIo->time = postTime = cl_get_time_stamp(); +#endif /* VNIC_STATISTIC */ + if (pIo->wrq.wr_type == WR_RDMA_WRITE ) + pIo->type = RDMA; + else + pIo->type = SEND; + + ib_status = + pQp->pViport->p_adapter->ifc.post_send( pQp->qp, &pIo->wrq, NULL ); + +#ifdef VNIC_STATISTIC + postTime = cl_get_time_stamp() - postTime; +#endif /* VNIC_STATISTIC */ + + if( ib_status != IB_SUCCESS ) + { + VNIC_TRACE( VNIC_DBG_ERROR, ("ib_post_send returned %s\n", + pQp->pViport->p_adapter->ifc.get_err_str( ib_status )) ); + } + else + { +#ifdef VNIC_STATISTIC + if (pIo->wrq.wr_type == WR_RDMA_WRITE) + { + pQp->statistics.rdmaPostTime += postTime; + pQp->statistics.rdmaPostIos++; + } + else + { + pQp->statistics.sendPostTime += postTime; + pQp->statistics.sendPostIos++; + } +#endif /* VNIC_STATISTIC */ + } + +failure: + NdisReleaseSpinLock( &pQp->qpLock ); + VNIC_EXIT( VNIC_DBG_IB ); + return ib_status; +} + + +ib_api_status_t +ibqp_postRecv(IbQp_t *pQp, Io_t *pIo) +{ + ib_api_status_t ib_status = IB_SUCCESS; +#ifdef VNIC_STATISTIC + int64_t postTime; +#endif /* VNIC_STATISTIC */ + + NdisAcquireSpinLock( &pQp->qpLock ); + /* can post recvieves before connecting queue pair */ + if( pQp->qpState != IB_INITTED && pQp->qpState != IB_ATTACHED ) + { + NdisReleaseSpinLock( &pQp->qpLock ); + return IB_INVALID_STATE; + } + pIo->type = RECV; + +#ifdef VNIC_STATISTIC + postTime = cl_get_time_stamp(); + if (pIo->time != 0) + { + pQp->statistics.recvCompTime += postTime - pIo->time; + pQp->statistics.recvCompIos++; + } +#endif /* VNIC_STATISTIC */ + + ib_status = + pQp->pViport->p_adapter->ifc.post_recv(pQp->qp, &pIo->r_wrq, NULL ); + +#ifdef VNIC_STATISTIC + postTime = (cl_get_time_stamp()) - postTime; +#endif /* VNIC_STATISTIC */ + + if( ib_status != IB_SUCCESS ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("Post Recv failed status %s(%d)\n", + pQp->pViport->p_adapter->ifc.get_err_str(ib_status), ib_status )); + + NdisReleaseSpinLock( &pQp->qpLock ); + return ib_status; + } + else + { +#ifdef VNIC_STATISTIC + pQp->statistics.recvPostTime += postTime; + pQp->statistics.recvPostIos++; +#endif /* VNIC_STATISTIC */ + } + + NdisReleaseSpinLock( &pQp->qpLock ); + return ib_status; +} + + +static void +_ibqp_connect_cb( + IN ib_cm_rep_rec_t *p_cm_rep ) +{ + IbQp_t *pQp; + ib_api_status_t ib_status = IB_SUCCESS; + + union + { + ib_cm_rtu_t cm_rtu; + ib_cm_mra_t cm_mra; + ib_cm_rej_t cm_rej; + } u_reply; + + viport_t *p_viport; + + VNIC_ENTER( VNIC_DBG_IB ); + + pQp = (IbQp_t * __ptr64 )p_cm_rep->qp_context; + p_viport = pQp->pViport; + + ASSERT( pQp->qpState == IB_ATTACHING ); + + ib_status = p_viport->p_adapter->ifc.rearm_cq( pQp->cq, FALSE ); + if ( ib_status != IB_SUCCESS ) + { + VNIC_TRACE_EXIT( VNIC_DBG_ERROR, + ("Rearm CQ failed %s\n", + p_viport->p_adapter->ifc.get_err_str( ib_status )) ); + + cl_memclr( &u_reply.cm_rej, sizeof( u_reply.cm_rej ) ); + u_reply.cm_rej.rej_status = IB_REJ_INSUF_RESOURCES; + + p_viport->p_adapter->ifc.cm_rej( p_cm_rep->h_cm_rep, &u_reply.cm_rej ); + goto err; + } + + cl_memclr( &u_reply.cm_rtu, sizeof( u_reply.cm_rtu ) ); + u_reply.cm_rtu.access_ctrl = IB_AC_LOCAL_WRITE; + + if( pQp->p_conf->sendGather > 1 ) + u_reply.cm_rtu.access_ctrl |= ( IB_AC_RDMA_WRITE ); + + u_reply.cm_rtu.pfn_cm_dreq_cb = _ibqp_dreq_cb; + + ib_status = p_viport->p_adapter->ifc.cm_rtu ( p_cm_rep->h_cm_rep, &u_reply.cm_rtu ); + if ( ib_status != IB_SUCCESS ) + { + VNIC_TRACE_EXIT( VNIC_DBG_ERROR, + ("Send RTU failed: status %#x\n", ib_status ) ); +err: + InterlockedExchange( &pQp->qpState, IB_DETACHED ); + pQp->pViport->p_adapter->hung++; + } + else + { + InterlockedExchange ( &pQp->qpState, IB_ATTACHED ); + } + + cl_event_signal( &p_viport->sync_event ); + VNIC_EXIT( VNIC_DBG_IB ); +} + + +#define WC_LIST_SIZE_TO_POLL 32 +static void +_ib_qpCompletion( + IN IbQp_t *pQp ) +{ + Io_t *pIo; + ib_wc_t wc[WC_LIST_SIZE_TO_POLL]; + ib_wc_t *p_free_wc; + ib_wc_t *p_done_wc; + ib_api_status_t ib_status = IB_SUCCESS; + int i; + +#ifdef VNIC_STATISTIC + int64_t compTime; +#endif /* VNIC_STATISTIC */ + + VNIC_ENTER ( VNIC_DBG_IB ); + + if ( pQp->qpState != IB_ATTACHING && pQp->qpState != IB_ATTACHED ) + return; + +#ifdef VNIC_STATISTIC + compTime = cl_get_time_stamp(); + pQp->statistics.numCallbacks++; +#endif /* VNIC_STATISTIC */ + + for( i = 0; i < (WC_LIST_SIZE_TO_POLL - 1); i++ ) + { + wc[i].p_next = &wc[i + 1]; + } + wc[(WC_LIST_SIZE_TO_POLL - 1)].p_next = NULL; + + p_free_wc = wc; + p_done_wc = NULL; + + ib_status = pQp->pViport->p_adapter->ifc.poll_cq( pQp->cq, &p_free_wc, &p_done_wc ); + + if ( ib_status != IB_SUCCESS && ib_status != IB_NOT_FOUND ) + { + VNIC_TRACE ( VNIC_DBG_ERROR, + ("ib_poll_cq failed status %d(%s)\n", ib_status, + pQp->pViport->p_adapter->ifc.get_err_str( ib_status )) ); + return; + } + + while ( p_done_wc ) + { + pIo = (Io_t *)(uintn_t)p_done_wc->wr_id; + + /* keep completion status for proper ndis packet return status */ + pIo->wc_status = p_done_wc->status; + + if( p_done_wc->status != IB_WCS_SUCCESS ) + { + VNIC_TRACE( VNIC_DBG_IB, + ("Failed Completion: WcType = %d, Status = %d, Length = %d\n", + p_done_wc->wc_type, + p_done_wc->status, + ( p_done_wc->wc_type == IB_WC_RECV )? p_done_wc->length : 0 ) ); + + if( pIo && pIo->type == RDMA ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("Failed RDMA Op, WC type = %d, WC status = %d IO type %d\n", + p_done_wc->wc_type, p_done_wc->status, pIo->type )); + + /* we must complete send packets */ + (*pIo->pRoutine)( pIo ); + } + } + else if(pIo) + { + if( pIo->pRoutine ) + { + (*pIo->pRoutine)( pIo ); + } + } + + p_done_wc = p_done_wc->p_next; + } + + ib_status = pQp->pViport->p_adapter->ifc.rearm_cq( pQp->cq, FALSE ); + + if ( ib_status != IB_SUCCESS ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("Rearm CQ failed status %d(%s)\n", ib_status, + pQp->pViport->p_adapter->ifc.get_err_str( ib_status )) ); + viport_failure( pQp->pViport ); + } + return; +} + + +static +void ib_workCompletion( + IN ib_cq_handle_t h_cq, + IN void *cqContext ) +{ + IbQp_t *pQp; + + VNIC_ENTER ( VNIC_DBG_IB ); + UNREFERENCED_PARAMETER( h_cq ); + pQp = (IbQp_t *)cqContext; + _ib_qpCompletion(pQp); + + VNIC_EXIT ( VNIC_DBG_IB ); + return; +} + +void +ib_asyncEvent( + IN ib_async_event_rec_t *pEventRecord ) +{ + vnic_adapter_t *p_adapter; + viport_t *p_viport; + + VNIC_ENTER ( VNIC_DBG_IB ); + + if ( pEventRecord ) + { + + switch ( pEventRecord->code ) + { + case IB_AE_PORT_DOWN: + p_adapter = ( vnic_adapter_t * __ptr64)pEventRecord->context; + + if( p_adapter && + p_adapter->p_currentPath->pViport && + !p_adapter->p_currentPath->pViport->errored ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("Async Event Port Down for CA GUID: %#016I64x\n", + p_adapter->ifc_data.ca_guid ) ); + } + break; + + case IB_AE_CQ_ERROR: + case IB_AE_RQ_ERROR: + case IB_AE_SQ_ERROR: + case IB_AE_QP_FATAL: + case IB_AE_WQ_REQ_ERROR: + case IB_AE_WQ_ACCESS_ERROR: + + p_viport = ((IbQp_t * __ptr64 )pEventRecord->context)->pViport; + + if( p_viport && !p_viport->errored ) + { + viport_failure( p_viport ); + + VNIC_TRACE( VNIC_DBG_ERROR, + ("Async Event %s (%#x) for port GUID: %#016I64x\n", + ib_get_async_event_str( pEventRecord->code ), + pEventRecord->code, + p_viport->portGuid ) ); + + } + break; + + default: + VNIC_TRACE( VNIC_DBG_IB, + ("Async Event %d\n", pEventRecord->code )); + break; + } + } + + VNIC_EXIT ( VNIC_DBG_IB ); +} + + + + + + + diff --git a/trunk/ulp/qlgcvnic/kernel/vnic_ib.h b/trunk/ulp/qlgcvnic/kernel/vnic_ib.h new file mode 100644 index 00000000..8dde7deb --- /dev/null +++ b/trunk/ulp/qlgcvnic/kernel/vnic_ib.h @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2007 QLogic Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id$ + */ +#ifndef _VNIC_IB_H_ +#define _VNIC_IB_H_ + + +#include +#include +#include "vnic_trailer.h" +struct Io; + +typedef void (CompRoutine_t)(struct Io *pIo); + +#define MAX_HCAS 4 +#define MAX_NUM_SGE 8 + +#define MAX_PHYS_MEMORY 0xFFFFFFFFFFFFFFFF +#define CONTROL_SID 0 +#define DATA_SID 1 + +#include +typedef union _vnic_sid { + uint64_t as_uint64; + struct { + uint8_t base_id; /* base id for vnic is 0x10 */ + uint8_t oui[3]; /* OUI */ + uint16_t reserved; /* should be zero */ + uint8_t type; /* control or data */ + uint8_t ioc_num; /* ioc number */ + }s; +} vnic_sid_t; + +typedef union _vnic_ioc_guid { + uint64_t as_uint64; + struct { + uint8_t oui[3]; + uint8_t ioc_num; + uint32_t counter; /* SST device type: 8 bits, counter:24 bits */ + }s; +} vnic_ioc_guid_t; +#include + +typedef enum { + IB_UNINITTED = 0, + IB_INITTED, + IB_ATTACHING, + IB_ATTACHED, + IB_DETACHING, + IB_DETACHED, + IB_DISCONNECTED +} IbState_t; +#pragma warning ( disable : 4324 ) +typedef struct _vnic_path_record { + cl_list_item_t list_entry; + ib_path_rec_t path_rec; +} vnic_path_record_t; +#pragma warning( default : 4324 ) + +typedef struct IbQp { + LIST_ENTRY listPtrs; + struct _viport *pViport; + struct IbConfig *p_conf; + NDIS_SPIN_LOCK qpLock; + volatile LONG qpState; + uint32_t qpNumber; + struct IbCa *pCa; + uint64_t portGuid; + ib_qp_handle_t qp; + ib_cq_handle_t cq; +#ifdef VNIC_STATISTIC + struct { + int64_t connectionTime; + int64_t rdmaPostTime; + uint32_t rdmaPostIos; + int64_t rdmaCompTime; + uint32_t rdmaCompIos; + int64_t sendPostTime; + uint32_t sendPostIos; + int64_t sendCompTime; + uint32_t sendCompIos; + int64_t recvPostTime; + uint32_t recvPostIos; + int64_t recvCompTime; + uint32_t recvCompIos; + uint32_t numIos; + uint32_t numCallbacks; + uint32_t maxIos; + } statistics; +#endif /* VNIC_STATISTIC */ +} IbQp_t; + +typedef struct IbRegion { + uint64_t virtAddress; + net64_t len; + ib_mr_handle_t h_mr; + net32_t lkey; + net32_t rkey; +} IbRegion_t; + + +#define VNIC_CA_MAX_PORTS 2 +typedef struct IbCa { + cl_list_item_t list_entry; + net64_t caGuid; + ib_pd_handle_t hPd; + IbRegion_t region; + uint32_t numPorts; + uint64_t portGuids[VNIC_CA_MAX_PORTS]; +} IbCa_t; + +typedef enum _OpType { + RECV, + RDMA, + SEND +} OpType_t; + +typedef struct Io { + LIST_ENTRY listPtrs; + struct _viport *pViport; + CompRoutine_t *pRoutine; + ib_send_wr_t wrq; + ib_recv_wr_t r_wrq; + ib_wc_status_t wc_status; +#ifdef VNIC_STATISTIC + int64_t time; +#endif /* VNIC_STATISTIC */ + OpType_t type; +} Io_t; + +typedef struct RdmaIo { + Io_t io; + ib_local_ds_t dsList[MAX_NUM_SGE]; + uint16_t index; + uint32_t len; + NDIS_PACKET *p_packet; + NDIS_BUFFER *p_buf; + ULONG packet_sz; + struct ViportTrailer *p_trailer; + uint8_t data[2* VIPORT_TRAILER_ALIGNMENT]; +} RdmaIo_t; + +typedef struct SendIo { + Io_t io; + ib_local_ds_t dsList; +} SendIo_t; + +typedef struct RecvIo { + Io_t io; + ib_local_ds_t dsList; +} RecvIo_t; + +void +ibqp_construct( + IN OUT IbQp_t *pQp, + IN struct _viport *pViport ); + +ib_api_status_t +ibqp_init( + IN IbQp_t *pQp, + IN uint64_t guid, + IN OUT struct IbConfig *p_conf); + +ib_api_status_t +ibqp_connect( + IN IbQp_t *pQp); + +void +ibqp_detach( + IN IbQp_t *pQp); + +void +ibqp_cleanup( + IN IbQp_t *pQp); + +ib_api_status_t +ibqp_postSend( + IN IbQp_t *pQp, + IN Io_t *pIo); + +ib_api_status_t +ibqp_postRecv( + IN IbQp_t *pQp, + IN Io_t *pIo); +uint8_t +ibca_findPortNum( + IN struct _viport *p_viport, + IN uint64_t guid ); + +ib_api_status_t +ibregion_init( + IN struct _viport *p_viport, + OUT IbRegion_t *pRegion, + IN ib_pd_handle_t hPd, + IN void* __ptr64 vaddr, + IN uint64_t len, + IN ib_access_t access_ctrl ); + +void +ibregion_cleanup( + IN struct _viport *p_viport, + IN IbRegion_t *pRegion ); + +void +ib_asyncEvent( + IN ib_async_event_rec_t *pEventRecord ); + +#define ibpd_fromCa(pCa) (&(pCa)->pd) + + +#endif /* _VNIC_IB_H_ */ diff --git a/trunk/ulp/qlgcvnic/kernel/vnic_netpath.c b/trunk/ulp/qlgcvnic/kernel/vnic_netpath.c new file mode 100644 index 00000000..98ddb374 --- /dev/null +++ b/trunk/ulp/qlgcvnic/kernel/vnic_netpath.c @@ -0,0 +1,345 @@ +/* + * Copyright (c) 2007 QLogic Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id$ + */ +#include "vnic_adapter.h" + +extern vnic_globals_t g_vnic; + + +void +netpath_init( + IN Netpath_t *pNetpath, + IN vnic_adapter_t *p_adapter ) +{ + VNIC_ENTER( VNIC_DBG_FUNC ); + + pNetpath->p_adapter = p_adapter; + pNetpath->carrier = 0; + pNetpath->pViport = NULL; + pNetpath->p_path_rec = NULL; + pNetpath->timerState = NETPATH_TS_IDLE; + + VNIC_EXIT( VNIC_DBG_FUNC ); + return; +} + +BOOLEAN +netpath_addPath ( + Netpath_t *pNetpath, + viport_t *pViport ) +{ + + if( pNetpath->pViport ) + { + return FALSE; + } + else + { + pNetpath->pViport = pViport; + viport_setParent( pViport, pNetpath ); + return TRUE; + } +} + +BOOLEAN +netpath_setUnicast( + IN Netpath_t* p_netpath, + IN uint8_t* p_address ) +{ + if( p_netpath->pViport ) + { + return( viport_setUnicast( p_netpath->pViport, p_address ) ); + } + return FALSE; +} + +NDIS_STATUS +netpath_setMulticast( + IN Netpath_t* p_netpath ) +{ + if( netpath_is_connected( p_netpath ) ) + { + return viport_setMulticast( p_netpath->pViport ); + } + return NDIS_STATUS_NOT_ACCEPTED; +} + +BOOLEAN +netpath_removePath( + IN Netpath_t *p_netpath, + IN viport_t *p_viport ) + +{ + if( p_netpath->pViport != p_viport ) + { + return FALSE; + } + else + { + viport_timerStop( p_netpath->pViport ); + viport_unsetParent( p_netpath->pViport ); + viport_cleanup( p_viport ); + } + + return TRUE; +} + +void +netpath_free( + IN Netpath_t *pNetpath ) +{ + if( netpath_is_valid( pNetpath ) ) + { + netpath_removePath( pNetpath, pNetpath->pViport ); + } + return; +} + +BOOLEAN +netpath_is_valid( + IN Netpath_t* const p_netpath ) +{ + if( p_netpath == NULL ) + return FALSE; + + if( p_netpath->pViport == NULL ) + return FALSE; + + return TRUE; +} + +BOOLEAN +netpath_is_connected( + IN Netpath_t* const p_netpath ) +{ + if( !netpath_is_valid( p_netpath ) ) + return FALSE; + + if( p_netpath->pViport->errored ) + return FALSE; + + if( p_netpath->p_path_rec == NULL ) + return FALSE; + + if( p_netpath->pViport->state != VIPORT_CONNECTED ) + return FALSE; + + + return TRUE; +} + +BOOLEAN +netpath_is_primary( + IN Netpath_t* const p_netpath ) +{ + return (BOOLEAN)( p_netpath->instance == NETPATH_PRIMARY ); +} +BOOLEAN +netpath_linkUp( + IN Netpath_t* p_netpath ) +{ + if( p_netpath != p_netpath->p_adapter->p_currentPath ) + return FALSE; + + if( p_netpath->carrier == TRUE && + InterlockedExchange( &p_netpath->p_adapter->carrier, TRUE ) == FALSE ) + { + NdisMIndicateStatus( p_netpath->p_adapter->h_handle, + NDIS_STATUS_MEDIA_CONNECT, NULL, 0 ); + NdisMIndicateStatusComplete( p_netpath->p_adapter->h_handle ); + VNIC_TRACE( VNIC_DBG_INIT, + ("IOC[%d] %s Link UP\n", + p_netpath->p_adapter->ioc_num, + netpath_to_string( p_netpath ) ) ); + } + return TRUE; +} + +BOOLEAN +netpath_linkDown( + IN Netpath_t* p_netpath ) +{ + if( p_netpath != p_netpath->p_adapter->p_currentPath ) + return FALSE; + + if ( InterlockedExchange( &p_netpath->p_adapter->carrier, FALSE ) == TRUE ) + { + NdisMIndicateStatus( p_netpath->p_adapter->h_handle, + NDIS_STATUS_MEDIA_DISCONNECT, NULL, 0 ); + NdisMIndicateStatusComplete( p_netpath->p_adapter->h_handle ); + VNIC_TRACE( VNIC_DBG_INIT, + ("IOC[%d] %s Link DOWN\n", + p_netpath->p_adapter->ioc_num, + netpath_to_string( p_netpath ) ) ); + } + + return TRUE; +} + +int netpath_maxMtu(Netpath_t *pNetpath) +{ + int ret = MAX_PARAM_VALUE; + + if (pNetpath->pViport) { + ret = viport_maxMtu(pNetpath->pViport); + } + return ret; +} + +BOOLEAN +netpath_xmitPacket( + IN Netpath_t *pNetpath, + IN NDIS_PACKET * const p_packet ) +{ + + if ( pNetpath->pViport && + pNetpath->p_adapter->xmitStarted ) + { + return ( viport_xmitPacket(pNetpath->pViport, p_packet ) ); + } + else + { + NdisInterlockedInsertTailList( + &pNetpath->p_adapter->send_pending_list, + VNIC_LIST_ITEM_FROM_PACKET( p_packet ), + &pNetpath->p_adapter->pending_list_lock ); + return TRUE; + } +} + +void +netpath_cancel_xmit( + IN Netpath_t *p_netpath, + IN PVOID cancel_id ) +{ + if( p_netpath->pViport ) + { + viport_cancel_xmit( p_netpath->pViport, cancel_id ); + } +} + +void +netpath_stopXmit( + IN Netpath_t *pNetpath ) + +{ + + VNIC_ENTER( VNIC_DBG_NETPATH ); + + if( pNetpath == pNetpath->p_adapter->p_currentPath ) + { + InterlockedCompareExchange( &pNetpath->p_adapter->xmitStarted, 0, 1 ); + } +#ifdef INIC_STATISTICS + if ( pNetpath->p_adapter->statistics.xmitRef == 0) + { + pNetpath->p_adapter->statistics.xmitRef = get_time_stamp_ms(); + } +#endif /* INIC_STATISTICS */ + return; +} + +void netpath_restartXmit( + IN Netpath_t *pNetpath ) +{ + VNIC_ENTER( VNIC_DBG_NETPATH ); + + if( ( netpath_is_connected( pNetpath ) ) && + pNetpath == pNetpath->p_adapter->p_currentPath ) + { + InterlockedCompareExchange( &pNetpath->p_adapter->xmitStarted, 1, 0 ); + VNIC_TRACE( VNIC_DBG_NETPATH, + ("IOC[%d] instance %d Restart TRANSMIT\n", + pNetpath->pViport->ioc_num, + pNetpath->instance )); + + } +#ifdef INIC_STATISTICS + if (pNetpath->p_adapter->statistics.xmitRef != 0) + { + pNetpath->p_adapter->statistics.xmitOffTime += + get_time_stamp_ms() - pNetpath->p_adapter->statistics.xmitRef; + pNetpath->p_adapter->statistics.xmitOffNum++; + pNetpath->p_adapter->statistics.xmitRef = 0; + } +#endif /* INIC_STATISTICS */ + return; +} + +// Viport on input calls this +void netpath_recvPacket( + IN Netpath_t *pNetpath, + IN NDIS_PACKET** pp_packet_array, + IN uint32_t num_packets ) +{ + +#ifdef INIC_STATISTICS + extern uin64_t recvRef; +#endif /* INIC_STATISTICS */ + + VNIC_ENTER( VNIC_DBG_NETPATH ); + +#ifdef INIC_STATISTICS + pNetpath->p_adapter->statistics.recvTime += cl_get_tick_count() - recvRef; + pNetpath->p_adapter->statistics.recvNum++; +#endif /* INIC_STATISTICS */ + + NdisMIndicateReceivePacket( pNetpath->p_adapter->h_handle, + pp_packet_array, + num_packets ); + return; +} + +void netpath_tx_timeout( + IN Netpath_t *pNetpath ) +{ + if ( pNetpath->pViport ) + { + viport_failure( pNetpath->pViport ); + } +} + +const char * +netpath_to_string( + IN Netpath_t *p_netpath ) +{ + if ( !netpath_is_valid( p_netpath ) ) + { + return "NULL"; + } + else if ( p_netpath == p_netpath->p_adapter->p_currentPath ) + { + return "CURRENT"; + } + else + { + return "STANDBY"; + } +} diff --git a/trunk/ulp/qlgcvnic/kernel/vnic_trailer.h b/trunk/ulp/qlgcvnic/kernel/vnic_trailer.h new file mode 100644 index 00000000..c047a9b6 --- /dev/null +++ b/trunk/ulp/qlgcvnic/kernel/vnic_trailer.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2007 QLogic Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id$ + */ + +#ifndef _VNIC_TRAILER_H_ +#define _VNIC_TRAILER_H_ + +/* pktFlags values */ +#define PF_CHASH_VALID 0x01 +#define PF_IPSEC_VALID 0x02 +#define PF_TCP_SEGMENT 0x04 +#define PF_KICK 0x08 +#define PF_VLAN_INSERT 0x10 +#define PF_PVID_OVERRIDDEN 0x20 +#define PF_FCS_INCLUDED 0x40 +#define PF_FORCE_ROUTE 0x80 + +/* txChksumFlags values */ +#define TX_CHKSUM_FLAGS_CHECKSUM_V4 0x01 +#define TX_CHKSUM_FLAGS_CHECKSUM_V6 0x02 +#define TX_CHKSUM_FLAGS_TCP_CHECKSUM 0x04 +#define TX_CHKSUM_FLAGS_UDP_CHECKSUM 0x08 +#define TX_CHKSUM_FLAGS_IP_CHECKSUM 0x10 + +/* rxChksumFlags values */ +#define RX_CHKSUM_FLAGS_TCP_CHECKSUM_FAILED 0x01 +#define RX_CHKSUM_FLAGS_UDP_CHECKSUM_FAILED 0x02 +#define RX_CHKSUM_FLAGS_IP_CHECKSUM_FAILED 0x04 +#define RX_CHKSUM_FLAGS_TCP_CHECKSUM_SUCCEEDED 0x08 +#define RX_CHKSUM_FLAGS_UDP_CHECKSUM_SUCCEEDED 0x10 +#define RX_CHKSUM_FLAGS_IP_CHECKSUM_SUCCEEDED 0x20 +#define RX_CHKSUM_FLAGS_LOOPBACK 0x40 +#define RX_CHKSUM_FLAGS_RESERVED 0x80 + +/* connectionHashAndValid values */ +#define CHV_VALID 0x80 +#define CHV_HASH_MASH 0x7f + +/* round down value to align, align must be a power of 2 */ +#ifndef ROUNDDOWNP2 +#define ROUNDDOWNP2(val, align) \ + (((ULONG)(val)) & (~((ULONG)(align)-1))) +#endif + +/* round up value to align, align must be a power of 2 */ +#ifndef ROUNDUPP2 +#define ROUNDUPP2(val, align) \ + (((ULONG)(val) + (ULONG)(align) - 1) & (~((ULONG)(align)-1))) +#endif + +#define VIPORT_TRAILER_ALIGNMENT 32 +#define BUFFER_SIZE(len) (sizeof(ViportTrailer_t) + ROUNDUPP2((len), VIPORT_TRAILER_ALIGNMENT)) +#define MAX_PAYLOAD(len) ROUNDDOWNP2((len) - sizeof(ViportTrailer_t), VIPORT_TRAILER_ALIGNMENT) +#define MIN_PACKET_LEN 64 +#include + +typedef struct ViportTrailer { + int8_t dataAlignmentOffset; + uint8_t rndisHeaderLength; /* reserved for use by Edp */ + uint16_t dataLength; + uint8_t pktFlags; + + uint8_t txChksumFlags; + + uint8_t rxChksumFlags; + + uint8_t ipSecFlags; + uint32_t tcpSeqNo; + uint32_t ipSecOffloadHandle; + uint32_t ipSecNextOffloadHandle; + uint8_t destMacAddr[6]; + uint16_t vLan; + uint16_t timeStamp; + uint8_t origin; + uint8_t connectionHashAndValid; +} ViportTrailer_t; + +#include + +#endif /* _VNIC_TRAILER_H_ */ diff --git a/trunk/ulp/qlgcvnic/kernel/vnic_util.h b/trunk/ulp/qlgcvnic/kernel/vnic_util.h new file mode 100644 index 00000000..c974b8df --- /dev/null +++ b/trunk/ulp/qlgcvnic/kernel/vnic_util.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2007 QLogic Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id$ + */ + +#ifndef _VNIC_UTIL_H_ +#define _VNIC_UTIL_H_ + +#include "vnic_debug.h" + +#define MAXU32 MAXULONG +#define MAXU64 ((uint64_t)(~0)) + +#define PTR64(what) ((uint64_t)(void * __ptr64)(what)) + +#ifndef min +#define min(a,b) ((a)<(b)?(a):(b)) +#endif + +#define hton16(x) _byteswap_ushort(x) +#define hton32(x) _byteswap_ulong(x) +#define hton64(x) _byteswap_uint64(x) + +#define ntoh16(x) hton16(x) +#define ntoh32(x) hton32(x) +#define ntoh64(x) hton64(x) + +#define IsPowerOf2(value) (((value) & (value - 1)) == 0) +/* round down to closest power of 2 value */ + +#define SetMinPowerOf2(_val) ((_val) & ( 1 << RtlFindMostSignificantBit( (uint64_t)(_val) ))) + + +#endif /* _VNIC_UTIL_H_ */ + diff --git a/trunk/ulp/qlgcvnic/kernel/vnic_viport.c b/trunk/ulp/qlgcvnic/kernel/vnic_viport.c new file mode 100644 index 00000000..f34c8bf4 --- /dev/null +++ b/trunk/ulp/qlgcvnic/kernel/vnic_viport.c @@ -0,0 +1,1232 @@ +/* + * Copyright (c) 2007 QLogic Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id$ + */ + +#include "iba/ib_al.h" +#include "vnic_util.h" +#include "vnic_driver.h" +#include "vnic_viport.h" +#include "vnic_control.h" +#include "vnic_data.h" +#include "vnic_config.h" +#include "vnic_controlpkt.h" + +extern vnic_globals_t g_vnic; + +static void +viport_timeout( + void *context ); + +static ib_api_status_t +viport_initMacAddresses( + viport_t *p_viport ); + +BOOLEAN +viport_config_defaults( + IN viport_t *p_viport ) +{ + + vnic_adapter_t *p_adapter = p_viport->p_adapter; + ViportConfig_t *pConfig = &p_viport->port_config; + ControlConfig_t *pControlConfig = &p_viport->port_config.controlConfig; + DataConfig_t *pDataConfig = &p_viport->port_config.dataConfig; + + VNIC_ENTER( VNIC_DBG_VIPORT ); + + p_viport->state = VIPORT_DISCONNECTED; + p_viport->linkState = LINK_RETRYWAIT; + p_viport->newMtu = 1500; + p_viport->newFlags = 0; + p_viport->hb_send_pending = FALSE; + + cl_timer_init( &p_viport->timer, viport_timeout, p_viport ); + + pConfig->statsInterval = p_adapter->params.ViportStatsInterval; + pConfig->hbInterval = p_adapter->params.ViportHbInterval; + pConfig->hbTimeout = p_adapter->params.ViportHbTimeout; + + cl_memcpy ( pConfig->ioc_string, + p_adapter->ioc_info.profile.id_string, + min( sizeof( p_adapter->ioc_info.profile.id_string ), + sizeof( pConfig->ioc_string )) ); + + pControlConfig->ibConfig.sid = 0; /* will set it later, from svc entries */ + pControlConfig->ibConfig.connData.pathId = 0; + pControlConfig->ibConfig.connData.inicInstance = 0; // assign instance id in update_path + pControlConfig->ibConfig.connData.pathNum = 0; + + pControlConfig->ibConfig.retryCount = p_adapter->params.RetryCount; + pControlConfig->ibConfig.rnrRetryCount = p_adapter->params.RetryCount; + pControlConfig->ibConfig.minRnrTimer = (uint8_t)p_adapter->params.MinRnrTimer; + pControlConfig->ibConfig.numRecvs = 5; /* Not configurable */ + pControlConfig->ibConfig.numSends = 1; /* Not configurable */ + pControlConfig->ibConfig.recvScatter = 1; /* Not configurable */ + pControlConfig->ibConfig.sendGather = 1; /* Not configurable */ + + /* indicate new features support capabilities */ + pControlConfig->ibConfig.connData.featuresSupported = + hton32((uint32_t)(INIC_FEAT_IGNORE_VLAN | INIC_FEAT_RDMA_IMMED )); + + cl_memcpy ( pControlConfig->ibConfig.connData.nodename, + g_vnic.host_name, + min( sizeof( g_vnic.host_name ), + sizeof( pControlConfig->ibConfig.connData.nodename )) ); + + pControlConfig->numRecvs = pControlConfig->ibConfig.numRecvs; + + pControlConfig->inicInstance = pControlConfig->ibConfig.connData.inicInstance; + pControlConfig->maxAddressEntries = (uint16_t)p_adapter->params.MaxAddressEntries; + pControlConfig->minAddressEntries = (uint16_t)p_adapter->params.MinAddressEntries; + pControlConfig->reqRetryCount = (uint8_t)p_adapter->params.ControlReqRetryCount; + pControlConfig->rspTimeout = p_adapter->params.ControlRspTimeout; + + pDataConfig->ibConfig.sid = 0; /* will set it later, from svc entries */ + pDataConfig->ibConfig.connData.pathId = get_time_stamp_ms(); + pDataConfig->ibConfig.connData.inicInstance = pControlConfig->inicInstance; + pDataConfig->ibConfig.connData.pathNum = 0; + + pDataConfig->ibConfig.retryCount = p_adapter->params.RetryCount; + pDataConfig->ibConfig.rnrRetryCount = p_adapter->params.RetryCount; + pDataConfig->ibConfig.minRnrTimer = (uint8_t)p_adapter->params.MinRnrTimer; + + /* + * NOTE: The numRecvs size assumes that the EIOC could + * RDMA enough packets to fill all of the host recv + * pool entries, plus send a kick message after each + * packet, plus RDMA new buffers for the size of + * the EIOC recv buffer pool, plus send kick messages + * after each MinHostUpdateSz of new buffers all + * before the Host can even pull off the first completed + * receive off the completion queue, and repost the + * receive. NOT LIKELY! + */ + pDataConfig->ibConfig.numRecvs = p_adapter->params.HostRecvPoolEntries + + ( p_adapter->params.MaxEiocPoolSz / p_adapter->params.MinHostUpdateSz ); + +#if LIMIT_OUTSTANDING_SENDS + + pDataConfig->ibConfig.numSends = (2 * p_adapter->params.NotifyBundleSz ) + + ( p_adapter->params.HostRecvPoolEntries / p_adapter->params.MinEiocUpdateSz ) + 1; + +#else /* !defined(LIMIT_OUTSTANDING_SENDS) */ + /* + * NOTE: The numSends size assumes that the HOST could + * post RDMA sends for every single buffer in the EIOCs + * receive pool, and allocate a full complement of + * receive buffers on the host, and RDMA free buffers + * every MinEiocUpdateSz entries all before the HCA + * can complete a single RDMA transfer. VERY UNLIKELY, + * BUT NOT COMPLETELY IMPOSSIBLE IF THERE IS AN IB + * PROBLEM! + */ + pDataConfig->ibConfig.numSends = p_adapter->params.MaxEiocPoolSz + + ( p_adapter->params.HostRecvPoolEntries / p_adapter->params.MinEiocUpdateSz ) + 1; + +#endif /* !defined(LIMIT_OUTSTANDING_SENDS) */ + + pDataConfig->ibConfig.recvScatter = 1; /* Not configurable */ + pDataConfig->ibConfig.sendGather = MAX_NUM_SGE; /* Not configurable */ + + pDataConfig->numRecvs = pDataConfig->ibConfig.numRecvs; + pDataConfig->pathId = pDataConfig->ibConfig.connData.pathId; + + pDataConfig->hostMin.sizeRecvPoolEntry = + (uint32_t)BUFFER_SIZE(ETH_VLAN_HLEN + p_adapter->params.MinMtu); + pDataConfig->hostMax.sizeRecvPoolEntry = + (uint32_t)BUFFER_SIZE(ETH_VLAN_HLEN + p_adapter->params.MaxMtu); + pDataConfig->eiocMin.sizeRecvPoolEntry = + (uint32_t)BUFFER_SIZE(ETH_VLAN_HLEN + p_adapter->params.MinMtu); + pDataConfig->eiocMax.sizeRecvPoolEntry = MAX_PARAM_VALUE; + + pDataConfig->hostRecvPoolEntries = p_adapter->params.HostRecvPoolEntries; + pDataConfig->notifyBundle = p_adapter->params.NotifyBundleSz; + + pDataConfig->hostMin.numRecvPoolEntries = p_adapter->params.MinHostPoolSz; + pDataConfig->hostMax.numRecvPoolEntries = MAX_PARAM_VALUE; + pDataConfig->eiocMin.numRecvPoolEntries = p_adapter->params.MinEiocPoolSz; + pDataConfig->eiocMax.numRecvPoolEntries = p_adapter->params.MaxEiocPoolSz; + + pDataConfig->hostMin.timeoutBeforeKick = p_adapter->params.MinHostKickTimeout; + pDataConfig->hostMax.timeoutBeforeKick = p_adapter->params.MaxHostKickTimeout; + pDataConfig->eiocMin.timeoutBeforeKick = 0; + pDataConfig->eiocMax.timeoutBeforeKick = MAX_PARAM_VALUE; + + pDataConfig->hostMin.numRecvPoolEntriesBeforeKick = p_adapter->params.MinHostKickEntries; + pDataConfig->hostMax.numRecvPoolEntriesBeforeKick = p_adapter->params.MaxHostKickEntries; + pDataConfig->eiocMin.numRecvPoolEntriesBeforeKick = 0; + pDataConfig->eiocMax.numRecvPoolEntriesBeforeKick = MAX_PARAM_VALUE; + + pDataConfig->hostMin.numRecvPoolBytesBeforeKick = p_adapter->params.MinHostKickBytes; + pDataConfig->hostMax.numRecvPoolBytesBeforeKick = p_adapter->params.MaxHostKickBytes; + pDataConfig->eiocMin.numRecvPoolBytesBeforeKick = 0; + pDataConfig->eiocMax.numRecvPoolBytesBeforeKick = MAX_PARAM_VALUE; + + pDataConfig->hostMin.freeRecvPoolEntriesPerUpdate = p_adapter->params.MinHostUpdateSz; + pDataConfig->hostMax.freeRecvPoolEntriesPerUpdate = p_adapter->params.MaxHostUpdateSz; + pDataConfig->eiocMin.freeRecvPoolEntriesPerUpdate = p_adapter->params.MinEiocUpdateSz; + pDataConfig->eiocMax.freeRecvPoolEntriesPerUpdate = p_adapter->params.MaxEiocUpdateSz; + + VNIC_EXIT( VNIC_DBG_VIPORT ); + return TRUE; +} + +static BOOLEAN config_isValid(ViportConfig_t *pConfig) +{ + UNREFERENCED_PARAMETER( pConfig ); + return TRUE; +} + + +void +viport_cleanup( + viport_t *p_viport ) +{ + VNIC_ENTER( VNIC_DBG_VIPORT ); + + if( p_viport ) + { + if( InterlockedExchange( (volatile LONG *)&p_viport->disconnect, TRUE ) ) + { + return; + } + + VNIC_TRACE(VNIC_DBG_VIPORT, + ("IOC[%d]viport cleanup\n", p_viport->ioc_num )); + + data_disconnect( &p_viport->data ); + + control_cleanup( &p_viport->control ); + + data_cleanup( &p_viport->data ); + + if( p_viport->macAddresses != NULL ) + { + NdisFreeMemory( p_viport->macAddresses, + p_viport->numMacAddresses * sizeof(Inic_AddressOp_t), 0 ); + } + + cl_timer_destroy( &p_viport->timer ); + + NdisFreeMemory( p_viport, sizeof(viport_t), 0 ); + p_viport = NULL; + } + + VNIC_EXIT( VNIC_DBG_VIPORT ); + return; +} + +BOOLEAN +viport_setParent( + IN viport_t *p_viport, + IN Netpath_t *pNetpath ) +{ + VNIC_ENTER( VNIC_DBG_VIPORT ); + + + if(p_viport->p_netpath != NULL) + { + return FALSE; + } + + p_viport->p_netpath = pNetpath; + + VNIC_EXIT( VNIC_DBG_VIPORT ); + return TRUE; +} + +BOOLEAN +viport_unsetParent( + IN viport_t *p_viport ) +{ + if( !p_viport || + !p_viport->p_netpath ) + { + return FALSE; + } + InterlockedExchange( &p_viport->p_netpath->carrier, FALSE ); + p_viport->p_netpath->pViport = NULL; + p_viport->p_netpath = NULL; + + if( p_viport->state == VIPORT_CONNECTED ) + { + p_viport->p_adapter->num_paths--; + } + return TRUE; +} + + +NDIS_STATUS +viport_setLink( + IN viport_t *p_viport, + IN uint8_t flags, + IN uint16_t mtu , + IN BOOLEAN sync ) +{ + + NDIS_STATUS status = NDIS_STATUS_SUCCESS; + + VNIC_ENTER( VNIC_DBG_VIPORT ); + + if( mtu > data_maxMtu(&p_viport->data) ) + { + viport_failure(p_viport); + VNIC_TRACE_EXIT( VNIC_DBG_ERROR, + ("IOC[%d] Configuration error. Mtu of %d unsupported\n", p_viport->ioc_num, mtu ) ); + return NDIS_STATUS_FAILURE; + } + + NdisAcquireSpinLock( &p_viport->lock ); + + if( ( (p_viport->newFlags & flags ) != flags ) || + ( p_viport->newMtu != mtu ) ) + { + p_viport->newFlags = flags; + p_viport->newMtu = mtu; + InterlockedOr( &p_viport->updates, NEED_LINK_CONFIG ); + + NdisReleaseSpinLock( &p_viport->lock ); + + status = _viport_process_query( p_viport, sync ); + } + else + NdisReleaseSpinLock( &p_viport->lock ); + + VNIC_EXIT( VNIC_DBG_VIPORT ); + return status; +} + +BOOLEAN +viport_setUnicast( + IN viport_t* const p_viport, + IN uint8_t *p_address ) +{ + NDIS_STATUS status = NDIS_STATUS_SUCCESS; + + VNIC_ENTER( VNIC_DBG_VIPORT ); + + if( !p_viport ) + return FALSE; + + NdisAcquireSpinLock( &p_viport->lock ); + + if( p_viport->macAddresses == NULL ) + { + NdisReleaseSpinLock( &p_viport->lock ); + return FALSE; + } + + if( cl_memcmp(p_viport->macAddresses[UNICAST_ADDR].address, + p_address, MAC_ADDR_LEN ) ) + { + + cl_memcpy( p_viport->macAddresses[UNICAST_ADDR].address, + p_address, MAC_ADDR_LEN ); + + VNIC_TRACE( VNIC_DBG_VIPORT, + ("Change Viport MAC From : %02x %02x %02x %02x %02x %02x -> to : %02x %02x %02x %02x %02x %02x\n", + p_viport->hwMacAddress[0], p_viport->hwMacAddress[1], p_viport->hwMacAddress[2], + p_viport->hwMacAddress[3], p_viport->hwMacAddress[4], p_viport->hwMacAddress[5], + p_viport->macAddresses[UNICAST_ADDR].address[0], p_viport->macAddresses[UNICAST_ADDR].address[1], + p_viport->macAddresses[UNICAST_ADDR].address[2], p_viport->macAddresses[UNICAST_ADDR].address[3], + p_viport->macAddresses[UNICAST_ADDR].address[4], p_viport->macAddresses[UNICAST_ADDR].address[5] + ) ); + + NdisMoveMemory( p_viport->hwMacAddress, + p_viport->macAddresses[UNICAST_ADDR].address, MAC_ADDR_LEN ); + + p_viport->macAddresses[UNICAST_ADDR].operation = INIC_OP_SET_ENTRY; + + InterlockedOr( &p_viport->updates, NEED_ADDRESS_CONFIG ); + + NdisReleaseSpinLock( &p_viport->lock ); + + status = _viport_process_query( p_viport, FALSE ); + if( status != NDIS_STATUS_SUCCESS && + status != NDIS_STATUS_PENDING ) + { + VNIC_TRACE_EXIT( VNIC_DBG_ERROR, ("Viport MAC set failed\n") ); + return FALSE; + } + } + + NdisReleaseSpinLock( &p_viport->lock ); + + VNIC_EXIT( VNIC_DBG_VIPORT ); + return TRUE; +} + + +/* Returns flags for state machine operations. */ +NDIS_STATUS +viport_setMulticast( + IN viport_t* const p_viport ) +{ + vnic_adapter_t *p_adapter = p_viport->p_adapter; + uint32_t updates = 0; + int i; + NDIS_STATUS status; + + VNIC_ENTER( VNIC_DBG_VIPORT ); + + NdisAcquireSpinLock( &p_viport->lock ); + + if( p_viport->macAddresses == NULL ) + { + NdisReleaseSpinLock( &p_viport->lock ); + return NDIS_STATUS_NOT_ACCEPTED; + } + + ASSERT( (p_viport->updates & ~MCAST_OVERFLOW) == 0 ); + + if( p_adapter->mc_count == 0 ) + { + /* invalidate all entries for the remote */ + for (i = MCAST_ADDR_START; + i < min( MAX_ADDR_ARRAY, p_viport->numMacAddresses ); i++ ) + { + p_viport->macAddresses[i].valid = 0; + p_viport->macAddresses[i].operation = INIC_OP_SET_ENTRY; + } + /* do we have to report to remote ? */ + p_viport->updates = 0; + NdisReleaseSpinLock( &p_viport->lock ); + return NDIS_STATUS_SUCCESS; + } + + if( p_adapter->mc_count > p_viport->numMacAddresses - MCAST_ADDR_START ) + { + updates |= NEED_LINK_CONFIG | MCAST_OVERFLOW; + } + else + { + if( InterlockedAnd( + &p_viport->updates, ~MCAST_OVERFLOW ) & MCAST_OVERFLOW ) + { + updates |= NEED_LINK_CONFIG; + } + /* Brute force algorithm */ + for (i = MCAST_ADDR_START; + i < min( MAX_ADDR_ARRAY, p_adapter->mc_count + MCAST_ADDR_START ); + i++ ) + { + if( p_viport->macAddresses[i].valid && + NdisEqualMemory( p_viport->macAddresses[i].address, + p_adapter->mcast_array[i - MCAST_ADDR_START].addr, + MAC_ADDR_LEN ) ) + { + continue; + } + + NdisMoveMemory( &p_viport->macAddresses[i].address, + p_adapter->mcast_array[i - MCAST_ADDR_START].addr, + MAC_ADDR_LEN ); + + p_viport->macAddresses[i].valid = 1; + p_viport->macAddresses[i].operation = INIC_OP_SET_ENTRY; + + updates |= NEED_ADDRESS_CONFIG; + } + for (; i < min( MAX_ADDR_ARRAY, p_viport->numMacAddresses ); i++ ) + { + if( !p_viport->macAddresses[i].valid ) + continue; + + updates |= NEED_ADDRESS_CONFIG; + + p_viport->macAddresses[i].valid = 0; + p_viport->macAddresses[i].operation = INIC_OP_SET_ENTRY; + } + } + + /* + * Now that the mac array is setup, we can set the update bits + * to send the request. + */ + InterlockedOr( &p_viport->updates, updates ); + NdisReleaseSpinLock( &p_viport->lock ); + + status = _viport_process_query( p_viport, FALSE ); + + VNIC_EXIT( VNIC_DBG_VIPORT ); + return status; +} + +NDIS_STATUS +viport_getStats( + IN viport_t *p_viport ) +{ + uint64_t stats_update_ms; + NDIS_STATUS status = STATUS_SUCCESS; + + VNIC_ENTER( VNIC_DBG_VIPORT ); + + stats_update_ms = get_time_stamp_ms(); + + if( stats_update_ms > p_viport->lastStatsTime + p_viport->port_config.statsInterval ) + { + p_viport->lastStatsTime = (uint32_t)stats_update_ms; + + InterlockedOr( &p_viport->updates, NEED_STATS ); + + status = _viport_process_query( p_viport, FALSE ); + if ( status != NDIS_STATUS_SUCCESS ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("Query NEED_STATS Failed\n") ); + } + } + + VNIC_EXIT( VNIC_DBG_VIPORT ); + return status; +} + + +BOOLEAN +viport_xmitPacket( + IN viport_t* const p_viport, + IN NDIS_PACKET* const p_packet ) +{ + BOOLEAN status; + LIST_ENTRY *p_list_item; + NDIS_PACKET *p_pending_packet; + vnic_adapter_t* p_adapter; + + VNIC_ENTER( VNIC_DBG_VIPORT ); + + NdisAcquireSpinLock( &p_viport->lock ); + + p_adapter = p_viport->p_netpath->p_adapter; + + while( ( p_list_item = NdisInterlockedRemoveHeadList( + &p_adapter->send_pending_list, + &p_adapter->pending_list_lock ) ) != NULL ) + { + p_pending_packet = VNIC_PACKET_FROM_LIST_ITEM( p_list_item ); + + status = data_xmitPacket( &p_viport->data, p_pending_packet ); + if( !status ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("IOC[%d] Xmit Pending Packet failed\n", p_viport->ioc_num )); + + /* put it back on pending list - will complete it on cleanup */ + NdisInterlockedInsertTailList( + &p_adapter->send_pending_list, + VNIC_LIST_ITEM_FROM_PACKET( p_pending_packet ), + &p_adapter->pending_list_lock ); + /*do not try to send packet, just exit */ + goto err; + } + } + + /* send a packet */ + status = data_xmitPacket( &p_viport->data, p_packet ); + if( status ) + { + NdisReleaseSpinLock( &p_viport->lock ); + + VNIC_EXIT( VNIC_DBG_VIPORT ); + return status; + } + +err: + NdisInterlockedInsertTailList( + &p_adapter->send_pending_list, + VNIC_LIST_ITEM_FROM_PACKET( p_packet ), + &p_adapter->pending_list_lock ); + + viport_stopXmit( p_viport ); + + NdisReleaseSpinLock( &p_viport->lock ); + + VNIC_EXIT( VNIC_DBG_VIPORT ); + return status; +} + +void +viport_cancel_xmit( + viport_t *p_viport, + PVOID cancel_id ) +{ + NDIS_PACKET *p_packet; + LIST_ENTRY *p_list_item; + LIST_ENTRY *p_list; + PVOID _id; + vnic_adapter_t* p_adapter; + + NdisAcquireSpinLock( &p_viport->lock ); + + p_adapter = p_viport->p_netpath->p_adapter; + p_list = &p_adapter->send_pending_list; + + while( !IsListEmpty( &p_adapter->send_pending_list ) ) + { + p_list_item = p_list->Flink; + + if ( p_list_item->Flink == &p_adapter->send_pending_list ) + break; + + p_packet = VNIC_PACKET_FROM_LIST_ITEM( p_list_item ); + + _id = NdisGetPacketCancelId( p_packet ); + + if( _id == cancel_id ) + { + NdisInterlockedRemoveHeadList( p_list, &p_adapter->pending_list_lock ); + NdisInterlockedInsertTailList( &p_adapter->cancel_send_list, p_list_item, + &p_adapter->cancel_list_lock ); + p_list_item = p_list->Flink; + } + else + { + p_list = p_list_item; + } + } + + while( !IsListEmpty( &p_adapter->cancel_send_list ) ) + { + p_list_item = NdisInterlockedRemoveHeadList( &p_adapter->cancel_send_list, + &p_adapter->cancel_list_lock ); + + p_packet = VNIC_PACKET_FROM_LIST_ITEM( p_list_item ); + + if( p_packet ) + { + NDIS_SET_PACKET_STATUS( p_packet, NDIS_STATUS_REQUEST_ABORTED ); + NdisMSendComplete( p_adapter->h_handle, p_packet, NDIS_STATUS_REQUEST_ABORTED ); + } + } + + NdisReleaseSpinLock( &p_viport->lock ); +} + +void +viport_linkUp(viport_t *p_viport) +{ + VNIC_ENTER( VNIC_DBG_VIPORT ); + + netpath_linkUp( p_viport->p_netpath ); + + VNIC_EXIT( VNIC_DBG_VIPORT ); + return; +} + +void +viport_linkDown(viport_t *p_viport) +{ + VNIC_ENTER( VNIC_DBG_VIPORT ); + + netpath_linkDown( p_viport->p_netpath ); + + VNIC_EXIT( VNIC_DBG_VIPORT ); + return; +} + +void +viport_stopXmit(viport_t *p_viport) +{ + VNIC_ENTER( VNIC_DBG_VIPORT ); + netpath_stopXmit( p_viport->p_netpath ); + VNIC_EXIT( VNIC_DBG_VIPORT ); + return; +} + +void +viport_restartXmit(viport_t *p_viport) +{ + VNIC_ENTER( VNIC_DBG_VIPORT ); + netpath_restartXmit( p_viport->p_netpath ); + VNIC_EXIT( VNIC_DBG_VIPORT ); + return; +} + +void +viport_recvPacket( + IN viport_t *p_viport, + IN NDIS_PACKET **pp_pkt_arr, + IN uint32_t num_packets ) +{ + VNIC_ENTER( VNIC_DBG_VIPORT ); + netpath_recvPacket(p_viport->p_netpath, pp_pkt_arr, num_packets ); + VNIC_EXIT( VNIC_DBG_VIPORT ); + return; +} + + +void +viport_failure( + IN viport_t *p_viport ) +{ + VNIC_ENTER( VNIC_DBG_VIPORT ); + + if( !p_viport || !p_viport->p_netpath ) + return; + + InterlockedExchange( &p_viport->p_netpath->carrier, FALSE ); + + if( InterlockedExchange( (volatile LONG*)&p_viport->errored, TRUE ) == FALSE ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("IOC[%d] %s instance %d FAILED\n", + p_viport->ioc_num, + netpath_to_string( p_viport->p_netpath ), + p_viport->p_netpath->instance )); + viport_stopXmit( p_viport ); + viport_linkDown( p_viport ); + } + + VNIC_EXIT( VNIC_DBG_VIPORT ); +} + + +void +viport_timeout( + IN void *context ) +{ + viport_t *p_viport = (viport_t *)context; + CL_ASSERT( p_viport ); + + if( InterlockedExchange( &p_viport->timerActive, FALSE ) == TRUE ) + { + // did we send a query and got response ? + if( p_viport->link_hb_state != LINK_HEARTBEATRSP && + !p_viport->hb_send_pending ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("IOC[%d] instance %d HEARTBEAT TIMEOUT\n", + p_viport->ioc_num, + p_viport->p_netpath->instance )); + viport_failure( p_viport ); + return; + } + /* send heartbeat message again */ + else if( !p_viport->errored && + p_viport->state == VIPORT_CONNECTED ) + { + viport_timer( p_viport, p_viport->port_config.hbInterval ); + } + } +} + + +void +viport_timer( + IN viport_t *p_viport, + IN int timeout ) +{ + ib_api_status_t ib_status; + + VNIC_ENTER( VNIC_DBG_VIPORT ); + + if( !p_viport->errored ) + { + p_viport->link_hb_state = LINK_HEARTBEATREQ; + InterlockedExchange( &p_viport->timerActive, TRUE ); + + /* we can send now */ + if( !p_viport->control.reqOutstanding ) + { + p_viport->hb_send_pending = FALSE; + cl_timer_start( &p_viport->timer, (uint32_t)timeout ); + + ib_status = control_heartbeatReq( &p_viport->control, + p_viport->port_config.hbTimeout ); + + if( ib_status != IB_SUCCESS ) + { + viport_timerStop( p_viport ); + VNIC_TRACE( VNIC_DBG_ERROR, + ("IOC[%d] instance %d HEARTBEAT send failed\n", + p_viport->ioc_num, + p_viport->p_netpath->instance )); + viport_failure( p_viport ); + return; + } + } + /* schedule send on next timeout */ + else + { + p_viport->hb_send_pending = TRUE; + cl_timer_start(&p_viport->timer, (uint32_t)timeout ); + } + } + + VNIC_EXIT( VNIC_DBG_VIPORT ); +} + + +void +viport_timerStop( + IN viport_t *p_viport ) +{ + VNIC_ENTER( VNIC_DBG_VIPORT ); + + if( p_viport ) + { + if( InterlockedExchange( &p_viport->timerActive, FALSE ) == TRUE ) + { + cl_timer_stop( &p_viport->timer ); + } + } + + VNIC_EXIT( VNIC_DBG_VIPORT ); + return; +} + +static ib_api_status_t +viport_initMacAddresses( + IN viport_t *p_viport ) +{ + int i, size; + NDIS_STATUS status; + VNIC_ENTER( VNIC_DBG_VIPORT ); + + size = p_viport->numMacAddresses * sizeof(Inic_AddressOp_t); + status = NdisAllocateMemoryWithTag( &p_viport->macAddresses, size , 'acam' ); + + if ( status != NDIS_STATUS_SUCCESS ) + { + VNIC_TRACE_EXIT( VNIC_DBG_ERROR, + ("Failed allocating MAC address table size %d\n", size) ); + return IB_INSUFFICIENT_MEMORY; + } + + NdisZeroMemory( p_viport->macAddresses, size ); + + NdisAcquireSpinLock( &p_viport->lock ); + for( i = 0; i < p_viport->numMacAddresses; i++ ) + { + p_viport->macAddresses[i].index = (uint16_t)i; + p_viport->macAddresses[i].vlan = p_viport->defaultVlan; + } + + NdisFillMemory( p_viport->macAddresses[BROADCAST_ADDR].address, + MAC_ADDR_LEN, 0xFF ); + p_viport->macAddresses[BROADCAST_ADDR].valid = TRUE; + + NdisMoveMemory( p_viport->macAddresses[UNICAST_ADDR].address, + p_viport->hwMacAddress, MAC_ADDR_LEN ); + + p_viport->macAddresses[UNICAST_ADDR].valid = TRUE; + + if( !p_viport->p_adapter->macSet ) + { + p_viport->p_adapter->macSet = TRUE; + } + + NdisReleaseSpinLock( &p_viport->lock ); + + VNIC_EXIT( VNIC_DBG_VIPORT ); + return IB_SUCCESS; +} + + +ib_api_status_t +viport_control_connect( + IN viport_t* const p_viport ) +{ + ib_api_status_t ib_status; + cl_status_t cl_status; + + VNIC_ENTER( VNIC_DBG_INIT ); + + ib_status = control_init( &p_viport->control, p_viport, + &p_viport->port_config.controlConfig, p_viport->portGuid ); + if( ib_status != IB_SUCCESS ) + { + VNIC_EXIT( VNIC_DBG_VIPORT ); + return ib_status; + } + + ib_status = ibqp_connect( &p_viport->control.qp ); + if( ib_status != IB_SUCCESS ) + { + VNIC_TRACE_EXIT( VNIC_DBG_ERROR, + ("control QP connect failed\n")); + control_cleanup( &p_viport->control ); + return ib_status; + } + + InterlockedExchange( (volatile LONG*)&p_viport->linkState, + (LONG)LINK_INITINICREQ ); + + ib_status = control_initInicReq( &p_viport->control ); + if( ib_status != IB_SUCCESS ) + { + VNIC_TRACE_EXIT( VNIC_DBG_ERROR, + ("CMD_INIT_INIC REQ failed\n") ); + + control_cleanup( &p_viport->control ); + return ib_status; + } + cl_status = cl_event_wait_on( &p_viport->sync_event, + (p_viport->control.p_conf->rspTimeout << 11), FALSE ); + + if( p_viport->linkState != LINK_INITINICRSP ) + { + VNIC_TRACE_EXIT( VNIC_DBG_ERROR, + ("CMD_INIT_INIC RSP failed: return linkstate: %d, cl_status: %d\n", + p_viport->linkState, cl_status )); + + ib_status = IB_INSUFFICIENT_RESOURCES; + control_cleanup( &p_viport->control ); + return ib_status; + } + + vnic_resume_oids( p_viport->p_adapter ); + + ib_status = viport_initMacAddresses( p_viport ); + if( ib_status != IB_SUCCESS ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("Init MAC Addresses failed\n")); + control_cleanup( &p_viport->control ); + } + + VNIC_EXIT( VNIC_DBG_INIT ); + return ib_status; +} + +ib_api_status_t +viport_data_connect( + IN viport_t* const p_viport ) +{ + NDIS_STATUS status; + ib_api_status_t ib_status; + + VNIC_ENTER( VNIC_DBG_INIT ); + + ib_status = data_init( &p_viport->data, + &p_viport->port_config.dataConfig, + p_viport->portGuid ); + if( ib_status != IB_SUCCESS ) + { + VNIC_TRACE( VNIC_DBG_ERROR, ("Data init returned %s\n", + p_viport->p_adapter->ifc.get_err_str( ib_status )) ); + return ib_status; + } + InterlockedExchange( (volatile LONG*)&p_viport->linkState, + (LONG)LINK_CONFIGDATAPATHREQ ); + + ib_status = control_configDataPathReq( &p_viport->control, + data_pathId(&p_viport->data ), data_hostPoolMax( &p_viport->data ), + data_eiocPoolMax( &p_viport->data ) ); + if( ib_status != IB_SUCCESS ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("command CONFIGDATAPATH REQ failed\n")); + return ib_status; + } + cl_event_wait_on( &p_viport->sync_event, + (p_viport->control.p_conf->rspTimeout << 11), TRUE ); + + if( p_viport->linkState != LINK_CONFIGDATAPATHRSP ) + { + VNIC_TRACE( VNIC_DBG_ERROR, + ("failed to get CONFIGDATAPATH RSP\n")); + return IB_INSUFFICIENT_RESOURCES; + } + + ib_status = data_connect( &p_viport->data ); + if( ib_status != IB_SUCCESS ) + { + VNIC_EXIT( VNIC_DBG_INIT ); + return ib_status; + } + cl_event_wait_on( &p_viport->sync_event, + (p_viport->control.p_conf->rspTimeout << 11), TRUE ); + if( p_viport->data.qp.qpState != IB_ATTACHED ) + { + VNIC_EXIT( VNIC_DBG_INIT ); + return IB_ERROR; + } + InterlockedExchange( (volatile LONG*)&p_viport->linkState, + (LONG)LINK_XCHGPOOLREQ ); + ib_status = control_exchangePoolsReq( &p_viport->control, + data_localPoolAddr(&p_viport->data), + data_localPoolRkey(&p_viport->data) ); + if( ib_status != IB_SUCCESS ) + { + VNIC_TRACE_EXIT( VNIC_DBG_ERROR, + ("command XCHGPOOL REQ failed\n")); + return ib_status; + } + cl_event_wait_on( &p_viport->sync_event, + (p_viport->control.p_conf->rspTimeout << 11), TRUE ); + + if( p_viport->linkState != LINK_XCHGPOOLRSP ) + { + VNIC_TRACE_EXIT( VNIC_DBG_ERROR, + ("failed to get LINK_XCHGPOOL RSP\n")); + return IB_ERROR; + } + + InterlockedExchange( (volatile LONG*)&p_viport->linkState, + (LONG)LINK_INITIALIZED ); + + p_viport->state = VIPORT_CONNECTED; + + ib_status = data_connected( &p_viport->data ); + if( ib_status != IB_SUCCESS ) + { + VNIC_TRACE_EXIT( VNIC_DBG_ERROR, + ("Alloc/Send Recv Buffers failed\n")); + return ib_status; + } + + p_viport->flags = 0; + + if( p_viport->p_netpath == p_viport->p_adapter->p_currentPath ) + { + status = viport_setLink( p_viport, + INIC_FLAG_ENABLE_NIC| INIC_FLAG_SET_MTU, + (uint16_t)p_viport->p_adapter->params.MinMtu, TRUE ); + if( status != NDIS_STATUS_SUCCESS ) + { + VNIC_TRACE_EXIT( VNIC_DBG_ERROR, + ("failed to set Link flags\n")); + return IB_ERROR; + } + + /* start periodic heartbeat timer for active path */ + if( p_viport->port_config.hbInterval ) + { + viport_timer( p_viport, p_viport->port_config.hbInterval ); + } + } + VNIC_EXIT( VNIC_DBG_INIT ); + return IB_SUCCESS; +} + + +NDIS_STATUS +_viport_process_query( + IN viport_t* const p_viport, + IN BOOLEAN sync ) +{ + NDIS_STATUS status; + ib_api_status_t ib_status; + LinkState_t expected_state = 0; + + VNIC_ENTER( VNIC_DBG_VIPORT ); + + if( p_viport->errored || + p_viport->p_adapter->pnp_state == IB_PNP_IOC_REMOVE ) + { + VNIC_TRACE( VNIC_DBG_WARN, + ("IOC[%d] updates = %#x packet_filter = %#x, query: %#x(%d) set: %#x(%d)\n", + p_viport->ioc_num, + p_viport->updates, + p_viport->p_adapter->packet_filter, + p_viport->p_adapter->query_oid.oid, + p_viport->p_adapter->pending_query, + p_viport->p_adapter->set_oid.oid, + p_viport->p_adapter->pending_set )); + + VNIC_TRACE_EXIT( VNIC_DBG_WARN, ("IOC[%d] in REMOVE or invalid state.\n", + p_viport->ioc_num )); + + return NDIS_STATUS_NOT_ACCEPTED; + } + + // Check for updates. Note that unless sync is set to TRUE, this + // is the only way for this function to return success. + if( !InterlockedCompareExchange( &p_viport->updates, 0, 0 ) ) + { + /* now can restart heartbeats */ + if( !p_viport->timerActive && + p_viport->port_config.hbInterval ) + { + viport_timer( p_viport, p_viport->port_config.hbInterval ); + } + return NDIS_STATUS_SUCCESS; + } + + else + { + /* stop heartbeat timer to serve another query */ + viport_timerStop( p_viport ); + } + + if( sync ) + { + status = NDIS_STATUS_SUCCESS; + InterlockedOr( &p_viport->updates, SYNC_QUERY ); + } + else + { + status = NDIS_STATUS_PENDING; + } + + // Handle update bits one at a time. + if( p_viport->updates & NEED_ADDRESS_CONFIG ) + { + VNIC_TRACE( VNIC_DBG_CONF,("QUERY NEED_ADDRESS_CONFIG\n")); + + NdisAcquireSpinLock(&p_viport->lock ); + + p_viport->linkState = LINK_CONFIGADDRSREQ; + ib_status = control_configAddrsReq( + &p_viport->control, p_viport->macAddresses, + p_viport->numMacAddresses, &p_viport->addrs_query_done ); + + NdisReleaseSpinLock( &p_viport->lock ); + + if ( ib_status != IB_SUCCESS ) + { + InterlockedAnd( &p_viport->updates, ~NEED_ADDRESS_CONFIG ); + VNIC_EXIT( VNIC_DBG_VIPORT ); + return NDIS_STATUS_FAILURE; + } + expected_state = LINK_CONFIGADDRSRSP; + } + else if( p_viport->updates & NEED_LINK_CONFIG ) + { + VNIC_TRACE( VNIC_DBG_CONF, + ("QUERY NEED_LINK_CONFIG\n")); + + NdisAcquireSpinLock(&p_viport->lock ); + + p_viport->linkState = LINK_CONFIGLINKREQ; + + if( (InterlockedAnd( + &p_viport->updates, ~MCAST_OVERFLOW ) & MCAST_OVERFLOW ) ) + { + p_viport->newFlags |= INIC_FLAG_ENABLE_MCAST_ALL; + } + else + { + p_viport->newFlags &= ~INIC_FLAG_ENABLE_MCAST_ALL; + } + + if ( p_viport->mtu != p_viport->newMtu ) + { + p_viport->newFlags |= INIC_FLAG_SET_MTU; + p_viport->mtu = p_viport->newMtu; + } + if( ( p_viport->newFlags & INIC_FLAG_ENABLE_NIC ) && + ( p_viport->p_netpath != p_viport->p_adapter->p_currentPath ) ) + { + ASSERT(0); + } + + ib_status = control_configLinkReq( &p_viport->control, + p_viport->newFlags, p_viport->newMtu ); + + p_viport->newFlags &= ~INIC_FLAG_SET_MTU; + + NdisReleaseSpinLock( &p_viport->lock ); + + if( ib_status != IB_SUCCESS ) + { + InterlockedAnd( &p_viport->updates, ~NEED_LINK_CONFIG ); + VNIC_EXIT( VNIC_DBG_VIPORT ); + return NDIS_STATUS_FAILURE; + } + expected_state = LINK_CONFIGLINKRSP; + } + else if( p_viport->updates & NEED_STATS ) + { + // TODO: + VNIC_TRACE( VNIC_DBG_CONF, + ("QUERY NEED_STATS\n")); + + NdisAcquireSpinLock( &p_viport->lock ); + + p_viport->linkState = LINK_REPORTSTATREQ; + + ib_status = control_reportStatisticsReq( &p_viport->control ); + + NdisReleaseSpinLock( &p_viport->lock ); + + if( ib_status != IB_SUCCESS ) + { + InterlockedAnd( &p_viport->updates, ~NEED_STATS ); + VNIC_EXIT( VNIC_DBG_VIPORT ); + return NDIS_STATUS_FAILURE; + } + expected_state = LINK_REPORTSTATRSP; + } + + if( sync ) + { + cl_event_wait_on( &p_viport->sync_event, EVENT_NO_TIMEOUT, TRUE ); + + if( p_viport->linkState != expected_state ) + { + status = NDIS_STATUS_FAILURE; + VNIC_TRACE( VNIC_DBG_ERROR, + ("Link state error: expected %d but got %d\n", + expected_state, p_viport->linkState)); + } + } + VNIC_EXIT( VNIC_DBG_VIPORT ); + return status; +} + +BOOLEAN +viport_canTxCsum( + IN viport_t* p_viport ) +{ + if( !p_viport ) + return FALSE; + + return( BOOLEAN )( ( p_viport->featuresSupported & + ( INIC_FEAT_IPV4_HEADERS | + INIC_FEAT_IPV6_HEADERS | + INIC_FEAT_IPV4_CSUM_TX | + INIC_FEAT_TCP_CSUM_TX | + INIC_FEAT_UDP_CSUM_TX ) ) == + ( INIC_FEAT_IPV4_HEADERS | + INIC_FEAT_IPV6_HEADERS | + INIC_FEAT_IPV4_CSUM_TX | + INIC_FEAT_TCP_CSUM_TX | + INIC_FEAT_UDP_CSUM_TX ) ); +} + +BOOLEAN +viport_canRxCsum( + IN viport_t* p_viport ) +{ + if( !p_viport ) + return FALSE; + + return( BOOLEAN )( ( p_viport->featuresSupported & + ( INIC_FEAT_IPV4_HEADERS | + INIC_FEAT_IPV6_HEADERS | + INIC_FEAT_IPV4_CSUM_RX | + INIC_FEAT_TCP_CSUM_RX | + INIC_FEAT_UDP_CSUM_RX ) ) == + ( INIC_FEAT_IPV4_HEADERS | + INIC_FEAT_IPV6_HEADERS | + INIC_FEAT_IPV4_CSUM_RX | + INIC_FEAT_TCP_CSUM_RX | + INIC_FEAT_UDP_CSUM_RX ) ); +} diff --git a/trunk/ulp/qlgcvnic/kernel/vnic_viport.h b/trunk/ulp/qlgcvnic/kernel/vnic_viport.h new file mode 100644 index 00000000..b881e69f --- /dev/null +++ b/trunk/ulp/qlgcvnic/kernel/vnic_viport.h @@ -0,0 +1,396 @@ +/* + * Copyright (c) 2007 QLogic Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id$ + */ +#ifndef _VNIC_VIPORT_H_ +#define _VNIC_VIPORT_H_ + +typedef struct _mc_list { + uint8_t mc_addr[MAC_ADDR_LEN]; +} mc_list_t; + +typedef enum { + VIPORT_DISCONNECTED, + VIPORT_CONNECTED +} viport_state_t; + +typedef enum { + LINK_UNINITIALIZED, + LINK_INITIALIZE, + LINK_INITIALIZECONTROL, + LINK_INITIALIZEDATA, + LINK_CONTROLCONNECT, + LINK_CONTROLCONNECTWAIT, + LINK_INITINICREQ, + LINK_INITINICRSP, + LINK_BEGINDATAPATH, + LINK_CONFIGDATAPATHREQ, + LINK_CONFIGDATAPATHRSP, + LINK_DATACONNECT, + LINK_DATACONNECTWAIT, + LINK_XCHGPOOLREQ, + LINK_XCHGPOOLRSP, + LINK_INITIALIZED, + LINK_IDLE, + LINK_IDLING, + LINK_CONFIGLINKREQ, + LINK_CONFIGLINKRSP, + LINK_CONFIGADDRSREQ, + LINK_CONFIGADDRSRSP, + LINK_REPORTSTATREQ, + LINK_REPORTSTATRSP, + LINK_HEARTBEATREQ, + LINK_HEARTBEATRSP, + LINK_RESET, + LINK_RESETRSP, + LINK_RESETCONTROL, + LINK_RESETCONTROLRSP, + LINK_DATADISCONNECT, + LINK_CONTROLDISCONNECT, + LINK_CLEANUPDATA, + LINK_CLEANUPCONTROL, + LINK_DISCONNECTED, + LINK_RETRYWAIT +} LinkState_t; + +/* index entries */ +#define BROADCAST_ADDR 0 +#define UNICAST_ADDR 1 +#define MCAST_ADDR_START 2 +#define MAX_MCAST (MAX_ADDR_ARRAY - MCAST_ADDR_START) + +#define currentMacAddress macAddresses[UNICAST_ADDR].address + +#define NEED_STATS 0x00000001 +#define NEED_ADDRESS_CONFIG 0x00000002 +#define NEED_LINK_CONFIG 0x00000004 +#define MCAST_OVERFLOW 0x00000008 +#define SYNC_QUERY 0x80000000 + +typedef enum { + NETPATH_TS_IDLE, + NETPATH_TS_ACTIVE, + NETPATH_TS_EXPIRED +} netpathTS_t; + + +typedef struct { + LIST_ENTRY listPtrs; + struct _vnic_adapter *p_adapter; + uint8_t event_num; +} InicNPEvent_t; + +typedef enum { + NETPATH_PRIMARY = 1, + NETPATH_SECONDARY = 2 +} netpath_instance_t; + + +typedef struct Netpath { + volatile LONG carrier; + struct _vnic_adapter *p_adapter; + struct _viport *pViport; + ib_path_rec_t *p_path_rec; + uint64_t connectTime; + netpathTS_t timerState; + netpath_instance_t instance; +} Netpath_t; + +typedef enum { + WAIT, + DELAY, + NOW +} conn_wait_state_t; + +typedef struct _viport { + LIST_ENTRY listPtrs; + NDIS_SPIN_LOCK lock; + cl_obj_t obj; + struct _vnic_adapter *p_adapter; + struct Netpath *p_netpath; + struct ViportConfig port_config; + struct Control control; + struct Data data; + uint64_t iocGuid; + uint64_t portGuid; + uint32_t ioc_num; + // connected/disconnected state of control and data QPs. + viport_state_t state; + + // Control Path cmd state Query/Rsp + LinkState_t linkState; + LinkState_t link_hb_state; + Inic_CmdReportStatisticsRsp_t stats; + uint64_t lastStatsTime; + uint32_t featuresSupported; + uint8_t hwMacAddress[MAC_ADDR_LEN]; + uint16_t defaultVlan; + uint16_t numMacAddresses; + Inic_AddressOp_t *macAddresses; + int32_t addrs_query_done; + + // Indicates actions (to the VEx) that need to be taken. + volatile LONG updates; + + uint8_t flags; + uint8_t newFlags; + uint16_t mtu; + uint16_t newMtu; + uint32_t errored; + uint32_t disconnect; + volatile LONG timerActive; + cl_timer_t timer; + cl_event_t sync_event; + BOOLEAN hb_send_pending; +} viport_t; + + +BOOLEAN +viport_xmitPacket( + IN viport_t* const p_viport, + IN NDIS_PACKET* const p_pkt ); + +BOOLEAN +viport_config_defaults( + IN viport_t *p_viport ); + +uint32_t +viport_get_adapter_name( + IN viport_t *p_viport ); + +void +viport_cleanup( + IN viport_t *p_viport ); + +BOOLEAN +viport_setParent( + IN viport_t *pViport, + IN struct Netpath *pNetpath); + +NDIS_STATUS +viport_setLink( + IN viport_t *pViport, + IN uint8_t flags, + IN uint16_t mtu, + IN BOOLEAN sync ); + +NDIS_STATUS +viport_getStats( + IN viport_t *pViport ); + +void +viport_timer( + IN viport_t *p_viport, + IN int timeout ); + +void +viport_timerStop( + IN viport_t *p_viport ); + +void +viport_linkUp( + IN viport_t *pViport); + +void +viport_linkDown( + IN viport_t *pViport); + +void +viport_stopXmit( + IN viport_t *pViport); + +void +viport_restartXmit( + IN viport_t *pViport); + +void +viport_recvPacket( + IN viport_t *pViport, + IN NDIS_PACKET **p_pkt, + IN uint32_t num_pkts ); + +void +viport_failure( + IN viport_t *pViport); + +BOOLEAN +viport_setUnicast( + IN viport_t* const pViport, + IN uint8_t * pAddress); + +NDIS_STATUS +viport_setMulticast( + IN viport_t* const pViport ); + +void +netpath_init( + IN struct Netpath *pNetpath, + IN struct _vnic_adapter *p_adapter ); + +BOOLEAN +netpath_addPath( + IN struct Netpath *pNetpath, + IN viport_t *pViport); + +BOOLEAN +viport_unsetParent( + IN viport_t *pViport ); + +ib_api_status_t +viport_control_connect( + IN viport_t* const p_viport ); + +ib_api_status_t +viport_data_connect( + IN viport_t* const p_viport ); + +NDIS_STATUS +_viport_process_query( + IN viport_t* const p_viport, + IN BOOLEAN sync ); + +void +viport_cancel_xmit( + IN viport_t *p_viport, + IN void *p_cancel_id ); + +BOOLEAN +netpath_removePath( + IN struct Netpath *pNetpath, + IN viport_t *p_viport ); + +void +netpath_free( + IN struct Netpath *pNetpath ); + +BOOLEAN +netpath_getStats( + IN struct Netpath *pNetpath ); + +NDIS_STATUS +netpath_setMulticast( + IN struct Netpath *pNetpath ); + +int +netpath_maxMtu( + IN struct Netpath *pNetpath); + +BOOLEAN +netpath_linkDown( + IN Netpath_t* p_netpath ); + + +BOOLEAN +netpath_linkUp( + IN Netpath_t* p_netpath ); + +BOOLEAN +netpath_is_valid( + IN Netpath_t* const p_netpath ); + +BOOLEAN +netpath_is_connected( + IN Netpath_t* const p_netpath ); + +BOOLEAN +netpath_is_primary( + IN Netpath_t* const p_netpath ); + +BOOLEAN +netpath_xmitPacket( + IN struct Netpath* pNetpath, + IN NDIS_PACKET* const p_pkt ); + +void +netpath_cancel_xmit( + IN struct Netpath* p_netpath, + IN PVOID cancel_id ); + +void +netpath_recvPacket( + IN struct Netpath* pNetpath, + IN NDIS_PACKET** pp_pkt, + IN uint32_t num_packets); + +void +netpath_stopXmit( + IN struct Netpath *pNetpath ); + +void +netpath_restartXmit( + IN struct Netpath *pNetpath ); + +void +netpath_kick( + IN struct Netpath *pNetpath); + +void +netpath_timer( + IN struct Netpath *pNetpath, + IN int timeout); + +void +netpath_tx_timeout( + IN struct Netpath *pNetpath); + +const char* +netpath_to_string( + IN struct Netpath *pNetpath ); + +BOOLEAN +netpath_setUnicast( + IN Netpath_t* p_netpath, + IN uint8_t* p_address ); + +BOOLEAN +viport_canTxCsum( + IN viport_t* p_viport ); + +BOOLEAN +viport_canRxCsum( + IN viport_t* p_viport ); + +#define viport_portGuid(pViport) ((pViport)->portGuid) +#define viport_maxMtu(pViport) data_maxMtu(&(pViport)->data) + +#define viport_getHwAddr(pViport,pAddress) \ + cl_memcpy(pAddress, (pViport)->hwMacAddress, MAC_ADDR_LEN) + +#define viport_features(pViport) ( (pViport)->featuresSupported ) + +#define netpath_getHwAddr(pNetpath, pAddress) \ + viport_getHwAddr((pNetpath)->pViport, pAddress) + +#define netpath_canTxCsum(pNetpath) \ + viport_canTxCsum( (pNetpath)->pViport ) + +#define netpath_canRxCsum(pNetpath) \ + viport_canRxCsum( (pNetpath)->pViport ) + +#endif /* _VNIC_VIPORT_H_ */