From: tzachid Date: Thu, 25 Jun 2009 15:36:56 +0000 (+0000) Subject: [IPoIB NDIS 6.0 CM] X-Git-Url: https://openfabrics.org/gitweb/?a=commitdiff_plain;h=cc0909a02bb1201d424979b6d53efc9ae43b1a1f;p=~shefty%2Frdma-win.git [IPoIB NDIS 6.0 CM] Files renamed to .cpp Code cleaning (MLNX: 4521) git-svn-id: svn://openib.tc.cornell.edu/gen1@2270 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86 --- diff --git a/trunk/ulp/ipoib_NDIS6_CM/kernel/SOURCES b/trunk/ulp/ipoib_NDIS6_CM/kernel/SOURCES index a528904b..774f114b 100644 --- a/trunk/ulp/ipoib_NDIS6_CM/kernel/SOURCES +++ b/trunk/ulp/ipoib_NDIS6_CM/kernel/SOURCES @@ -19,13 +19,13 @@ ENABLE_EVENT_TRACING=1 SOURCES= ipoib_log.mc \ ipoib.rc \ - ipoib_driver.c \ - ipoib_adapter.c \ - ipoib_endpoint.c \ - ipoib_port.c \ - ipoib_ibat.c \ -# ipoib_cm.c \ - ipoib_xfr_mgr.c + ipoib_driver.cpp \ + ipoib_adapter.cpp \ + ipoib_endpoint.cpp \ + ipoib_port.cpp \ + ipoib_ibat.cpp \ +# ipoib_cm.cpp \ + ipoib_xfr_mgr.cpp INCLUDES=..;..\..\..\inc;..\..\..\inc\kernel; @@ -50,7 +50,7 @@ TARGETLIBS= \ C_DEFINES = $(C_DEFINES) -DEVENT_TRACING -RUN_WPP = $(SOURCES) -km -ext: .c .h .C .H \ +RUN_WPP = $(SOURCES) -km -ext: .c .cpp .h .C .CPP .H\ -scan:ipoib_debug.h \ -func:IPOIB_PRINT(LEVEL,FLAGS,(MSG,...)) \ -func:IPOIB_PRINT_EXIT(LEVEL,FLAGS,(MSG,...)) diff --git a/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_adapter.c b/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_adapter.c deleted file mode 100644 index 92747097..00000000 --- a/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_adapter.c +++ /dev/null @@ -1,1642 +0,0 @@ -/* - * Copyright (c) 2005 SilverStorm Technologies. All rights reserved. - * Copyright (c) 2006 Mellanox Technologies. All rights reserved. - * Portions Copyright (c) 2008 Microsoft 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: ipoib_adapter.c 4506 2009-06-23 14:40:54Z xalex $ - */ - - - -#include "ipoib_adapter.h" -#include "ipoib_port.h" -#include "ipoib_driver.h" -#include "ipoib_debug.h" - -#if defined(EVENT_TRACING) -#ifdef offsetof -#undef offsetof -#endif -#include "ipoib_adapter.tmh" -#endif - - -#define ITEM_POOL_START 16 -#define ITEM_POOL_GROW 16 - - -/* IB Link speeds in 100bps */ -#define ONE_X_IN_100BPS 25000000 -#define FOUR_X_IN_100BPS 100000000 -#define TWELVE_X_IN_100BPS 300000000 - - -/* Declarations */ -static void -adapter_construct( - IN ipoib_adapter_t* const p_adapter ); - - -static ib_api_status_t -adapter_init( - IN ipoib_adapter_t* const p_adapter ); - - -static void -__adapter_destroying( - IN cl_obj_t* const p_obj ); - - -static void -__adapter_free( - IN cl_obj_t* const p_obj ); - - -static ib_api_status_t -__ipoib_pnp_reg( - IN ipoib_adapter_t* const p_adapter, - IN ib_pnp_class_t flags ); - - -static void -__ipoib_pnp_dereg( - IN void* context ); - - -static void -__ipoib_adapter_reset( - IN void* context); - - -static ib_api_status_t -__ipoib_pnp_cb( - IN ib_pnp_rec_t *p_pnp_rec ); - - -void -ipoib_join_mcast( - IN ipoib_adapter_t* const p_adapter ); - - -/* Leaves all mcast groups when port goes down. */ -static void -ipoib_clear_mcast( - IN ipoib_port_t* const p_port ); - -NDIS_STATUS -ipoib_get_adapter_guids( - IN NDIS_HANDLE* const h_adapter, - IN OUT ipoib_adapter_t *p_adapter ); - -NDIS_STATUS -ipoib_get_adapter_params( - IN NDIS_HANDLE* const wrapper_config_context, - IN OUT ipoib_adapter_t *p_adapter, - OUT PUCHAR *p_mac, - OUT UINT *p_len); - - -/* Implementation */ -ib_api_status_t -ipoib_create_adapter( - IN NDIS_HANDLE wrapper_config_context, - IN void* const h_adapter, - OUT ipoib_adapter_t** const pp_adapter ) -{ - ipoib_adapter_t *p_adapter; - ib_api_status_t status; - cl_status_t cl_status; - PUCHAR mac; - UINT len; - - IPOIB_ENTER( IPOIB_DBG_INIT ); - - p_adapter = cl_zalloc( sizeof(ipoib_adapter_t) ); - if( !p_adapter ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed to allocate ipoib_adapter_t (%d bytes)", - sizeof(ipoib_adapter_t)) ); - return IB_INSUFFICIENT_MEMORY; - } - - adapter_construct( p_adapter ); - - p_adapter->h_adapter = h_adapter; - - p_adapter->p_ifc = cl_zalloc( sizeof(ib_al_ifc_t) ); - if( !p_adapter->p_ifc ) - { - __adapter_free( &p_adapter->obj ); - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ipoib_create_adapter failed to alloc ipoib_ifc_t %d bytes\n", - sizeof(ib_al_ifc_t)) ); - return IB_INSUFFICIENT_MEMORY; - } - - /* Get the CA and port GUID from the bus driver. */ - status = ipoib_get_adapter_guids( h_adapter, p_adapter ); - if( status != NDIS_STATUS_SUCCESS ) - { -ASSERT(FALSE); -//return NDIS_STATUS_SUCCESS; - __adapter_free( &p_adapter->obj ); - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ipoib_get_adapter_guids returned 0x%.8X.\n", status) ); - return status; - } - - IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, - ("Port %016I64x (CA %016I64x port %d) initializing\n", - p_adapter->guids.port_guid.guid, p_adapter->guids.ca_guid, - p_adapter->guids.port_num) ); - - cl_status = cl_obj_init( &p_adapter->obj, CL_DESTROY_SYNC, - __adapter_destroying, NULL, __adapter_free ); - if( cl_status != CL_SUCCESS ) - { - __adapter_free( &p_adapter->obj ); - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("cl_obj_init returned %#x\n", cl_status) ); - return IB_ERROR; - } - - /* Read configuration parameters. */ - status = ipoib_get_adapter_params( wrapper_config_context, - p_adapter , &mac, &len); - if( status != NDIS_STATUS_SUCCESS ) - { - cl_obj_destroy( &p_adapter->obj ); - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ipoib_get_adapter_params returned 0x%.8x.\n", status) ); - return status; - } - - status = adapter_init( p_adapter ); - if( status != IB_SUCCESS ) - { - cl_obj_destroy( &p_adapter->obj ); - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("adapter_init returned %s.\n", - p_adapter->p_ifc->get_err_str( status )) ); - return status; - } - - ETH_COPY_NETWORK_ADDRESS( p_adapter->params.conf_mac.addr, p_adapter->mac.addr ); - /* If there is a NetworkAddress override in registry, use it */ - if( (status == NDIS_STATUS_SUCCESS) && (len == HW_ADDR_LEN) ) - { - if( ETH_IS_MULTICAST(mac) || ETH_IS_BROADCAST(mac) || - !ETH_IS_LOCALLY_ADMINISTERED(mac) ) - { - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_INIT, - ("Overriding NetworkAddress is invalid - " - "%02x-%02x-%02x-%02x-%02x-%02x\n", - mac[0], mac[1], mac[2], - mac[3], mac[4], mac[5]) ); - } - else - { - ETH_COPY_NETWORK_ADDRESS( p_adapter->params.conf_mac.addr, mac ); - } - } - - *pp_adapter = p_adapter; - - IPOIB_EXIT( IPOIB_DBG_INIT ); - return status; -} - - -ib_api_status_t -ipoib_start_adapter( - IN ipoib_adapter_t* const p_adapter ) -{ - ib_api_status_t status; - - IPOIB_ENTER( IPOIB_DBG_INIT ); - - status = __ipoib_pnp_reg( p_adapter, - IB_PNP_FLAG_REG_SYNC | IB_PNP_FLAG_REG_COMPLETE ); - - IPOIB_EXIT( IPOIB_DBG_INIT ); - return status; -} - - -void -ipoib_destroy_adapter( - IN ipoib_adapter_t* const p_adapter ) -{ - IPOIB_ENTER( IPOIB_DBG_INIT ); - - CL_ASSERT( p_adapter ); - - /* - * Flag the adapter as being removed. We use the IB_PNP_PORT_REMOVE state - * for this purpose. Note that we protect this state change with both the - * mutex and the lock. The mutex provides synchronization as a whole - * between destruction and AL callbacks (PnP, Query, Destruction). - * The lock provides protection - */ - KeWaitForMutexObject( - &p_adapter->mutex, Executive, KernelMode, FALSE, NULL ); - cl_obj_lock( &p_adapter->obj ); - p_adapter->state = IB_PNP_PORT_REMOVE; - - /* - * Clear the pointer to the port object since the object destruction - * will cascade to child objects. This prevents potential duplicate - * destruction (or worse, stale pointer usage). - */ - p_adapter->p_port = NULL; - - cl_obj_unlock( &p_adapter->obj ); - - KeReleaseMutex( &p_adapter->mutex, FALSE ); - - cl_obj_destroy( &p_adapter->obj ); - - IPOIB_EXIT( IPOIB_DBG_INIT ); -} - - -static void -adapter_construct( - IN ipoib_adapter_t* const p_adapter ) -{ - cl_obj_construct( &p_adapter->obj, IPOIB_OBJ_INSTANCE ); - cl_spinlock_construct( &p_adapter->send_stat_lock ); - cl_spinlock_construct( &p_adapter->recv_stat_lock ); - cl_qpool_construct( &p_adapter->item_pool ); - KeInitializeMutex( &p_adapter->mutex, 0 ); - - cl_thread_construct(&p_adapter->destroy_thread); - - cl_vector_construct( &p_adapter->ip_vector ); - - cl_perf_construct( &p_adapter->perf ); - - p_adapter->state = IB_PNP_PORT_ADD; - p_adapter->port_rate = FOUR_X_IN_100BPS; -} - - -static ib_api_status_t -adapter_init( - IN ipoib_adapter_t* const p_adapter ) -{ - cl_status_t cl_status; - ib_api_status_t status; - - IPOIB_ENTER( IPOIB_DBG_INIT ); - - cl_status = cl_perf_init( &p_adapter->perf, MaxPerf ); - if( cl_status != CL_SUCCESS ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("cl_perf_init returned %#x\n", cl_status) ); - return IB_ERROR; - } - - cl_status = cl_spinlock_init( &p_adapter->send_stat_lock ); - if( cl_status != CL_SUCCESS ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("cl_spinlock_init returned %#x\n", cl_status) ); - return IB_ERROR; - } - - cl_status = cl_spinlock_init( &p_adapter->recv_stat_lock ); - if( cl_status != CL_SUCCESS ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("cl_spinlock_init returned %#x\n", cl_status) ); - return IB_ERROR; - } - - cl_status = cl_qpool_init( &p_adapter->item_pool, ITEM_POOL_START, 0, - ITEM_POOL_GROW, sizeof(cl_pool_obj_t), NULL, NULL, NULL ); - if( cl_status != CL_SUCCESS ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("cl_qpool_init returned %#x\n", cl_status) ); - return IB_ERROR; - } - - - /* We manually manage the size and capacity of the vector. */ - cl_status = cl_vector_init( &p_adapter->ip_vector, 0, - 0, sizeof(net_address_item_t), NULL, NULL, p_adapter ); - if( cl_status != CL_SUCCESS ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("cl_vector_init for ip_vector returned %#x\n", - cl_status) ); - return IB_ERROR; - } - - /* Validate the port GUID and generate the MAC address. */ - status = - ipoib_mac_from_guid( p_adapter->guids.port_guid.guid, p_adapter->params.guid_mask, &p_adapter->mac); - if( status != IB_SUCCESS ) - { - if( status == IB_INVALID_GUID_MASK ) - { - IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_ERROR, - ("Invalid GUID mask received, rejecting it") ); - ipoib_create_log(p_adapter->h_adapter, GUID_MASK_LOG_INDEX, EVENT_IPOIB_WRONG_PARAMETER_WRN); - } - - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ipoib_mac_from_guid returned %s\n", - p_adapter->p_ifc->get_err_str( status )) ); - return status; - } - - /* Open AL. */ - status = p_adapter->p_ifc->open_al( &p_adapter->h_al ); - if( status != IB_SUCCESS ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ib_open_al returned %s\n", - p_adapter->p_ifc->get_err_str( status )) ); - return status; - } - - IPOIB_EXIT( IPOIB_DBG_INIT ); - return status; -} - - -static ib_api_status_t -__ipoib_pnp_reg( - IN ipoib_adapter_t* const p_adapter, - IN ib_pnp_class_t flags ) -{ - ib_api_status_t status; - ib_pnp_req_t pnp_req; - - IPOIB_ENTER( IPOIB_DBG_INIT ); - - CL_ASSERT( !p_adapter->h_pnp ); - CL_ASSERT( !p_adapter->registering ); - - p_adapter->registering = TRUE; - - /* Register for PNP events. */ - cl_memclr( &pnp_req, sizeof(pnp_req) ); - pnp_req.pnp_class = IB_PNP_PORT | flags; - /* - * Context is the cl_obj of the adapter to allow passing cl_obj_deref - * to ib_dereg_pnp. - */ - pnp_req.pnp_context = &p_adapter->obj; - pnp_req.pfn_pnp_cb = __ipoib_pnp_cb; - status = p_adapter->p_ifc->reg_pnp( p_adapter->h_al, &pnp_req, &p_adapter->h_pnp ); - if( status != IB_SUCCESS ) - { - ASSERT(FALSE); - p_adapter->registering = FALSE; - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ib_reg_pnp returned %s\n", - p_adapter->p_ifc->get_err_str( status )) ); - return status; - } - /* - * Reference the adapter on behalf of the PNP registration. - * This allows the destruction to block until the PNP deregistration - * completes. - */ - cl_obj_ref( &p_adapter->obj ); - - IPOIB_EXIT( IPOIB_DBG_INIT ); - return status; -} - - -static void -__adapter_destroying( - IN cl_obj_t* const p_obj ) -{ - ipoib_adapter_t *p_adapter; - KLOCK_QUEUE_HANDLE hdl; - - IPOIB_ENTER( IPOIB_DBG_INIT ); - - p_adapter = PARENT_STRUCT( p_obj, ipoib_adapter_t, obj ); - - /* - * The adapter's object will be dereferenced when the deregistration - * completes. No need to lock here since all PnP related API calls - * are driven by NDIS (via the Init/Reset/Destroy paths). - */ - if( p_adapter->h_pnp ) - { - p_adapter->p_ifc->dereg_pnp( p_adapter->h_pnp, cl_obj_deref ); - p_adapter->h_pnp = NULL; - } - - if( p_adapter->packet_filter ) - { - KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl ); - cl_obj_lock( &p_adapter->obj ); - - ASSERT( cl_qlist_count( &g_ipoib.adapter_list ) ); - cl_qlist_remove_item( &g_ipoib.adapter_list, &p_adapter->entry ); - - p_adapter->packet_filter = 0; - - cl_obj_unlock( &p_adapter->obj ); - KeReleaseInStackQueuedSpinLock( &hdl ); - } - - IPOIB_EXIT( IPOIB_DBG_INIT ); -} - - -static void -__adapter_free( - IN cl_obj_t* const p_obj ) -{ - ipoib_adapter_t *p_adapter; - - IPOIB_ENTER( IPOIB_DBG_INIT ); - - p_adapter = PARENT_STRUCT( p_obj, ipoib_adapter_t, obj ); - - if( p_adapter->p_ifc ) - { - if( p_adapter->h_al ) - p_adapter->p_ifc->close_al( p_adapter->h_al ); - - cl_free( p_adapter->p_ifc ); - p_adapter->p_ifc = NULL; - } - - cl_vector_destroy( &p_adapter->ip_vector ); - cl_qpool_destroy( &p_adapter->item_pool ); - cl_spinlock_destroy( &p_adapter->recv_stat_lock ); - cl_spinlock_destroy( &p_adapter->send_stat_lock ); - cl_obj_deinit( p_obj ); - - cl_perf_destroy( &p_adapter->perf, TRUE ); - - cl_free( p_adapter ); - - IPOIB_EXIT( IPOIB_DBG_INIT ); -} - - -static ib_api_status_t -ipoib_query_pkey_index(ipoib_adapter_t *p_adapter) -{ - ib_api_status_t status; - ib_ca_attr_t *ca_attr; - uint32_t ca_size; - uint16_t index = 0; - - /* Query the CA for Pkey table */ - status = p_adapter->p_ifc->query_ca(p_adapter->p_port->ib_mgr.h_ca, NULL, &ca_size); - if(status != IB_INSUFFICIENT_MEMORY) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ib_query_ca failed\n")); - return status; - } - - ca_attr = (ib_ca_attr_t*)cl_zalloc(ca_size); - if (!ca_attr) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("cl_zalloc can't allocate %d\n",ca_size)); - return IB_INSUFFICIENT_MEMORY; - } - - status = p_adapter->p_ifc->query_ca(p_adapter->p_port->ib_mgr.h_ca, ca_attr,&ca_size); - if( status != IB_SUCCESS ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ib_query_ca returned %s\n", - p_adapter->p_ifc->get_err_str( status )) ); - goto pkey_end; - } - CL_ASSERT(ca_attr->p_port_attr[p_adapter->p_port->port_num -1].p_pkey_table[0] == IB_DEFAULT_PKEY); - for(index = 0; index < ca_attr->p_port_attr[p_adapter->p_port->port_num -1].num_pkeys; index++) - { - if(cl_hton16(p_adapter->guids.port_guid.pkey) == ca_attr->p_port_attr[p_adapter->p_port->port_num -1].p_pkey_table[index]) - break; - } - if(index >= ca_attr->p_port_attr[p_adapter->p_port->port_num -1].num_pkeys) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Pkey table is invalid, index not found\n")); - NdisWriteErrorLogEntry( p_adapter->h_adapter, - EVENT_IPOIB_PARTITION_ERR, 1, p_adapter->guids.port_guid.pkey ); - status = IB_NOT_FOUND; - p_adapter->p_port->pkey_index = PKEY_INVALID_INDEX; - goto pkey_end; - } - - p_adapter->p_port->pkey_index = index; - IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_IB, - ("for PKEY = 0x%04X got index = %d\n",p_adapter->guids.port_guid.pkey,index)); - -pkey_end: - if(ca_attr) - cl_free(ca_attr); - return status; -} - -static ib_api_status_t -__ipoib_pnp_cb( - IN ib_pnp_rec_t *p_pnp_rec ) -{ - ipoib_adapter_t *p_adapter; - ipoib_port_t *p_port; - ib_pnp_event_t old_state; - ib_pnp_port_rec_t *p_port_rec; - ib_api_status_t status = IB_SUCCESS; - NDIS_LINK_STATE link_state; - NDIS_STATUS_INDICATION status_indication; - - IPOIB_ENTER( IPOIB_DBG_PNP ); - - CL_ASSERT( p_pnp_rec ); - NdisZeroMemory(&link_state, sizeof(NDIS_LINK_STATE)); - p_adapter = - PARENT_STRUCT( p_pnp_rec->pnp_context, ipoib_adapter_t, obj ); - - CL_ASSERT( p_adapter ); - - /* Synchronize with destruction */ - KeWaitForMutexObject( - &p_adapter->mutex, Executive, KernelMode, FALSE, NULL ); - cl_obj_lock( &p_adapter->obj ); - old_state = p_adapter->state; - cl_obj_unlock( &p_adapter->obj ); - if( old_state == IB_PNP_PORT_REMOVE ) - { - KeReleaseMutex( &p_adapter->mutex, FALSE ); - IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_PNP, - ("Aborting - Adapter destroying.\n") ); - return IB_NOT_DONE; - } - - IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_PNP, - ("p_pnp_rec->pnp_event = 0x%x (%s)\n", - p_pnp_rec->pnp_event, ib_get_pnp_event_str( p_pnp_rec->pnp_event )) ); - - p_port_rec = (ib_pnp_port_rec_t*)p_pnp_rec; - - switch( p_pnp_rec->pnp_event ) - { - case IB_PNP_PORT_ADD: - CL_ASSERT( !p_pnp_rec->context ); - /* Only process our port GUID. */ - if( p_pnp_rec->guid != p_adapter->guids.port_guid.guid ) - { - status = IB_NOT_DONE; - break; - } - - /* Don't process if we're destroying. */ - if( p_adapter->obj.state == CL_DESTROYING ) - { - status = IB_NOT_DONE; - break; - } - - CL_ASSERT( !p_adapter->p_port ); - /* Allocate all IB resources. */ - cl_obj_lock( &p_adapter->obj ); - p_adapter->state = IB_PNP_PORT_ADD; - cl_obj_unlock( &p_adapter->obj ); - status = ipoib_create_port( p_adapter, p_port_rec, &p_port ); - cl_obj_lock( &p_adapter->obj ); - if( status != IB_SUCCESS ) - { - p_adapter->state = old_state; - cl_obj_unlock( &p_adapter->obj ); - p_adapter->hung = TRUE; - break; - } - - p_pnp_rec->context = p_port; - - p_adapter->p_port = p_port; - cl_obj_unlock( &p_adapter->obj ); - break; - - case IB_PNP_PORT_REMOVE: - /* Release all IB resources. */ - CL_ASSERT( p_pnp_rec->context ); - - cl_obj_lock( &p_adapter->obj ); - p_adapter->state = IB_PNP_PORT_REMOVE; - p_port = p_adapter->p_port; - p_adapter->p_port = NULL; - cl_obj_unlock( &p_adapter->obj ); - ipoib_port_destroy( p_port ); - p_pnp_rec->context = NULL; - status = IB_SUCCESS; - break; - - case IB_PNP_PORT_ACTIVE: - /* Join multicast groups and put QP in RTS. */ - CL_ASSERT( p_pnp_rec->context ); - - cl_obj_lock( &p_adapter->obj ); - p_adapter->state = IB_PNP_PORT_INIT; - cl_obj_unlock( &p_adapter->obj ); - ipoib_port_up( p_adapter->p_port, p_port_rec ); - - status = IB_SUCCESS; - break; - - case IB_PNP_PORT_ARMED: - status = IB_SUCCESS; - break; - - case IB_PNP_PORT_INIT: - /* - * Init could happen if the SM brings the port down - * without changing the physical link. - */ - case IB_PNP_PORT_DOWN: - CL_ASSERT( p_pnp_rec->context ); - - cl_obj_lock( &p_adapter->obj ); - old_state = p_adapter->state; - p_adapter->state = IB_PNP_PORT_DOWN; - cl_obj_unlock( &p_adapter->obj ); - status = IB_SUCCESS; - - if( !p_adapter->registering && old_state != IB_PNP_PORT_DOWN ) - { - link_state.Header.Revision = NDIS_LINK_STATE_REVISION_1; - link_state.Header.Type = NDIS_OBJECT_TYPE_DEFAULT; - link_state.Header.Size = sizeof(NDIS_LINK_STATE); - link_state.MediaConnectState = MediaConnectStateDisconnected; - //link_state.MediaConnectState = MediaConnectStateConnected; - link_state.MediaDuplexState = MediaDuplexStateFull; - link_state.XmitLinkSpeed = link_state.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED; - - IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication, - p_adapter->h_adapter, - NDIS_STATUS_LINK_STATE, - (PVOID)&link_state, - sizeof(link_state)); - - NdisMIndicateStatusEx(p_adapter->h_adapter,&status_indication); - IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, - ("Link DOWN!\n") ); - - ipoib_port_down( p_adapter->p_port ); - } - break; - - case IB_PNP_REG_COMPLETE: - if( p_adapter->registering ) - { - p_adapter->registering = FALSE; - cl_obj_lock( &p_adapter->obj ); - old_state = p_adapter->state; - cl_obj_unlock( &p_adapter->obj ); - - if( old_state == IB_PNP_PORT_DOWN ) - { - /* If we were initializing, we might have pended some OIDs. */ - ipoib_resume_oids( p_adapter ); - - link_state.Header.Revision = NDIS_LINK_STATE_REVISION_1; - link_state.Header.Type = NDIS_OBJECT_TYPE_DEFAULT; - link_state.Header.Size = sizeof(NDIS_LINK_STATE); - link_state.MediaConnectState = MediaConnectStateDisconnected; - //link_state.MediaConnectState = MediaConnectStateConnected; - link_state.MediaDuplexState = MediaDuplexStateFull; - link_state.XmitLinkSpeed = link_state.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED; - - IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication, - p_adapter->h_adapter, - NDIS_STATUS_LINK_STATE, - (PVOID)&link_state, - sizeof(link_state)); - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_INIT, - ("Indicate DISCONNECT\n") ); - NdisMIndicateStatusEx(p_adapter->h_adapter,&status_indication); - } - } - - if( p_adapter->reset && p_adapter->state != IB_PNP_PORT_INIT ) - { - p_adapter->reset = FALSE; - NdisMResetComplete( - p_adapter->h_adapter, NDIS_STATUS_SUCCESS, TRUE ); - } - status = IB_SUCCESS; - break; - - default: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, - ("IPOIB: Received unhandled PnP event 0x%x (%s)\n", - p_pnp_rec->pnp_event, ib_get_pnp_event_str( p_pnp_rec->pnp_event )) ); - /* Fall through. */ - - status = IB_SUCCESS; - - /* We ignore events below if the link is not active. */ - if( p_port_rec->p_port_attr->link_state != IB_LINK_ACTIVE ) - break; - - case IB_PNP_PKEY_CHANGE: - if(p_pnp_rec->pnp_event == IB_PNP_PKEY_CHANGE && - p_adapter->guids.port_guid.pkey != IB_DEFAULT_PKEY) - { - status = ipoib_query_pkey_index(p_adapter); - if(status != IB_SUCCESS) - { - cl_obj_lock( &p_adapter->obj ); - p_adapter->state = IB_PNP_PORT_INIT; - cl_obj_unlock( &p_adapter->obj ); - } - } - - case IB_PNP_SM_CHANGE: - case IB_PNP_GID_CHANGE: - case IB_PNP_LID_CHANGE: - - cl_obj_lock( &p_adapter->obj ); - old_state = p_adapter->state; - switch( old_state ) - { - case IB_PNP_PORT_DOWN: - p_adapter->state = IB_PNP_PORT_INIT; - break; - - default: - p_adapter->state = IB_PNP_PORT_DOWN; - } - cl_obj_unlock( &p_adapter->obj ); - - if( p_adapter->registering ) - break; - - switch( old_state ) - { - case IB_PNP_PORT_ACTIVE: - case IB_PNP_PORT_INIT: - link_state.Header.Revision = NDIS_LINK_STATE_REVISION_1; - link_state.Header.Type = NDIS_OBJECT_TYPE_DEFAULT; - link_state.Header.Size = sizeof(NDIS_LINK_STATE); - link_state.MediaConnectState = MediaConnectStateDisconnected; - //link_state.MediaConnectState = MediaConnectStateConnected; - link_state.MediaDuplexState = MediaDuplexStateFull; - link_state.XmitLinkSpeed = link_state.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED; - - IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication, - p_adapter->h_adapter, - NDIS_STATUS_LINK_STATE, - (PVOID)&link_state, - sizeof(link_state)); - - NdisMIndicateStatusEx(p_adapter->h_adapter,&status_indication); - - IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, - ("Link DOWN!\n") ); - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_INIT, - ("Indicate DISCONNECT\n") ); - - ipoib_port_down( p_adapter->p_port ); - /* Fall through. */ - - case IB_PNP_PORT_DOWN: - cl_obj_lock( &p_adapter->obj ); - p_adapter->state = IB_PNP_PORT_INIT; - cl_obj_unlock( &p_adapter->obj ); - ipoib_port_up( p_adapter->p_port, (ib_pnp_port_rec_t*)p_pnp_rec ); - } - break; - } - - KeReleaseMutex( &p_adapter->mutex, FALSE ); - - IPOIB_EXIT( IPOIB_DBG_PNP ); - return status; -} - - -/* Joins/leaves mcast groups based on currently programmed mcast MACs. */ -void -ipoib_refresh_mcast( - IN ipoib_adapter_t* const p_adapter, - IN mac_addr_t* const p_mac_array, - IN const uint8_t num_macs ) -{ - uint8_t i, j; - ipoib_port_t *p_port = NULL; - - IPOIB_ENTER( IPOIB_DBG_MCAST ); - cl_obj_lock( &p_adapter->obj ); - if( p_adapter->state == IB_PNP_PORT_ACTIVE ) - { - p_port = p_adapter->p_port; - ipoib_port_ref( p_port, ref_refresh_mcast ); - } - cl_obj_unlock( &p_adapter->obj ); - - if( p_port ) - { - /* Purge old entries. */ - for( i = 0; i < p_adapter->mcast_array_size; i++ ) - { - for( j = 0; j < num_macs; j++ ) - { - if( !cl_memcmp( &p_adapter->mcast_array[i], &p_mac_array[j], - sizeof(mac_addr_t) ) ) - { - break; - } - } - if( j != num_macs ) - continue; - - ipoib_port_remove_endpt( p_port, p_adapter->mcast_array[i] ); - } - - /* Add new entries */ - for( i = 0; i < num_macs; i++ ) - { - for( j = 0; j < p_adapter->mcast_array_size; j++ ) - { - if( !cl_memcmp( &p_adapter->mcast_array[j], &p_mac_array[i], - sizeof(mac_addr_t) ) ) - { - break; - } - } - - if( j != p_adapter->mcast_array_size ) - continue; - if ( ( p_mac_array[i].addr[0] == 1 && p_mac_array[i].addr[1] == 0 && p_mac_array[i].addr[2] == 0x5e && - p_mac_array[i].addr[3] == 0 && p_mac_array[i].addr[4] == 0 && p_mac_array[i].addr[5] == 1 ) || - !( p_mac_array[i].addr[0] == 1 && p_mac_array[i].addr[1] == 0 && p_mac_array[i].addr[2] == 0x5e ) - ) - { - ipoib_port_join_mcast( p_port, p_mac_array[i], IB_MC_REC_STATE_FULL_MEMBER ); - } - } - } - - /* Copy the MAC array. */ - NdisMoveMemory( p_adapter->mcast_array, p_mac_array, - num_macs * sizeof(mac_addr_t) ); - p_adapter->mcast_array_size = num_macs; - - if( p_port ) - ipoib_port_deref( p_port, ref_refresh_mcast ); - - IPOIB_EXIT( IPOIB_DBG_MCAST ); -} - - -ib_api_status_t -ipoib_reset_adapter( - IN ipoib_adapter_t* const p_adapter ) -{ - ib_api_status_t status; - ib_pnp_handle_t h_pnp; - - IPOIB_ENTER( IPOIB_DBG_INIT ); - - if( p_adapter->reset ) - return IB_INVALID_STATE; - - p_adapter->hung = FALSE; - p_adapter->reset = TRUE; - - if( p_adapter->h_pnp ) - { - h_pnp = p_adapter->h_pnp; - p_adapter->h_pnp = NULL; - status = p_adapter->p_ifc->dereg_pnp( h_pnp, __ipoib_pnp_dereg ); - if( status == IB_SUCCESS ) - status = IB_NOT_DONE; - } - else - { - status = __ipoib_pnp_reg( p_adapter, IB_PNP_FLAG_REG_COMPLETE ); - if( status == IB_SUCCESS ) - p_adapter->hung = FALSE; - } - if (status == IB_NOT_DONE) { - p_adapter->reset = TRUE; - } - else { - p_adapter->reset = FALSE; - } - IPOIB_EXIT( IPOIB_DBG_INIT ); - return status; -} - - -static void -__ipoib_pnp_dereg( - IN void* context ) -{ - ipoib_adapter_t* p_adapter; - - IPOIB_ENTER( IPOIB_DBG_INIT ); - - p_adapter = PARENT_STRUCT( context, ipoib_adapter_t, obj ); - - cl_thread_init(&p_adapter->destroy_thread, __ipoib_adapter_reset, (void*)p_adapter, "destroy_thread"); - - IPOIB_ENTER( IPOIB_DBG_INIT ); - -} - -static void -__ipoib_adapter_reset( - IN void* context) -{ - - ipoib_adapter_t *p_adapter; - ipoib_port_t *p_port; - ib_api_status_t status; - ib_pnp_event_t state; - - IPOIB_ENTER( IPOIB_DBG_INIT ); - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Got RESET\n") ); -// return; - p_adapter = (ipoib_adapter_t*)context; - - /* Synchronize with destruction */ - KeWaitForMutexObject( - &p_adapter->mutex, Executive, KernelMode, FALSE, NULL ); - - cl_obj_lock( &p_adapter->obj ); - - CL_ASSERT( !p_adapter->h_pnp ); - - if( p_adapter->state != IB_PNP_PORT_REMOVE ) - p_adapter->state = IB_PNP_PORT_ADD; - - state = p_adapter->state; - - /* Destroy the current port instance if it still exists. */ - p_port = p_adapter->p_port; - p_adapter->p_port = NULL; - cl_obj_unlock( &p_adapter->obj ); - - if( p_port ) - ipoib_port_destroy( p_port ); - ASSERT(p_adapter->reset == TRUE); - if( state != IB_PNP_PORT_REMOVE ) - { - status = __ipoib_pnp_reg( p_adapter, IB_PNP_FLAG_REG_COMPLETE ); - if( status != IB_SUCCESS ) - { - p_adapter->reset = FALSE; - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("__ipoib_pnp_reg returned %s\n", - p_adapter->p_ifc->get_err_str( status )) ); - NdisMResetComplete( - p_adapter->h_adapter, NDIS_STATUS_HARD_ERRORS, TRUE ); - } - } - else - { - p_adapter->reset = FALSE; - NdisMResetComplete( - p_adapter->h_adapter, NDIS_STATUS_SUCCESS, TRUE ); - status = IB_SUCCESS; - } - - /* Dereference the adapter since the previous registration is now gone. */ - cl_obj_deref( &p_adapter->obj ); - - KeReleaseMutex( &p_adapter->mutex, FALSE ); - - IPOIB_EXIT( IPOIB_DBG_INIT ); -} - - -void -ipoib_set_rate( - IN ipoib_adapter_t* const p_adapter, - IN const uint8_t link_width, - IN const uint8_t link_speed ) -{ - uint32_t rate; - - IPOIB_ENTER( IPOIB_DBG_INIT ); - - /* Set the link speed based on the IB link speed (1x vs 4x, etc). */ - switch( link_speed ) - { - case IB_LINK_SPEED_ACTIVE_2_5: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, - ("Link speed is 2.5Gs\n") ); - rate = IB_LINK_SPEED_ACTIVE_2_5; - break; - - case IB_LINK_SPEED_ACTIVE_5: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, - ("Link speed is 5G\n") ); - rate = IB_LINK_SPEED_ACTIVE_5; - break; - - case IB_LINK_SPEED_ACTIVE_10: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, - ("Link speed is 10G\n") ); - rate = IB_LINK_SPEED_ACTIVE_10; - break; - - default: - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Invalid link speed %d.\n", link_speed) ); - rate = 0; - } - - switch( link_width ) - { - case IB_LINK_WIDTH_ACTIVE_1X: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, - ("Link width is 1X\n") ); - rate *= ONE_X_IN_100BPS; - break; - - case IB_LINK_WIDTH_ACTIVE_4X: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, - ("Link width is 4X\n") ); - rate *= FOUR_X_IN_100BPS; - break; - - case IB_LINK_WIDTH_ACTIVE_12X: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, - ("Link width is 12X\n") ); - rate *= TWELVE_X_IN_100BPS; - break; - - default: - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Invalid link rate (%d).\n", link_width) ); - rate = 0; - } - - p_adapter->port_rate = rate; - IPOIB_EXIT( IPOIB_DBG_INIT ); -} - - -ib_api_status_t -ipoib_set_active( - IN ipoib_adapter_t* const p_adapter ) -{ - ib_pnp_event_t old_state; - uint8_t i; - ib_api_status_t status = IB_SUCCESS; - NDIS_LINK_STATE link_state; - NDIS_STATUS_INDICATION status_indication; - IPOIB_ENTER( IPOIB_DBG_INIT ); - - NdisZeroMemory(&link_state, sizeof(NDIS_LINK_STATE)); - cl_obj_lock( &p_adapter->obj ); - old_state = p_adapter->state; - - /* Change the state to indicate that we are now connected and live. */ - if( old_state == IB_PNP_PORT_INIT ) - p_adapter->state = IB_PNP_PORT_ACTIVE; - - cl_obj_unlock( &p_adapter->obj ); - - /* - * If we had a pending OID request for OID_GEN_LINK_SPEED, - * complete it now. - */ - switch( old_state ) - { - case IB_PNP_PORT_ADD: - ipoib_reg_addrs( p_adapter ); - /* Fall through. */ - - case IB_PNP_PORT_REMOVE: - ipoib_resume_oids( p_adapter ); - break; - - default: - if (p_adapter->guids.port_guid.pkey != IB_DEFAULT_PKEY) - { - status = ipoib_query_pkey_index(p_adapter); - if( IB_SUCCESS != status) - { - break; - } - } - /* Join all programmed multicast groups. */ - for( i = 0; i < p_adapter->mcast_array_size; i++ ) - { - ipoib_port_join_mcast( - p_adapter->p_port, p_adapter->mcast_array[i] ,IB_MC_REC_STATE_FULL_MEMBER); - } - - /* Register all existing addresses. */ - ipoib_reg_addrs( p_adapter ); - - ipoib_resume_oids( p_adapter ); - - /* - * Now that we're in the broadcast group, notify that - * we have a link. - */ - IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, ("Link UP!\n") ); - NdisWriteErrorLogEntry( p_adapter->h_adapter, - EVENT_IPOIB_PORT_UP + (p_adapter->port_rate/ONE_X_IN_100BPS), - 1, p_adapter->port_rate ); - - if( !p_adapter->reset ) - { - link_state.Header.Revision = NDIS_LINK_STATE_REVISION_1; - link_state.Header.Type = NDIS_OBJECT_TYPE_DEFAULT; - link_state.Header.Size = sizeof(NDIS_LINK_STATE); - link_state.MediaConnectState = MediaConnectStateConnected; - link_state.MediaDuplexState = MediaDuplexStateFull; - link_state.XmitLinkSpeed = - link_state.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED; - link_state.PauseFunctions = NdisPauseFunctionsSendAndReceive; - IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication, - p_adapter->h_adapter, - NDIS_STATUS_LINK_STATE, - (PVOID)&link_state, - sizeof(link_state)); - IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, ("***************Indicate connect!\n") ); - NdisMIndicateStatusEx(p_adapter->h_adapter,&status_indication); - } - } - - if( p_adapter->reset ) - { - ASSERT(FALSE); - p_adapter->reset = FALSE; - NdisMResetComplete( - p_adapter->h_adapter, NDIS_STATUS_SUCCESS, TRUE ); - } - - IPOIB_EXIT( IPOIB_DBG_INIT ); - return status; -} - -/* - * If something goes wrong after the port goes active, e.g. - * - PortInfo query failure - * - MC Join timeout - * - etc - * Mark the port state as down, resume any pended OIDS, etc. - */ -void -ipoib_set_inactive( - IN ipoib_adapter_t* const p_adapter ) -{ - ib_pnp_event_t old_state; - NDIS_LINK_STATE link_state; - NDIS_STATUS_INDICATION status_indication; - - IPOIB_ENTER( IPOIB_DBG_INIT ); - - NdisZeroMemory(&link_state, sizeof(NDIS_LINK_STATE)); - cl_obj_lock( &p_adapter->obj ); - old_state = p_adapter->state; - if( old_state != IB_PNP_PORT_REMOVE ) - p_adapter->state = IB_PNP_PORT_DOWN; - cl_obj_unlock( &p_adapter->obj ); - - /* - * If we had a pending OID request for OID_GEN_LINK_SPEED, - * complete it now. - */ - if( old_state == IB_PNP_PORT_INIT ) - { - link_state.Header.Revision = NDIS_LINK_STATE_REVISION_1; - link_state.Header.Type = NDIS_OBJECT_TYPE_DEFAULT; - link_state.Header.Size = sizeof(NDIS_LINK_STATE); - link_state.MediaConnectState = MediaConnectStateDisconnected; - //link_state.MediaConnectState = MediaConnectStateConnected; - - link_state.MediaDuplexState = MediaDuplexStateFull; - link_state.XmitLinkSpeed = link_state.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED; - - IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication, - p_adapter->h_adapter, - NDIS_STATUS_LINK_STATE, - (PVOID)&link_state, - sizeof(link_state)); - IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, ("Indicate Disconnect!\n") ); - NdisMIndicateStatusEx(p_adapter->h_adapter,&status_indication); - - ipoib_resume_oids( p_adapter ); - } - - if( p_adapter->reset ) - { - p_adapter->reset = FALSE; - NdisMResetComplete( - p_adapter->h_adapter, NDIS_STATUS_SUCCESS, TRUE ); - } - - IPOIB_EXIT( IPOIB_DBG_INIT ); -} - -NDIS_STATUS -ipoib_get_gen_stat( - IN ipoib_adapter_t* const p_adapter, - OUT pending_oid_t* const p_oid_info) -{ - PNDIS_STATISTICS_INFO StatisticsInfo; - IPOIB_ENTER( IPOIB_DBG_STAT ); - - if (p_oid_info->buf_len < sizeof(StatisticsInfo)) - { - *p_oid_info->p_bytes_needed = sizeof(NDIS_STATISTICS_INFO); - return NDIS_STATUS_INVALID_LENGTH; - } - - StatisticsInfo = (PNDIS_STATISTICS_INFO)p_oid_info->p_buf; - StatisticsInfo->Header.Revision = NDIS_OBJECT_REVISION_1; - StatisticsInfo->Header.Type = NDIS_OBJECT_TYPE_DEFAULT; - StatisticsInfo->Header.Size = sizeof(NDIS_STATISTICS_INFO); - /*StatisticsInfo->SupportedStatistics = NDIS_STATISTICS_FLAGS_VALID_RCV_DISCARDS | - NDIS_STATISTICS_FLAGS_VALID_RCV_ERROR | - NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_RCV | - NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_RCV | - NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_RCV | - NDIS_STATISTICS_FLAGS_VALID_BYTES_RCV | - NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_RCV | - NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_RCV | - NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_RCV | - - NDIS_STATISTICS_FLAGS_VALID_XMIT_DISCARDS | - NDIS_STATISTICS_FLAGS_VALID_XMIT_ERROR | - NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_XMIT | - NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_XMIT | - NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_XMIT | - NDIS_STATISTICS_FLAGS_VALID_BYTES_XMIT | - NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_XMIT | - NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_XMIT | - NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_XMIT; */ - - - StatisticsInfo->SupportedStatistics = NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_RCV | - //The data in the ifHCInUcastPkts member is valid. - NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_RCV | - //The data in the ifHCInMulticastPkts member is valid. - NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_RCV | - //The data in the ifHCInBroadcastPkts member is valid. - NDIS_STATISTICS_FLAGS_VALID_BYTES_RCV | - //The data in the ifHCInOctets member is valid. - NDIS_STATISTICS_FLAGS_VALID_RCV_DISCARDS | - //The data in the ifInDiscards member is valid. - NDIS_STATISTICS_FLAGS_VALID_RCV_ERROR | - //The data in the ifInErrors member is valid. - NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_XMIT | - //The data in the ifHCOutUcastPkts member is valid. - NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_XMIT | - //The data in the ifHCOutMulticastPkts member is valid. - NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_XMIT | - //The data in the ifHCOutBroadcastPkts member is valid. - NDIS_STATISTICS_FLAGS_VALID_BYTES_XMIT | - //The data in the ifHCOutOctets member is valid. - NDIS_STATISTICS_FLAGS_VALID_XMIT_ERROR | - //The data in the ifOutErrors member is valid. - NDIS_STATISTICS_FLAGS_VALID_XMIT_DISCARDS | - //The data in the ifOutDiscards member is valid. - NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_RCV | - //The data in the ifHCInUcastOctets member is valid. - NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_RCV | - //The data in the ifHCInMulticastOctets member is valid. - NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_RCV | - //The data in the ifHCInBroadcastOctets member is valid. - NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_XMIT | - //The data in the ifHCOutUcastOctets member is valid. - NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_XMIT | - //The data in the ifHCOutMulticastOctets member is valid. - NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_XMIT ; - //The data in the ifHCOutBroadcastOctets member is valid - - cl_spinlock_acquire( &p_adapter->recv_stat_lock ); - StatisticsInfo->ifInDiscards = p_adapter->recv_stats.comp.dropped + - p_adapter->recv_stats.comp.error; - StatisticsInfo->ifInErrors = p_adapter->recv_stats.comp.error; - StatisticsInfo->ifHCInOctets = p_adapter->recv_stats.ucast.bytes + - p_adapter->recv_stats.bcast.bytes + - p_adapter->recv_stats.mcast.bytes; - StatisticsInfo->ifHCInUcastPkts = p_adapter->recv_stats.ucast.frames; - StatisticsInfo->ifHCInMulticastPkts = p_adapter->recv_stats.mcast.frames; - StatisticsInfo->ifHCInBroadcastPkts = p_adapter->recv_stats.bcast.frames; - StatisticsInfo->ifHCInMulticastOctets = p_adapter->recv_stats.mcast.bytes; - StatisticsInfo->ifHCInBroadcastOctets = p_adapter->recv_stats.bcast.bytes; - StatisticsInfo->ifHCInUcastOctets = p_adapter->recv_stats.ucast.bytes; - cl_spinlock_release( &p_adapter->recv_stat_lock ); - - cl_spinlock_acquire( &p_adapter->send_stat_lock ); - StatisticsInfo->ifHCOutOctets = p_adapter->send_stats.ucast.bytes + - p_adapter->send_stats.mcast.bytes + - p_adapter->send_stats.bcast.bytes; - StatisticsInfo->ifHCOutUcastPkts = p_adapter->send_stats.ucast.frames; - StatisticsInfo->ifHCOutMulticastPkts = p_adapter->send_stats.mcast.frames; - StatisticsInfo->ifHCOutBroadcastPkts = p_adapter->send_stats.bcast.frames; - StatisticsInfo->ifOutErrors = p_adapter->send_stats.comp.error; - StatisticsInfo->ifOutDiscards = p_adapter->send_stats.comp.dropped; - StatisticsInfo->ifHCOutUcastOctets = p_adapter->send_stats.ucast.bytes; - StatisticsInfo->ifHCOutMulticastOctets = p_adapter->send_stats.mcast.bytes; - StatisticsInfo->ifHCOutBroadcastOctets = p_adapter->send_stats.bcast.bytes; - cl_spinlock_release( &p_adapter->send_stat_lock ); - - *p_oid_info->p_bytes_used = sizeof(NDIS_STATISTICS_INFO); - - IPOIB_EXIT( IPOIB_DBG_INIT ); - return NDIS_STATUS_SUCCESS; -} - -NDIS_STATUS -ipoib_get_recv_stat( - IN ipoib_adapter_t* const p_adapter, - IN const ip_stat_sel_t stat_sel, - IN pending_oid_t* const p_oid_info ) -{ - uint64_t stat; - - IPOIB_ENTER( IPOIB_DBG_STAT ); - - CL_ASSERT( p_adapter ); - - cl_spinlock_acquire( &p_adapter->recv_stat_lock ); - switch( stat_sel ) - { - case IP_STAT_SUCCESS: - stat = p_adapter->recv_stats.comp.success; - break; - - case IP_STAT_ERROR: - stat = p_adapter->recv_stats.comp.error; - break; - - case IP_STAT_DROPPED: - stat = p_adapter->recv_stats.comp.dropped; - break; - - case IP_STAT_UCAST_BYTES: - stat = p_adapter->recv_stats.ucast.bytes; - break; - - case IP_STAT_UCAST_FRAMES: - stat = p_adapter->recv_stats.ucast.frames; - break; - - case IP_STAT_BCAST_BYTES: - stat = p_adapter->recv_stats.bcast.bytes; - break; - - case IP_STAT_BCAST_FRAMES: - stat = p_adapter->recv_stats.bcast.frames; - break; - - case IP_STAT_MCAST_BYTES: - stat = p_adapter->recv_stats.mcast.bytes; - break; - - case IP_STAT_MCAST_FRAMES: - stat = p_adapter->recv_stats.mcast.frames; - break; - - default: - stat = 0; - } - cl_spinlock_release( &p_adapter->recv_stat_lock ); - - *p_oid_info->p_bytes_needed = sizeof(uint64_t); - - if( p_oid_info->buf_len >= sizeof(uint64_t) ) - { - *((uint64_t*)p_oid_info->p_buf) = stat; - *p_oid_info->p_bytes_used = sizeof(uint64_t); - } - else if( p_oid_info->buf_len >= sizeof(uint32_t) ) - { - *((uint32_t*)p_oid_info->p_buf) = (uint32_t)stat; - *p_oid_info->p_bytes_used = sizeof(uint32_t); - } - else - { - *p_oid_info->p_bytes_used = 0; - IPOIB_EXIT( IPOIB_DBG_STAT ); - return NDIS_STATUS_INVALID_LENGTH; - } - - IPOIB_EXIT( IPOIB_DBG_STAT ); - return NDIS_STATUS_SUCCESS; -} - - -void -ipoib_inc_recv_stat( - IN ipoib_adapter_t* const p_adapter, - IN const ip_stat_sel_t stat_sel, - IN const size_t bytes OPTIONAL, - IN const size_t packets OPTIONAL ) -{ - IPOIB_ENTER( IPOIB_DBG_STAT ); - - cl_spinlock_acquire( &p_adapter->recv_stat_lock ); - switch( stat_sel ) - { - case IP_STAT_ERROR: - p_adapter->recv_stats.comp.error++; - break; - - case IP_STAT_DROPPED: - p_adapter->recv_stats.comp.dropped++; - break; - - case IP_STAT_UCAST_BYTES: - case IP_STAT_UCAST_FRAMES: - p_adapter->recv_stats.comp.success++; - p_adapter->recv_stats.ucast.frames += packets; - p_adapter->recv_stats.ucast.bytes += bytes; - break; - - case IP_STAT_BCAST_BYTES: - case IP_STAT_BCAST_FRAMES: - p_adapter->recv_stats.comp.success++; - p_adapter->recv_stats.bcast.frames += packets; - p_adapter->recv_stats.bcast.bytes += bytes; - break; - - case IP_STAT_MCAST_BYTES: - case IP_STAT_MCAST_FRAMES: - p_adapter->recv_stats.comp.success++; - p_adapter->recv_stats.mcast.frames += packets; - p_adapter->recv_stats.mcast.bytes += bytes; - break; - - default: - break; - } - cl_spinlock_release( &p_adapter->recv_stat_lock ); - - IPOIB_EXIT( IPOIB_DBG_STAT ); -} - -NDIS_STATUS -ipoib_get_send_stat( - IN ipoib_adapter_t* const p_adapter, - IN const ip_stat_sel_t stat_sel, - IN pending_oid_t* const p_oid_info ) -{ - uint64_t stat; - - IPOIB_ENTER( IPOIB_DBG_STAT ); - - CL_ASSERT( p_adapter ); - - cl_spinlock_acquire( &p_adapter->send_stat_lock ); - switch( stat_sel ) - { - case IP_STAT_SUCCESS: - stat = p_adapter->send_stats.comp.success; - break; - - case IP_STAT_ERROR: - stat = p_adapter->send_stats.comp.error; - break; - - case IP_STAT_DROPPED: - stat = p_adapter->send_stats.comp.dropped; - break; - - case IP_STAT_UCAST_BYTES: - stat = p_adapter->send_stats.ucast.bytes; - break; - - case IP_STAT_UCAST_FRAMES: - stat = p_adapter->send_stats.ucast.frames; - break; - - case IP_STAT_BCAST_BYTES: - stat = p_adapter->send_stats.bcast.bytes; - break; - - case IP_STAT_BCAST_FRAMES: - stat = p_adapter->send_stats.bcast.frames; - break; - - case IP_STAT_MCAST_BYTES: - stat = p_adapter->send_stats.mcast.bytes; - break; - - case IP_STAT_MCAST_FRAMES: - stat = p_adapter->send_stats.mcast.frames; - break; - - default: - stat = 0; - } - cl_spinlock_release( &p_adapter->send_stat_lock ); - - *p_oid_info->p_bytes_needed = sizeof(uint64_t); - - if( p_oid_info->buf_len >= sizeof(uint64_t) ) - { - *((uint64_t*)p_oid_info->p_buf) = stat; - *p_oid_info->p_bytes_used = sizeof(uint64_t); - } - else if( p_oid_info->buf_len >= sizeof(uint32_t) ) - { - *((uint32_t*)p_oid_info->p_buf) = (uint32_t)stat; - *p_oid_info->p_bytes_used = sizeof(uint32_t); - } - else - { - *p_oid_info->p_bytes_used = 0; - IPOIB_EXIT( IPOIB_DBG_STAT ); - return NDIS_STATUS_INVALID_LENGTH; - } - - IPOIB_EXIT( IPOIB_DBG_STAT ); - return NDIS_STATUS_SUCCESS; -} - - -void -ipoib_inc_send_stat( - IN ipoib_adapter_t* const p_adapter, - IN const ip_stat_sel_t stat_sel, - IN const size_t bytes OPTIONAL ) -{ - IPOIB_ENTER( IPOIB_DBG_STAT ); - - cl_spinlock_acquire( &p_adapter->send_stat_lock ); - switch( stat_sel ) - { - case IP_STAT_ERROR: - p_adapter->send_stats.comp.error++; - break; - - case IP_STAT_DROPPED: - p_adapter->send_stats.comp.dropped++; - break; - - case IP_STAT_UCAST_BYTES: - case IP_STAT_UCAST_FRAMES: - p_adapter->send_stats.comp.success++; - p_adapter->send_stats.ucast.frames++; - p_adapter->send_stats.ucast.bytes += bytes; - break; - - case IP_STAT_BCAST_BYTES: - case IP_STAT_BCAST_FRAMES: - p_adapter->send_stats.comp.success++; - p_adapter->send_stats.bcast.frames++; - p_adapter->send_stats.bcast.bytes += bytes; - break; - - case IP_STAT_MCAST_BYTES: - case IP_STAT_MCAST_FRAMES: - p_adapter->send_stats.comp.success++; - p_adapter->send_stats.mcast.frames++; - p_adapter->send_stats.mcast.bytes += bytes; - break; - - default: - break; - } - cl_spinlock_release( &p_adapter->send_stat_lock ); - - IPOIB_EXIT( IPOIB_DBG_STAT ); -} diff --git a/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_adapter.cpp b/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_adapter.cpp new file mode 100644 index 00000000..6733a38d --- /dev/null +++ b/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_adapter.cpp @@ -0,0 +1,1639 @@ +/* + * Copyright (c) 2005 SilverStorm Technologies. All rights reserved. + * Copyright (c) 2006 Mellanox Technologies. All rights reserved. + * Portions Copyright (c) 2008 Microsoft 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: ipoib_adapter.c 4506 2009-06-23 14:40:54Z xalex $ + */ + + + +#include "ipoib_adapter.h" +#include "ipoib_port.h" +#include "ipoib_driver.h" +#include "ipoib_debug.h" + +#if defined(EVENT_TRACING) +#ifdef offsetof +#undef offsetof +#endif +#include "ipoib_adapter.tmh" +#endif + + +#define ITEM_POOL_START 16 +#define ITEM_POOL_GROW 16 + + +/* IB Link speeds in 100bps */ +#define ONE_X_IN_100BPS 25000000 +#define FOUR_X_IN_100BPS 100000000 +#define TWELVE_X_IN_100BPS 300000000 + + +/* Declarations */ +static void +adapter_construct( + IN ipoib_adapter_t* const p_adapter ); + + +static ib_api_status_t +adapter_init( + IN ipoib_adapter_t* const p_adapter ); + + +static void +__adapter_destroying( + IN cl_obj_t* const p_obj ); + + +static void +__adapter_free( + IN cl_obj_t* const p_obj ); + + +static ib_api_status_t +__ipoib_pnp_reg( + IN ipoib_adapter_t* const p_adapter, + IN ib_pnp_class_t flags ); + + +static void +__ipoib_pnp_dereg( + IN void* context ); + + +static void +__ipoib_adapter_reset( + IN void* context); + + +static ib_api_status_t +__ipoib_pnp_cb( + IN ib_pnp_rec_t *p_pnp_rec ); + + +void +ipoib_join_mcast( + IN ipoib_adapter_t* const p_adapter ); + + +/* Leaves all mcast groups when port goes down. */ +static void +ipoib_clear_mcast( + IN ipoib_port_t* const p_port ); + +NDIS_STATUS +ipoib_get_adapter_guids( + IN NDIS_HANDLE* const h_adapter, + IN OUT ipoib_adapter_t *p_adapter ); + +NDIS_STATUS +ipoib_get_adapter_params( + IN OUT ipoib_adapter_t *p_adapter, + OUT PUCHAR *p_mac, + OUT UINT *p_len); + + +/* Implementation */ +ib_api_status_t +ipoib_create_adapter( + IN void* const h_adapter, + OUT ipoib_adapter_t** const pp_adapter ) +{ + ipoib_adapter_t *p_adapter; + NDIS_STATUS status; + ib_api_status_t ib_status; + cl_status_t cl_status; + PUCHAR mac; + UINT len; + + IPOIB_ENTER( IPOIB_DBG_INIT ); + + p_adapter = (ipoib_adapter_t *) cl_zalloc( sizeof(ipoib_adapter_t) ); + if( !p_adapter ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed to allocate ipoib_adapter_t (%d bytes)", + sizeof(ipoib_adapter_t)) ); + return IB_INSUFFICIENT_MEMORY; + } + + adapter_construct( p_adapter ); + + p_adapter->h_adapter = h_adapter; + + p_adapter->p_ifc = (ib_al_ifc_t *) cl_zalloc( sizeof(ib_al_ifc_t) ); + if( !p_adapter->p_ifc ) + { + __adapter_free( &p_adapter->obj ); + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ipoib_create_adapter failed to alloc ipoib_ifc_t %d bytes\n", + sizeof(ib_al_ifc_t)) ); + return IB_INSUFFICIENT_MEMORY; + } + + /* Get the CA and port GUID from the bus driver. */ + status = ipoib_get_adapter_guids( (NDIS_HANDLE *const) h_adapter, p_adapter ); + if( status != NDIS_STATUS_SUCCESS ) + { + ASSERT(FALSE); + __adapter_free( &p_adapter->obj ); + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ipoib_get_adapter_guids returned 0x%.8X.\n", status) ); + return IB_ERROR; + } + + IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, + ("Port %016I64x (CA %016I64x port %d) initializing\n", + p_adapter->guids.port_guid.guid, p_adapter->guids.ca_guid, + p_adapter->guids.port_num) ); + + cl_status = cl_obj_init( &p_adapter->obj, CL_DESTROY_SYNC, + __adapter_destroying, NULL, __adapter_free ); + if( cl_status != CL_SUCCESS ) + { + __adapter_free( &p_adapter->obj ); + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("cl_obj_init returned %#x\n", cl_status) ); + return IB_ERROR; + } + + /* Read configuration parameters. */ + status = ipoib_get_adapter_params( p_adapter , &mac, &len ); + if( status != NDIS_STATUS_SUCCESS ) + { + cl_obj_destroy( &p_adapter->obj ); + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ipoib_get_adapter_params returned 0x%.8x.\n", status) ); + return IB_ERROR; + } + + ib_status = adapter_init( p_adapter ); + if( ib_status != IB_SUCCESS ) + { + cl_obj_destroy( &p_adapter->obj ); + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("adapter_init returned %s.\n", + p_adapter->p_ifc->get_err_str( ib_status )) ); + return ib_status; + } + + ETH_COPY_NETWORK_ADDRESS( p_adapter->params.conf_mac.addr, p_adapter->mac.addr ); + /* If there is a NetworkAddress override in registry, use it */ + if( (status == NDIS_STATUS_SUCCESS) && (len == HW_ADDR_LEN) ) + { + if( ETH_IS_MULTICAST(mac) || ETH_IS_BROADCAST(mac) || + !ETH_IS_LOCALLY_ADMINISTERED(mac) ) + { + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_INIT, + ("Overriding NetworkAddress is invalid - " + "%02x-%02x-%02x-%02x-%02x-%02x\n", + mac[0], mac[1], mac[2], + mac[3], mac[4], mac[5]) ); + } + else + { + ETH_COPY_NETWORK_ADDRESS( p_adapter->params.conf_mac.addr, mac ); + } + } + + *pp_adapter = p_adapter; + + IPOIB_EXIT( IPOIB_DBG_INIT ); + return IB_SUCCESS; +} + + +ib_api_status_t +ipoib_start_adapter( + IN ipoib_adapter_t* const p_adapter ) +{ + ib_api_status_t status; + + IPOIB_ENTER( IPOIB_DBG_INIT ); + + status = __ipoib_pnp_reg( p_adapter, + IB_PNP_FLAG_REG_SYNC | IB_PNP_FLAG_REG_COMPLETE ); + + IPOIB_EXIT( IPOIB_DBG_INIT ); + return status; +} + + +void +ipoib_destroy_adapter( + IN ipoib_adapter_t* const p_adapter ) +{ + IPOIB_ENTER( IPOIB_DBG_INIT ); + + CL_ASSERT( p_adapter ); + + /* + * Flag the adapter as being removed. We use the IB_PNP_PORT_REMOVE state + * for this purpose. Note that we protect this state change with both the + * mutex and the lock. The mutex provides synchronization as a whole + * between destruction and AL callbacks (PnP, Query, Destruction). + * The lock provides protection + */ + KeWaitForMutexObject( + &p_adapter->mutex, Executive, KernelMode, FALSE, NULL ); + cl_obj_lock( &p_adapter->obj ); + p_adapter->state = IB_PNP_PORT_REMOVE; + + /* + * Clear the pointer to the port object since the object destruction + * will cascade to child objects. This prevents potential duplicate + * destruction (or worse, stale pointer usage). + */ + p_adapter->p_port = NULL; + + cl_obj_unlock( &p_adapter->obj ); + + KeReleaseMutex( &p_adapter->mutex, FALSE ); + + cl_obj_destroy( &p_adapter->obj ); + + IPOIB_EXIT( IPOIB_DBG_INIT ); +} + + +static void +adapter_construct( + IN ipoib_adapter_t* const p_adapter ) +{ + cl_obj_construct( &p_adapter->obj, IPOIB_OBJ_INSTANCE ); + cl_spinlock_construct( &p_adapter->send_stat_lock ); + cl_spinlock_construct( &p_adapter->recv_stat_lock ); + cl_qpool_construct( &p_adapter->item_pool ); + KeInitializeMutex( &p_adapter->mutex, 0 ); + + cl_thread_construct(&p_adapter->destroy_thread); + + cl_vector_construct( &p_adapter->ip_vector ); + + cl_perf_construct( &p_adapter->perf ); + + p_adapter->state = IB_PNP_PORT_ADD; + p_adapter->port_rate = FOUR_X_IN_100BPS; +} + + +static ib_api_status_t +adapter_init( + IN ipoib_adapter_t* const p_adapter ) +{ + cl_status_t cl_status; + ib_api_status_t status; + + IPOIB_ENTER( IPOIB_DBG_INIT ); + + cl_status = cl_perf_init( &p_adapter->perf, MaxPerf ); + if( cl_status != CL_SUCCESS ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("cl_perf_init returned %#x\n", cl_status) ); + return IB_ERROR; + } + + cl_status = cl_spinlock_init( &p_adapter->send_stat_lock ); + if( cl_status != CL_SUCCESS ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("cl_spinlock_init returned %#x\n", cl_status) ); + return IB_ERROR; + } + + cl_status = cl_spinlock_init( &p_adapter->recv_stat_lock ); + if( cl_status != CL_SUCCESS ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("cl_spinlock_init returned %#x\n", cl_status) ); + return IB_ERROR; + } + + cl_status = cl_qpool_init( &p_adapter->item_pool, ITEM_POOL_START, 0, + ITEM_POOL_GROW, sizeof(cl_pool_obj_t), NULL, NULL, NULL ); + if( cl_status != CL_SUCCESS ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("cl_qpool_init returned %#x\n", cl_status) ); + return IB_ERROR; + } + + + /* We manually manage the size and capacity of the vector. */ + cl_status = cl_vector_init( &p_adapter->ip_vector, 0, + 0, sizeof(net_address_item_t), NULL, NULL, p_adapter ); + if( cl_status != CL_SUCCESS ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("cl_vector_init for ip_vector returned %#x\n", + cl_status) ); + return IB_ERROR; + } + + /* Validate the port GUID and generate the MAC address. */ + status = + ipoib_mac_from_guid( p_adapter->guids.port_guid.guid, p_adapter->params.guid_mask, &p_adapter->mac); + if( status != IB_SUCCESS ) + { + if( status == IB_INVALID_GUID_MASK ) + { + IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_ERROR, + ("Invalid GUID mask received, rejecting it") ); + ipoib_create_log(p_adapter->h_adapter, GUID_MASK_LOG_INDEX, EVENT_IPOIB_WRONG_PARAMETER_WRN); + } + + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ipoib_mac_from_guid returned %s\n", + p_adapter->p_ifc->get_err_str( status )) ); + return status; + } + + /* Open AL. */ + status = p_adapter->p_ifc->open_al( &p_adapter->h_al ); + if( status != IB_SUCCESS ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ib_open_al returned %s\n", + p_adapter->p_ifc->get_err_str( status )) ); + return status; + } + + IPOIB_EXIT( IPOIB_DBG_INIT ); + return status; +} + + +static ib_api_status_t +__ipoib_pnp_reg( + IN ipoib_adapter_t* const p_adapter, + IN ib_pnp_class_t flags ) +{ + ib_api_status_t status; + ib_pnp_req_t pnp_req; + + IPOIB_ENTER( IPOIB_DBG_INIT ); + + CL_ASSERT( !p_adapter->h_pnp ); + CL_ASSERT( !p_adapter->registering ); + + p_adapter->registering = TRUE; + + /* Register for PNP events. */ + cl_memclr( &pnp_req, sizeof(pnp_req) ); + pnp_req.pnp_class = IB_PNP_PORT | flags; + /* + * Context is the cl_obj of the adapter to allow passing cl_obj_deref + * to ib_dereg_pnp. + */ + pnp_req.pnp_context = &p_adapter->obj; + pnp_req.pfn_pnp_cb = __ipoib_pnp_cb; + status = p_adapter->p_ifc->reg_pnp( p_adapter->h_al, &pnp_req, &p_adapter->h_pnp ); + if( status != IB_SUCCESS ) + { + ASSERT(FALSE); + p_adapter->registering = FALSE; + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ib_reg_pnp returned %s\n", + p_adapter->p_ifc->get_err_str( status )) ); + return status; + } + /* + * Reference the adapter on behalf of the PNP registration. + * This allows the destruction to block until the PNP deregistration + * completes. + */ + cl_obj_ref( &p_adapter->obj ); + + IPOIB_EXIT( IPOIB_DBG_INIT ); + return status; +} + + +static void +__adapter_destroying( + IN cl_obj_t* const p_obj ) +{ + ipoib_adapter_t *p_adapter; + KLOCK_QUEUE_HANDLE hdl; + + IPOIB_ENTER( IPOIB_DBG_INIT ); + + p_adapter = PARENT_STRUCT( p_obj, ipoib_adapter_t, obj ); + + /* + * The adapter's object will be dereferenced when the deregistration + * completes. No need to lock here since all PnP related API calls + * are driven by NDIS (via the Init/Reset/Destroy paths). + */ + if( p_adapter->h_pnp ) + { + p_adapter->p_ifc->dereg_pnp( p_adapter->h_pnp, (ib_pfn_destroy_cb_t) cl_obj_deref ); + p_adapter->h_pnp = NULL; + } + + if( p_adapter->packet_filter ) + { + KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl ); + cl_obj_lock( &p_adapter->obj ); + + ASSERT( cl_qlist_count( &g_ipoib.adapter_list ) ); + cl_qlist_remove_item( &g_ipoib.adapter_list, &p_adapter->entry ); + + p_adapter->packet_filter = 0; + + cl_obj_unlock( &p_adapter->obj ); + KeReleaseInStackQueuedSpinLock( &hdl ); + } + + IPOIB_EXIT( IPOIB_DBG_INIT ); +} + + +static void +__adapter_free( + IN cl_obj_t* const p_obj ) +{ + ipoib_adapter_t *p_adapter; + + IPOIB_ENTER( IPOIB_DBG_INIT ); + + p_adapter = PARENT_STRUCT( p_obj, ipoib_adapter_t, obj ); + + if( p_adapter->p_ifc ) + { + if( p_adapter->h_al ) + p_adapter->p_ifc->close_al( p_adapter->h_al ); + + cl_free( p_adapter->p_ifc ); + p_adapter->p_ifc = NULL; + } + + cl_vector_destroy( &p_adapter->ip_vector ); + cl_qpool_destroy( &p_adapter->item_pool ); + cl_spinlock_destroy( &p_adapter->recv_stat_lock ); + cl_spinlock_destroy( &p_adapter->send_stat_lock ); + cl_obj_deinit( p_obj ); + + cl_perf_destroy( &p_adapter->perf, TRUE ); + + cl_free( p_adapter ); + + IPOIB_EXIT( IPOIB_DBG_INIT ); +} + + +static ib_api_status_t +ipoib_query_pkey_index(ipoib_adapter_t *p_adapter) +{ + ib_api_status_t status; + ib_ca_attr_t *ca_attr; + uint32_t ca_size; + uint16_t index = 0; + + /* Query the CA for Pkey table */ + status = p_adapter->p_ifc->query_ca(p_adapter->p_port->ib_mgr.h_ca, NULL, &ca_size); + if(status != IB_INSUFFICIENT_MEMORY) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ib_query_ca failed\n")); + return status; + } + + ca_attr = (ib_ca_attr_t*)cl_zalloc(ca_size); + if (!ca_attr) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("cl_zalloc can't allocate %d\n",ca_size)); + return IB_INSUFFICIENT_MEMORY; + } + + status = p_adapter->p_ifc->query_ca(p_adapter->p_port->ib_mgr.h_ca, ca_attr,&ca_size); + if( status != IB_SUCCESS ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ib_query_ca returned %s\n", + p_adapter->p_ifc->get_err_str( status )) ); + goto pkey_end; + } + CL_ASSERT(ca_attr->p_port_attr[p_adapter->p_port->port_num -1].p_pkey_table[0] == IB_DEFAULT_PKEY); + for(index = 0; index < ca_attr->p_port_attr[p_adapter->p_port->port_num -1].num_pkeys; index++) + { + if(cl_hton16(p_adapter->guids.port_guid.pkey) == ca_attr->p_port_attr[p_adapter->p_port->port_num -1].p_pkey_table[index]) + break; + } + if(index >= ca_attr->p_port_attr[p_adapter->p_port->port_num -1].num_pkeys) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Pkey table is invalid, index not found\n")); + NdisWriteErrorLogEntry( p_adapter->h_adapter, + EVENT_IPOIB_PARTITION_ERR, 1, p_adapter->guids.port_guid.pkey ); + status = IB_NOT_FOUND; + p_adapter->p_port->pkey_index = PKEY_INVALID_INDEX; + goto pkey_end; + } + + p_adapter->p_port->pkey_index = index; + IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_IB, + ("for PKEY = 0x%04X got index = %d\n",p_adapter->guids.port_guid.pkey,index)); + +pkey_end: + if(ca_attr) + cl_free(ca_attr); + return status; +} + +static ib_api_status_t +__ipoib_pnp_cb( + IN ib_pnp_rec_t *p_pnp_rec ) +{ + ipoib_adapter_t *p_adapter; + ipoib_port_t *p_port; + ib_pnp_event_t old_state; + ib_pnp_port_rec_t *p_port_rec; + ib_api_status_t status = IB_SUCCESS; + NDIS_LINK_STATE link_state; + NDIS_STATUS_INDICATION status_indication; + + IPOIB_ENTER( IPOIB_DBG_PNP ); + + CL_ASSERT( p_pnp_rec ); + NdisZeroMemory(&link_state, sizeof(NDIS_LINK_STATE)); + p_adapter = + PARENT_STRUCT( p_pnp_rec->pnp_context, ipoib_adapter_t, obj ); + + CL_ASSERT( p_adapter ); + + /* Synchronize with destruction */ + KeWaitForMutexObject( + &p_adapter->mutex, Executive, KernelMode, FALSE, NULL ); + cl_obj_lock( &p_adapter->obj ); + old_state = p_adapter->state; + cl_obj_unlock( &p_adapter->obj ); + if( old_state == IB_PNP_PORT_REMOVE ) + { + KeReleaseMutex( &p_adapter->mutex, FALSE ); + IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_PNP, + ("Aborting - Adapter destroying.\n") ); + return IB_NOT_DONE; + } + + IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_PNP, + ("p_pnp_rec->pnp_event = 0x%x (%s)\n", + p_pnp_rec->pnp_event, ib_get_pnp_event_str( p_pnp_rec->pnp_event )) ); + + p_port_rec = (ib_pnp_port_rec_t*)p_pnp_rec; + + switch( p_pnp_rec->pnp_event ) + { + case IB_PNP_PORT_ADD: + CL_ASSERT( !p_pnp_rec->context ); + /* Only process our port GUID. */ + if( p_pnp_rec->guid != p_adapter->guids.port_guid.guid ) + { + status = IB_NOT_DONE; + break; + } + + /* Don't process if we're destroying. */ + if( p_adapter->obj.state == CL_DESTROYING ) + { + status = IB_NOT_DONE; + break; + } + + CL_ASSERT( !p_adapter->p_port ); + /* Allocate all IB resources. */ + cl_obj_lock( &p_adapter->obj ); + p_adapter->state = IB_PNP_PORT_ADD; + cl_obj_unlock( &p_adapter->obj ); + status = ipoib_create_port( p_adapter, p_port_rec, &p_port ); + cl_obj_lock( &p_adapter->obj ); + if( status != IB_SUCCESS ) + { + p_adapter->state = old_state; + cl_obj_unlock( &p_adapter->obj ); + p_adapter->hung = TRUE; + break; + } + + p_pnp_rec->context = p_port; + + p_adapter->p_port = p_port; + cl_obj_unlock( &p_adapter->obj ); + break; + + case IB_PNP_PORT_REMOVE: + /* Release all IB resources. */ + CL_ASSERT( p_pnp_rec->context ); + + cl_obj_lock( &p_adapter->obj ); + p_adapter->state = IB_PNP_PORT_REMOVE; + p_port = p_adapter->p_port; + p_adapter->p_port = NULL; + cl_obj_unlock( &p_adapter->obj ); + ipoib_port_destroy( p_port ); + p_pnp_rec->context = NULL; + status = IB_SUCCESS; + break; + + case IB_PNP_PORT_ACTIVE: + /* Join multicast groups and put QP in RTS. */ + CL_ASSERT( p_pnp_rec->context ); + + cl_obj_lock( &p_adapter->obj ); + p_adapter->state = IB_PNP_PORT_INIT; + cl_obj_unlock( &p_adapter->obj ); + ipoib_port_up( p_adapter->p_port, p_port_rec ); + + status = IB_SUCCESS; + break; + + case IB_PNP_PORT_ARMED: + status = IB_SUCCESS; + break; + + case IB_PNP_PORT_INIT: + /* + * Init could happen if the SM brings the port down + * without changing the physical link. + */ + case IB_PNP_PORT_DOWN: + CL_ASSERT( p_pnp_rec->context ); + + cl_obj_lock( &p_adapter->obj ); + old_state = p_adapter->state; + p_adapter->state = IB_PNP_PORT_DOWN; + cl_obj_unlock( &p_adapter->obj ); + status = IB_SUCCESS; + + if( !p_adapter->registering && old_state != IB_PNP_PORT_DOWN ) + { + link_state.Header.Revision = NDIS_LINK_STATE_REVISION_1; + link_state.Header.Type = NDIS_OBJECT_TYPE_DEFAULT; + link_state.Header.Size = sizeof(NDIS_LINK_STATE); + link_state.MediaConnectState = MediaConnectStateDisconnected; + //link_state.MediaConnectState = MediaConnectStateConnected; + link_state.MediaDuplexState = MediaDuplexStateFull; + link_state.XmitLinkSpeed = link_state.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED; + + IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication, + p_adapter->h_adapter, + NDIS_STATUS_LINK_STATE, + (PVOID)&link_state, + sizeof(link_state)); + + NdisMIndicateStatusEx(p_adapter->h_adapter,&status_indication); + IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, + ("Link DOWN!\n") ); + + ipoib_port_down( p_adapter->p_port ); + } + break; + + case IB_PNP_REG_COMPLETE: + if( p_adapter->registering ) + { + p_adapter->registering = FALSE; + cl_obj_lock( &p_adapter->obj ); + old_state = p_adapter->state; + cl_obj_unlock( &p_adapter->obj ); + + if( old_state == IB_PNP_PORT_DOWN ) + { + /* If we were initializing, we might have pended some OIDs. */ + ipoib_resume_oids( p_adapter ); + + link_state.Header.Revision = NDIS_LINK_STATE_REVISION_1; + link_state.Header.Type = NDIS_OBJECT_TYPE_DEFAULT; + link_state.Header.Size = sizeof(NDIS_LINK_STATE); + link_state.MediaConnectState = MediaConnectStateDisconnected; + //link_state.MediaConnectState = MediaConnectStateConnected; + link_state.MediaDuplexState = MediaDuplexStateFull; + link_state.XmitLinkSpeed = link_state.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED; + + IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication, + p_adapter->h_adapter, + NDIS_STATUS_LINK_STATE, + (PVOID)&link_state, + sizeof(link_state)); + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_INIT, + ("Indicate DISCONNECT\n") ); + NdisMIndicateStatusEx(p_adapter->h_adapter,&status_indication); + } + } + + if( p_adapter->reset && p_adapter->state != IB_PNP_PORT_INIT ) + { + p_adapter->reset = FALSE; + NdisMResetComplete( + p_adapter->h_adapter, NDIS_STATUS_SUCCESS, TRUE ); + } + status = IB_SUCCESS; + break; + + default: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, + ("IPOIB: Received unhandled PnP event 0x%x (%s)\n", + p_pnp_rec->pnp_event, ib_get_pnp_event_str( p_pnp_rec->pnp_event )) ); + /* Fall through. */ + + status = IB_SUCCESS; + + /* We ignore events below if the link is not active. */ + if( p_port_rec->p_port_attr->link_state != IB_LINK_ACTIVE ) + break; + + case IB_PNP_PKEY_CHANGE: + if(p_pnp_rec->pnp_event == IB_PNP_PKEY_CHANGE && + p_adapter->guids.port_guid.pkey != IB_DEFAULT_PKEY) + { + status = ipoib_query_pkey_index(p_adapter); + if(status != IB_SUCCESS) + { + cl_obj_lock( &p_adapter->obj ); + p_adapter->state = IB_PNP_PORT_INIT; + cl_obj_unlock( &p_adapter->obj ); + } + } + + case IB_PNP_SM_CHANGE: + case IB_PNP_GID_CHANGE: + case IB_PNP_LID_CHANGE: + + cl_obj_lock( &p_adapter->obj ); + old_state = p_adapter->state; + switch( old_state ) + { + case IB_PNP_PORT_DOWN: + p_adapter->state = IB_PNP_PORT_INIT; + break; + + default: + p_adapter->state = IB_PNP_PORT_DOWN; + } + cl_obj_unlock( &p_adapter->obj ); + + if( p_adapter->registering ) + break; + + switch( old_state ) + { + case IB_PNP_PORT_ACTIVE: + case IB_PNP_PORT_INIT: + link_state.Header.Revision = NDIS_LINK_STATE_REVISION_1; + link_state.Header.Type = NDIS_OBJECT_TYPE_DEFAULT; + link_state.Header.Size = sizeof(NDIS_LINK_STATE); + link_state.MediaConnectState = MediaConnectStateDisconnected; + //link_state.MediaConnectState = MediaConnectStateConnected; + link_state.MediaDuplexState = MediaDuplexStateFull; + link_state.XmitLinkSpeed = link_state.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED; + + IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication, + p_adapter->h_adapter, + NDIS_STATUS_LINK_STATE, + (PVOID)&link_state, + sizeof(link_state)); + + NdisMIndicateStatusEx(p_adapter->h_adapter,&status_indication); + + IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, + ("Link DOWN!\n") ); + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_INIT, + ("Indicate DISCONNECT\n") ); + + ipoib_port_down( p_adapter->p_port ); + /* Fall through. */ + + case IB_PNP_PORT_DOWN: + cl_obj_lock( &p_adapter->obj ); + p_adapter->state = IB_PNP_PORT_INIT; + cl_obj_unlock( &p_adapter->obj ); + ipoib_port_up( p_adapter->p_port, (ib_pnp_port_rec_t*)p_pnp_rec ); + } + break; + } + + KeReleaseMutex( &p_adapter->mutex, FALSE ); + + IPOIB_EXIT( IPOIB_DBG_PNP ); + return status; +} + + +/* Joins/leaves mcast groups based on currently programmed mcast MACs. */ +void +ipoib_refresh_mcast( + IN ipoib_adapter_t* const p_adapter, + IN mac_addr_t* const p_mac_array, + IN const uint8_t num_macs ) +{ + uint8_t i, j; + ipoib_port_t *p_port = NULL; + + IPOIB_ENTER( IPOIB_DBG_MCAST ); + cl_obj_lock( &p_adapter->obj ); + if( p_adapter->state == IB_PNP_PORT_ACTIVE ) + { + p_port = p_adapter->p_port; + ipoib_port_ref( p_port, ref_refresh_mcast ); + } + cl_obj_unlock( &p_adapter->obj ); + + if( p_port ) + { + /* Purge old entries. */ + for( i = 0; i < p_adapter->mcast_array_size; i++ ) + { + for( j = 0; j < num_macs; j++ ) + { + if( !cl_memcmp( &p_adapter->mcast_array[i], &p_mac_array[j], + sizeof(mac_addr_t) ) ) + { + break; + } + } + if( j != num_macs ) + continue; + + ipoib_port_remove_endpt( p_port, p_adapter->mcast_array[i] ); + } + + /* Add new entries */ + for( i = 0; i < num_macs; i++ ) + { + for( j = 0; j < p_adapter->mcast_array_size; j++ ) + { + if( !cl_memcmp( &p_adapter->mcast_array[j], &p_mac_array[i], + sizeof(mac_addr_t) ) ) + { + break; + } + } + + if( j != p_adapter->mcast_array_size ) + continue; + if ( ( p_mac_array[i].addr[0] == 1 && p_mac_array[i].addr[1] == 0 && p_mac_array[i].addr[2] == 0x5e && + p_mac_array[i].addr[3] == 0 && p_mac_array[i].addr[4] == 0 && p_mac_array[i].addr[5] == 1 ) || + !( p_mac_array[i].addr[0] == 1 && p_mac_array[i].addr[1] == 0 && p_mac_array[i].addr[2] == 0x5e ) + ) + { + ipoib_port_join_mcast( p_port, p_mac_array[i], IB_MC_REC_STATE_FULL_MEMBER ); + } + } + } + + /* Copy the MAC array. */ + NdisMoveMemory( p_adapter->mcast_array, p_mac_array, + num_macs * sizeof(mac_addr_t) ); + p_adapter->mcast_array_size = num_macs; + + if( p_port ) + ipoib_port_deref( p_port, ref_refresh_mcast ); + + IPOIB_EXIT( IPOIB_DBG_MCAST ); +} + + +ib_api_status_t +ipoib_reset_adapter( + IN ipoib_adapter_t* const p_adapter ) +{ + ib_api_status_t status; + ib_pnp_handle_t h_pnp; + + IPOIB_ENTER( IPOIB_DBG_INIT ); + + if( p_adapter->reset ) + return IB_INVALID_STATE; + + p_adapter->hung = FALSE; + p_adapter->reset = TRUE; + + if( p_adapter->h_pnp ) + { + h_pnp = p_adapter->h_pnp; + p_adapter->h_pnp = NULL; + status = p_adapter->p_ifc->dereg_pnp( h_pnp, __ipoib_pnp_dereg ); + if( status == IB_SUCCESS ) + status = IB_NOT_DONE; + } + else + { + status = __ipoib_pnp_reg( p_adapter, IB_PNP_FLAG_REG_COMPLETE ); + if( status == IB_SUCCESS ) + p_adapter->hung = FALSE; + } + if (status == IB_NOT_DONE) { + p_adapter->reset = TRUE; + } + else { + p_adapter->reset = FALSE; + } + IPOIB_EXIT( IPOIB_DBG_INIT ); + return status; +} + + +static void +__ipoib_pnp_dereg( + IN void* context ) +{ + ipoib_adapter_t* p_adapter; + + IPOIB_ENTER( IPOIB_DBG_INIT ); + + p_adapter = PARENT_STRUCT( context, ipoib_adapter_t, obj ); + + cl_thread_init(&p_adapter->destroy_thread, __ipoib_adapter_reset, (void*)p_adapter, "destroy_thread"); + + IPOIB_ENTER( IPOIB_DBG_INIT ); + +} + +static void +__ipoib_adapter_reset( + IN void* context) +{ + + ipoib_adapter_t *p_adapter; + ipoib_port_t *p_port; + ib_api_status_t status; + ib_pnp_event_t state; + + IPOIB_ENTER( IPOIB_DBG_INIT ); + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Got RESET\n") ); +// return; + p_adapter = (ipoib_adapter_t*)context; + + /* Synchronize with destruction */ + KeWaitForMutexObject( + &p_adapter->mutex, Executive, KernelMode, FALSE, NULL ); + + cl_obj_lock( &p_adapter->obj ); + + CL_ASSERT( !p_adapter->h_pnp ); + + if( p_adapter->state != IB_PNP_PORT_REMOVE ) + p_adapter->state = IB_PNP_PORT_ADD; + + state = p_adapter->state; + + /* Destroy the current port instance if it still exists. */ + p_port = p_adapter->p_port; + p_adapter->p_port = NULL; + cl_obj_unlock( &p_adapter->obj ); + + if( p_port ) + ipoib_port_destroy( p_port ); + ASSERT(p_adapter->reset == TRUE); + if( state != IB_PNP_PORT_REMOVE ) + { + status = __ipoib_pnp_reg( p_adapter, IB_PNP_FLAG_REG_COMPLETE ); + if( status != IB_SUCCESS ) + { + p_adapter->reset = FALSE; + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("__ipoib_pnp_reg returned %s\n", + p_adapter->p_ifc->get_err_str( status )) ); + NdisMResetComplete( + p_adapter->h_adapter, NDIS_STATUS_HARD_ERRORS, TRUE ); + } + } + else + { + p_adapter->reset = FALSE; + NdisMResetComplete( + p_adapter->h_adapter, NDIS_STATUS_SUCCESS, TRUE ); + status = IB_SUCCESS; + } + + /* Dereference the adapter since the previous registration is now gone. */ + cl_obj_deref( &p_adapter->obj ); + + KeReleaseMutex( &p_adapter->mutex, FALSE ); + + IPOIB_EXIT( IPOIB_DBG_INIT ); +} + + +void +ipoib_set_rate( + IN ipoib_adapter_t* const p_adapter, + IN const uint8_t link_width, + IN const uint8_t link_speed ) +{ + uint32_t rate; + + IPOIB_ENTER( IPOIB_DBG_INIT ); + + /* Set the link speed based on the IB link speed (1x vs 4x, etc). */ + switch( link_speed ) + { + case IB_LINK_SPEED_ACTIVE_2_5: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, + ("Link speed is 2.5Gs\n") ); + rate = IB_LINK_SPEED_ACTIVE_2_5; + break; + + case IB_LINK_SPEED_ACTIVE_5: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, + ("Link speed is 5G\n") ); + rate = IB_LINK_SPEED_ACTIVE_5; + break; + + case IB_LINK_SPEED_ACTIVE_10: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, + ("Link speed is 10G\n") ); + rate = IB_LINK_SPEED_ACTIVE_10; + break; + + default: + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Invalid link speed %d.\n", link_speed) ); + rate = 0; + } + + switch( link_width ) + { + case IB_LINK_WIDTH_ACTIVE_1X: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, + ("Link width is 1X\n") ); + rate *= ONE_X_IN_100BPS; + break; + + case IB_LINK_WIDTH_ACTIVE_4X: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, + ("Link width is 4X\n") ); + rate *= FOUR_X_IN_100BPS; + break; + + case IB_LINK_WIDTH_ACTIVE_12X: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, + ("Link width is 12X\n") ); + rate *= TWELVE_X_IN_100BPS; + break; + + default: + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Invalid link rate (%d).\n", link_width) ); + rate = 0; + } + + p_adapter->port_rate = rate; + IPOIB_EXIT( IPOIB_DBG_INIT ); +} + + +ib_api_status_t +ipoib_set_active( + IN ipoib_adapter_t* const p_adapter ) +{ + ib_pnp_event_t old_state; + uint8_t i; + ib_api_status_t status = IB_SUCCESS; + NDIS_LINK_STATE link_state; + NDIS_STATUS_INDICATION status_indication; + IPOIB_ENTER( IPOIB_DBG_INIT ); + + NdisZeroMemory(&link_state, sizeof(NDIS_LINK_STATE)); + cl_obj_lock( &p_adapter->obj ); + old_state = p_adapter->state; + + /* Change the state to indicate that we are now connected and live. */ + if( old_state == IB_PNP_PORT_INIT ) + p_adapter->state = IB_PNP_PORT_ACTIVE; + + cl_obj_unlock( &p_adapter->obj ); + + /* + * If we had a pending OID request for OID_GEN_LINK_SPEED, + * complete it now. + */ + switch( old_state ) + { + case IB_PNP_PORT_ADD: + ipoib_reg_addrs( p_adapter ); + /* Fall through. */ + + case IB_PNP_PORT_REMOVE: + ipoib_resume_oids( p_adapter ); + break; + + default: + if (p_adapter->guids.port_guid.pkey != IB_DEFAULT_PKEY) + { + status = ipoib_query_pkey_index(p_adapter); + if( IB_SUCCESS != status) + { + break; + } + } + /* Join all programmed multicast groups. */ + for( i = 0; i < p_adapter->mcast_array_size; i++ ) + { + ipoib_port_join_mcast( + p_adapter->p_port, p_adapter->mcast_array[i] ,IB_MC_REC_STATE_FULL_MEMBER); + } + + /* Register all existing addresses. */ + ipoib_reg_addrs( p_adapter ); + + ipoib_resume_oids( p_adapter ); + + /* + * Now that we're in the broadcast group, notify that + * we have a link. + */ + IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, ("Link UP!\n") ); + NdisWriteErrorLogEntry( p_adapter->h_adapter, + EVENT_IPOIB_PORT_UP + (p_adapter->port_rate/ONE_X_IN_100BPS), + 1, p_adapter->port_rate ); + + if( !p_adapter->reset ) + { + link_state.Header.Revision = NDIS_LINK_STATE_REVISION_1; + link_state.Header.Type = NDIS_OBJECT_TYPE_DEFAULT; + link_state.Header.Size = sizeof(NDIS_LINK_STATE); + link_state.MediaConnectState = MediaConnectStateConnected; + link_state.MediaDuplexState = MediaDuplexStateFull; + link_state.XmitLinkSpeed = + link_state.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED; + link_state.PauseFunctions = NdisPauseFunctionsSendAndReceive; + IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication, + p_adapter->h_adapter, + NDIS_STATUS_LINK_STATE, + (PVOID)&link_state, + sizeof(link_state)); + IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, ("***************Indicate connect!\n") ); + NdisMIndicateStatusEx(p_adapter->h_adapter,&status_indication); + } + } + + if( p_adapter->reset ) + { + ASSERT(FALSE); + p_adapter->reset = FALSE; + NdisMResetComplete( + p_adapter->h_adapter, NDIS_STATUS_SUCCESS, TRUE ); + } + + IPOIB_EXIT( IPOIB_DBG_INIT ); + return status; +} + +/* + * If something goes wrong after the port goes active, e.g. + * - PortInfo query failure + * - MC Join timeout + * - etc + * Mark the port state as down, resume any pended OIDS, etc. + */ +void +ipoib_set_inactive( + IN ipoib_adapter_t* const p_adapter ) +{ + ib_pnp_event_t old_state; + NDIS_LINK_STATE link_state; + NDIS_STATUS_INDICATION status_indication; + + IPOIB_ENTER( IPOIB_DBG_INIT ); + + NdisZeroMemory(&link_state, sizeof(NDIS_LINK_STATE)); + cl_obj_lock( &p_adapter->obj ); + old_state = p_adapter->state; + if( old_state != IB_PNP_PORT_REMOVE ) + p_adapter->state = IB_PNP_PORT_DOWN; + cl_obj_unlock( &p_adapter->obj ); + + /* + * If we had a pending OID request for OID_GEN_LINK_SPEED, + * complete it now. + */ + if( old_state == IB_PNP_PORT_INIT ) + { + link_state.Header.Revision = NDIS_LINK_STATE_REVISION_1; + link_state.Header.Type = NDIS_OBJECT_TYPE_DEFAULT; + link_state.Header.Size = sizeof(NDIS_LINK_STATE); + link_state.MediaConnectState = MediaConnectStateDisconnected; + //link_state.MediaConnectState = MediaConnectStateConnected; + + link_state.MediaDuplexState = MediaDuplexStateFull; + link_state.XmitLinkSpeed = link_state.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED; + + IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication, + p_adapter->h_adapter, + NDIS_STATUS_LINK_STATE, + (PVOID)&link_state, + sizeof(link_state)); + IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, ("Indicate Disconnect!\n") ); + NdisMIndicateStatusEx(p_adapter->h_adapter,&status_indication); + + ipoib_resume_oids( p_adapter ); + } + + if( p_adapter->reset ) + { + p_adapter->reset = FALSE; + NdisMResetComplete( + p_adapter->h_adapter, NDIS_STATUS_SUCCESS, TRUE ); + } + + IPOIB_EXIT( IPOIB_DBG_INIT ); +} + +NDIS_STATUS +ipoib_get_gen_stat( + IN ipoib_adapter_t* const p_adapter, + OUT pending_oid_t* const p_oid_info) +{ + PNDIS_STATISTICS_INFO StatisticsInfo; + IPOIB_ENTER( IPOIB_DBG_STAT ); + + if (p_oid_info->buf_len < sizeof(StatisticsInfo)) + { + *p_oid_info->p_bytes_needed = sizeof(NDIS_STATISTICS_INFO); + return NDIS_STATUS_INVALID_LENGTH; + } + + StatisticsInfo = (PNDIS_STATISTICS_INFO)p_oid_info->p_buf; + StatisticsInfo->Header.Revision = NDIS_OBJECT_REVISION_1; + StatisticsInfo->Header.Type = NDIS_OBJECT_TYPE_DEFAULT; + StatisticsInfo->Header.Size = sizeof(NDIS_STATISTICS_INFO); + /*StatisticsInfo->SupportedStatistics = NDIS_STATISTICS_FLAGS_VALID_RCV_DISCARDS | + NDIS_STATISTICS_FLAGS_VALID_RCV_ERROR | + NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_RCV | + NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_RCV | + NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_RCV | + NDIS_STATISTICS_FLAGS_VALID_BYTES_RCV | + NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_RCV | + NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_RCV | + NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_RCV | + + NDIS_STATISTICS_FLAGS_VALID_XMIT_DISCARDS | + NDIS_STATISTICS_FLAGS_VALID_XMIT_ERROR | + NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_XMIT | + NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_XMIT | + NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_XMIT | + NDIS_STATISTICS_FLAGS_VALID_BYTES_XMIT | + NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_XMIT | + NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_XMIT | + NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_XMIT; */ + + + StatisticsInfo->SupportedStatistics = NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_RCV | + //The data in the ifHCInUcastPkts member is valid. + NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_RCV | + //The data in the ifHCInMulticastPkts member is valid. + NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_RCV | + //The data in the ifHCInBroadcastPkts member is valid. + NDIS_STATISTICS_FLAGS_VALID_BYTES_RCV | + //The data in the ifHCInOctets member is valid. + NDIS_STATISTICS_FLAGS_VALID_RCV_DISCARDS | + //The data in the ifInDiscards member is valid. + NDIS_STATISTICS_FLAGS_VALID_RCV_ERROR | + //The data in the ifInErrors member is valid. + NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_XMIT | + //The data in the ifHCOutUcastPkts member is valid. + NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_XMIT | + //The data in the ifHCOutMulticastPkts member is valid. + NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_XMIT | + //The data in the ifHCOutBroadcastPkts member is valid. + NDIS_STATISTICS_FLAGS_VALID_BYTES_XMIT | + //The data in the ifHCOutOctets member is valid. + NDIS_STATISTICS_FLAGS_VALID_XMIT_ERROR | + //The data in the ifOutErrors member is valid. + NDIS_STATISTICS_FLAGS_VALID_XMIT_DISCARDS | + //The data in the ifOutDiscards member is valid. + NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_RCV | + //The data in the ifHCInUcastOctets member is valid. + NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_RCV | + //The data in the ifHCInMulticastOctets member is valid. + NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_RCV | + //The data in the ifHCInBroadcastOctets member is valid. + NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_XMIT | + //The data in the ifHCOutUcastOctets member is valid. + NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_XMIT | + //The data in the ifHCOutMulticastOctets member is valid. + NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_XMIT ; + //The data in the ifHCOutBroadcastOctets member is valid + + cl_spinlock_acquire( &p_adapter->recv_stat_lock ); + StatisticsInfo->ifInDiscards = p_adapter->recv_stats.comp.dropped + + p_adapter->recv_stats.comp.error; + StatisticsInfo->ifInErrors = p_adapter->recv_stats.comp.error; + StatisticsInfo->ifHCInOctets = p_adapter->recv_stats.ucast.bytes + + p_adapter->recv_stats.bcast.bytes + + p_adapter->recv_stats.mcast.bytes; + StatisticsInfo->ifHCInUcastPkts = p_adapter->recv_stats.ucast.frames; + StatisticsInfo->ifHCInMulticastPkts = p_adapter->recv_stats.mcast.frames; + StatisticsInfo->ifHCInBroadcastPkts = p_adapter->recv_stats.bcast.frames; + StatisticsInfo->ifHCInMulticastOctets = p_adapter->recv_stats.mcast.bytes; + StatisticsInfo->ifHCInBroadcastOctets = p_adapter->recv_stats.bcast.bytes; + StatisticsInfo->ifHCInUcastOctets = p_adapter->recv_stats.ucast.bytes; + cl_spinlock_release( &p_adapter->recv_stat_lock ); + + cl_spinlock_acquire( &p_adapter->send_stat_lock ); + StatisticsInfo->ifHCOutOctets = p_adapter->send_stats.ucast.bytes + + p_adapter->send_stats.mcast.bytes + + p_adapter->send_stats.bcast.bytes; + StatisticsInfo->ifHCOutUcastPkts = p_adapter->send_stats.ucast.frames; + StatisticsInfo->ifHCOutMulticastPkts = p_adapter->send_stats.mcast.frames; + StatisticsInfo->ifHCOutBroadcastPkts = p_adapter->send_stats.bcast.frames; + StatisticsInfo->ifOutErrors = p_adapter->send_stats.comp.error; + StatisticsInfo->ifOutDiscards = p_adapter->send_stats.comp.dropped; + StatisticsInfo->ifHCOutUcastOctets = p_adapter->send_stats.ucast.bytes; + StatisticsInfo->ifHCOutMulticastOctets = p_adapter->send_stats.mcast.bytes; + StatisticsInfo->ifHCOutBroadcastOctets = p_adapter->send_stats.bcast.bytes; + cl_spinlock_release( &p_adapter->send_stat_lock ); + + *p_oid_info->p_bytes_used = sizeof(NDIS_STATISTICS_INFO); + + IPOIB_EXIT( IPOIB_DBG_INIT ); + return NDIS_STATUS_SUCCESS; +} + +NDIS_STATUS +ipoib_get_recv_stat( + IN ipoib_adapter_t* const p_adapter, + IN const ip_stat_sel_t stat_sel, + IN pending_oid_t* const p_oid_info ) +{ + uint64_t stat; + + IPOIB_ENTER( IPOIB_DBG_STAT ); + + CL_ASSERT( p_adapter ); + + cl_spinlock_acquire( &p_adapter->recv_stat_lock ); + switch( stat_sel ) + { + case IP_STAT_SUCCESS: + stat = p_adapter->recv_stats.comp.success; + break; + + case IP_STAT_ERROR: + stat = p_adapter->recv_stats.comp.error; + break; + + case IP_STAT_DROPPED: + stat = p_adapter->recv_stats.comp.dropped; + break; + + case IP_STAT_UCAST_BYTES: + stat = p_adapter->recv_stats.ucast.bytes; + break; + + case IP_STAT_UCAST_FRAMES: + stat = p_adapter->recv_stats.ucast.frames; + break; + + case IP_STAT_BCAST_BYTES: + stat = p_adapter->recv_stats.bcast.bytes; + break; + + case IP_STAT_BCAST_FRAMES: + stat = p_adapter->recv_stats.bcast.frames; + break; + + case IP_STAT_MCAST_BYTES: + stat = p_adapter->recv_stats.mcast.bytes; + break; + + case IP_STAT_MCAST_FRAMES: + stat = p_adapter->recv_stats.mcast.frames; + break; + + default: + stat = 0; + } + cl_spinlock_release( &p_adapter->recv_stat_lock ); + + *p_oid_info->p_bytes_needed = sizeof(uint64_t); + + if( p_oid_info->buf_len >= sizeof(uint64_t) ) + { + *((uint64_t*)p_oid_info->p_buf) = stat; + *p_oid_info->p_bytes_used = sizeof(uint64_t); + } + else if( p_oid_info->buf_len >= sizeof(uint32_t) ) + { + *((uint32_t*)p_oid_info->p_buf) = (uint32_t)stat; + *p_oid_info->p_bytes_used = sizeof(uint32_t); + } + else + { + *p_oid_info->p_bytes_used = 0; + IPOIB_EXIT( IPOIB_DBG_STAT ); + return NDIS_STATUS_INVALID_LENGTH; + } + + IPOIB_EXIT( IPOIB_DBG_STAT ); + return NDIS_STATUS_SUCCESS; +} + + +void +ipoib_inc_recv_stat( + IN ipoib_adapter_t* const p_adapter, + IN const ip_stat_sel_t stat_sel, + IN const size_t bytes OPTIONAL, + IN const size_t packets OPTIONAL ) +{ + IPOIB_ENTER( IPOIB_DBG_STAT ); + + cl_spinlock_acquire( &p_adapter->recv_stat_lock ); + switch( stat_sel ) + { + case IP_STAT_ERROR: + p_adapter->recv_stats.comp.error++; + break; + + case IP_STAT_DROPPED: + p_adapter->recv_stats.comp.dropped++; + break; + + case IP_STAT_UCAST_BYTES: + case IP_STAT_UCAST_FRAMES: + p_adapter->recv_stats.comp.success++; + p_adapter->recv_stats.ucast.frames += packets; + p_adapter->recv_stats.ucast.bytes += bytes; + break; + + case IP_STAT_BCAST_BYTES: + case IP_STAT_BCAST_FRAMES: + p_adapter->recv_stats.comp.success++; + p_adapter->recv_stats.bcast.frames += packets; + p_adapter->recv_stats.bcast.bytes += bytes; + break; + + case IP_STAT_MCAST_BYTES: + case IP_STAT_MCAST_FRAMES: + p_adapter->recv_stats.comp.success++; + p_adapter->recv_stats.mcast.frames += packets; + p_adapter->recv_stats.mcast.bytes += bytes; + break; + + default: + break; + } + cl_spinlock_release( &p_adapter->recv_stat_lock ); + + IPOIB_EXIT( IPOIB_DBG_STAT ); +} + +NDIS_STATUS +ipoib_get_send_stat( + IN ipoib_adapter_t* const p_adapter, + IN const ip_stat_sel_t stat_sel, + IN pending_oid_t* const p_oid_info ) +{ + uint64_t stat; + + IPOIB_ENTER( IPOIB_DBG_STAT ); + + CL_ASSERT( p_adapter ); + + cl_spinlock_acquire( &p_adapter->send_stat_lock ); + switch( stat_sel ) + { + case IP_STAT_SUCCESS: + stat = p_adapter->send_stats.comp.success; + break; + + case IP_STAT_ERROR: + stat = p_adapter->send_stats.comp.error; + break; + + case IP_STAT_DROPPED: + stat = p_adapter->send_stats.comp.dropped; + break; + + case IP_STAT_UCAST_BYTES: + stat = p_adapter->send_stats.ucast.bytes; + break; + + case IP_STAT_UCAST_FRAMES: + stat = p_adapter->send_stats.ucast.frames; + break; + + case IP_STAT_BCAST_BYTES: + stat = p_adapter->send_stats.bcast.bytes; + break; + + case IP_STAT_BCAST_FRAMES: + stat = p_adapter->send_stats.bcast.frames; + break; + + case IP_STAT_MCAST_BYTES: + stat = p_adapter->send_stats.mcast.bytes; + break; + + case IP_STAT_MCAST_FRAMES: + stat = p_adapter->send_stats.mcast.frames; + break; + + default: + stat = 0; + } + cl_spinlock_release( &p_adapter->send_stat_lock ); + + *p_oid_info->p_bytes_needed = sizeof(uint64_t); + + if( p_oid_info->buf_len >= sizeof(uint64_t) ) + { + *((uint64_t*)p_oid_info->p_buf) = stat; + *p_oid_info->p_bytes_used = sizeof(uint64_t); + } + else if( p_oid_info->buf_len >= sizeof(uint32_t) ) + { + *((uint32_t*)p_oid_info->p_buf) = (uint32_t)stat; + *p_oid_info->p_bytes_used = sizeof(uint32_t); + } + else + { + *p_oid_info->p_bytes_used = 0; + IPOIB_EXIT( IPOIB_DBG_STAT ); + return NDIS_STATUS_INVALID_LENGTH; + } + + IPOIB_EXIT( IPOIB_DBG_STAT ); + return NDIS_STATUS_SUCCESS; +} + + +void +ipoib_inc_send_stat( + IN ipoib_adapter_t* const p_adapter, + IN const ip_stat_sel_t stat_sel, + IN const size_t bytes OPTIONAL ) +{ + IPOIB_ENTER( IPOIB_DBG_STAT ); + + cl_spinlock_acquire( &p_adapter->send_stat_lock ); + switch( stat_sel ) + { + case IP_STAT_ERROR: + p_adapter->send_stats.comp.error++; + break; + + case IP_STAT_DROPPED: + p_adapter->send_stats.comp.dropped++; + break; + + case IP_STAT_UCAST_BYTES: + case IP_STAT_UCAST_FRAMES: + p_adapter->send_stats.comp.success++; + p_adapter->send_stats.ucast.frames++; + p_adapter->send_stats.ucast.bytes += bytes; + break; + + case IP_STAT_BCAST_BYTES: + case IP_STAT_BCAST_FRAMES: + p_adapter->send_stats.comp.success++; + p_adapter->send_stats.bcast.frames++; + p_adapter->send_stats.bcast.bytes += bytes; + break; + + case IP_STAT_MCAST_BYTES: + case IP_STAT_MCAST_FRAMES: + p_adapter->send_stats.comp.success++; + p_adapter->send_stats.mcast.frames++; + p_adapter->send_stats.mcast.bytes += bytes; + break; + + default: + break; + } + cl_spinlock_release( &p_adapter->send_stat_lock ); + + IPOIB_EXIT( IPOIB_DBG_STAT ); +} diff --git a/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_adapter.h b/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_adapter.h index 2254f399..0d3c106b 100644 --- a/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_adapter.h +++ b/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_adapter.h @@ -372,7 +372,6 @@ typedef struct _net_address_item ib_api_status_t ipoib_create_adapter( - IN NDIS_HANDLE wrapper_config_context, IN void* const h_adapter, OUT ipoib_adapter_t** const pp_adapter ); diff --git a/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_driver.c b/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_driver.c deleted file mode 100644 index 0bc3ebd5..00000000 --- a/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_driver.c +++ /dev/null @@ -1,4708 +0,0 @@ -/* - * Copyright (c) 2005 SilverStorm Technologies. All rights reserved. - * Copyright (c) 2006 Mellanox Technologies. All rights reserved. - * Portions Copyright (c) 2008 Microsoft 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: ipoib_driver.c 4506 2009-06-23 14:40:54Z xalex $ - */ - -#include "limits.h" -#include "ipoib_driver.h" -#include "ipoib_debug.h" - -#if defined(EVENT_TRACING) -#ifdef offsetof -#undef offsetof -#endif -#include "ipoib_driver.tmh" -#endif - -#include "ipoib_port.h" -#include "ipoib_ibat.h" -#include -#include -#include -#include -#include "ntstrsafe.h" -#include "strsafe.h" -#include - - - -#define MAJOR_DRIVER_VERSION 2 -#define MINOR_DRIVER_VERSION 1 -#if defined(NDIS60_MINIPORT) -#define MAJOR_NDIS_VERSION 6 -#define MINOR_NDIS_VERSION 0 - -#else -#error NDIS Version not defined, try defining NDIS60_MINIPORT -#endif - -PDRIVER_OBJECT g_p_drv_obj; - - -#if 0 -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_NETWORK_LAYER_ADDRESSES, - 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_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 -}; -#endif - -NDIS_OID NICSupportedOidsTest[] = -{ - 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_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_VENDOR_DRIVER_VERSION, - OID_GEN_CURRENT_PACKET_FILTER, - OID_GEN_CURRENT_LOOKAHEAD, - OID_GEN_DRIVER_VERSION, - OID_GEN_MAXIMUM_TOTAL_SIZE, - OID_GEN_MAC_OPTIONS, - OID_GEN_MAXIMUM_SEND_PACKETS, - OID_GEN_XMIT_OK, - OID_GEN_RCV_OK, - OID_GEN_XMIT_ERROR, - OID_GEN_RCV_ERROR, - OID_GEN_RCV_NO_BUFFER, - OID_GEN_RCV_CRC_ERROR, - OID_GEN_TRANSMIT_QUEUE_LENGTH, - OID_802_3_PERMANENT_ADDRESS, - OID_802_3_CURRENT_ADDRESS, - OID_802_3_MULTICAST_LIST, - OID_802_3_MAXIMUM_LIST_SIZE, - OID_802_3_RCV_ERROR_ALIGNMENT, - OID_802_3_XMIT_ONE_COLLISION, - OID_802_3_XMIT_MORE_COLLISIONS, - OID_802_3_XMIT_DEFERRED, - OID_802_3_XMIT_MAX_COLLISIONS, - OID_802_3_RCV_OVERRUN, - OID_802_3_XMIT_UNDERRUN, - OID_802_3_XMIT_HEARTBEAT_FAILURE, - OID_802_3_XMIT_TIMES_CRS_LOST, - OID_802_3_XMIT_LATE_COLLISIONS, - -#if !BUILD_W2K - OID_GEN_PHYSICAL_MEDIUM, -#endif - - OID_TCP_TASK_OFFLOAD, - -/* powermanagement */ - - OID_PNP_CAPABILITIES, - OID_PNP_SET_POWER, - OID_PNP_QUERY_POWER, - OID_PNP_ADD_WAKE_UP_PATTERN, - OID_PNP_REMOVE_WAKE_UP_PATTERN, - OID_PNP_ENABLE_WAKE_UP, - - -/* custom oid WMI support */ -// OID_CUSTOM_PERF_COUNTERS, - // OID_CUSTOM_STRING, - - OID_GEN_RECEIVE_SCALE_CAPABILITIES, - OID_GEN_RECEIVE_SCALE_PARAMETERS, - -// -// new and required for NDIS 6 miniports -// - OID_GEN_LINK_PARAMETERS, - OID_GEN_INTERRUPT_MODERATION, - OID_GEN_STATISTICS, - -/* Offload */ - OID_TCP_OFFLOAD_CURRENT_CONFIG, - OID_TCP_OFFLOAD_PARAMETERS, - OID_TCP_OFFLOAD_HARDWARE_CAPABILITIES, - OID_OFFLOAD_ENCAPSULATION, - -/* Header - Data seperation */ - // OID_GEN_HD_SPLIT_PARAMETERS, - // OID_GEN_HD_SPLIT_CURRENT_CONFIG, - -/* VLAN */ - // OID_ADD_VALN_ID, - // OID_DELETE_VLAN_ID, - -/* Set MAC */ - // OID_SET_MAC_ADDRESS - -}; - -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_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_VENDOR_DRIVER_VERSION, - OID_GEN_CURRENT_PACKET_FILTER, - OID_GEN_CURRENT_LOOKAHEAD, - OID_GEN_DRIVER_VERSION, - OID_GEN_MAXIMUM_TOTAL_SIZE, - OID_GEN_MAC_OPTIONS, - OID_GEN_MAXIMUM_SEND_PACKETS, - OID_GEN_XMIT_OK, - OID_GEN_RCV_OK, - OID_GEN_XMIT_ERROR, - OID_GEN_RCV_ERROR, - OID_GEN_RCV_NO_BUFFER, - OID_GEN_RCV_CRC_ERROR, - OID_GEN_TRANSMIT_QUEUE_LENGTH, - OID_802_3_PERMANENT_ADDRESS, - OID_802_3_CURRENT_ADDRESS, - OID_802_3_MULTICAST_LIST, - OID_802_3_MAXIMUM_LIST_SIZE, - OID_802_3_RCV_ERROR_ALIGNMENT, - OID_802_3_XMIT_ONE_COLLISION, - OID_802_3_XMIT_MORE_COLLISIONS, - OID_802_3_XMIT_DEFERRED, - OID_802_3_XMIT_MAX_COLLISIONS, - OID_802_3_RCV_OVERRUN, - OID_802_3_XMIT_UNDERRUN, - OID_802_3_XMIT_HEARTBEAT_FAILURE, - OID_802_3_XMIT_TIMES_CRS_LOST, - OID_802_3_XMIT_LATE_COLLISIONS, - -#if !BUILD_W2K - OID_GEN_PHYSICAL_MEDIUM, -#endif - - OID_TCP_TASK_OFFLOAD, - -/* powermanagement */ - - OID_PNP_CAPABILITIES, - OID_PNP_SET_POWER, - OID_PNP_QUERY_POWER, - OID_PNP_ADD_WAKE_UP_PATTERN, - OID_PNP_REMOVE_WAKE_UP_PATTERN, - OID_PNP_ENABLE_WAKE_UP, - -#if 0 -/* custom oid WMI support */ - OID_CUSTOM_PERF_COUNTERS, - OID_CUSTOM_STRING, -#endif - - OID_GEN_RECEIVE_SCALE_CAPABILITIES, - OID_GEN_RECEIVE_SCALE_PARAMETERS, - - -// -// new and required for NDIS 6 miniports -// - OID_GEN_LINK_PARAMETERS, - OID_GEN_INTERRUPT_MODERATION, - OID_GEN_STATISTICS, - -/* Offload */ - OID_TCP_OFFLOAD_CURRENT_CONFIG, - OID_TCP_OFFLOAD_PARAMETERS, - OID_TCP_OFFLOAD_HARDWARE_CAPABILITIES, - OID_OFFLOAD_ENCAPSULATION, - -#if 0 - -/* Header - Data seperation */ - OID_GEN_HD_SPLIT_PARAMETERS, - OID_GEN_HD_SPLIT_CURRENT_CONFIG, - -/* VLAN */ - OID_ADD_VALN_ID, - OID_DELETE_VLAN_ID, - - -/* Set MAC */ - OID_SET_MAC_ADDRESS -#endif - -}; - -static const unsigned char VENDOR_ID[] = {0x00, 0x06, 0x6A, 0x00}; - -#define VENDOR_DESCRIPTION "Internet Protocol over InfiniBand" - -#define IB_INFINITE_SERVICE_LEASE 0xFFFFFFFF - -//The mask is 8 bit and can't contain more than 6 non-zero bits -#define MAX_GUID_MAX 0xFC - - -/* Global driver debug level */ -uint32_t g_ipoib_dbg_level = TRACE_LEVEL_ERROR; -uint32_t g_ipoib_dbg_flags = 0x00000fff; -ipoib_globals_t g_ipoib = {0}; -NDIS_HANDLE g_IpoibMiniportDriverHandle = NULL; -NDIS_HANDLE g_IpoibDriverContext = NULL; - - - -typedef struct _IPOIB_REG_ENTRY -{ - NDIS_STRING RegName; // variable name text - BOOLEAN bRequired; // 1 -> required, 0 -> optional - UINT FieldOffset; // offset in parent struct - UINT FieldSize; // size (in bytes) of the field - UINT Default; // default value to use - UINT Min; // minimum value allowed - UINT Max; // maximum value allowed -} IPOIB_REG_ENTRY, *PIPOIB_REG_ENTRY; - -IPOIB_REG_ENTRY HCARegTable[] = { - // reg value name If Required Offset in parentr struct Field size Default Min Max - {NDIS_STRING_CONST("GUIDMask"), 0, IPOIB_OFFSET(guid_mask), IPOIB_SIZE(guid_mask), 0, 0, MAX_GUID_MAX}, - /* GUIDMask should be the first element */ - {NDIS_STRING_CONST("RqDepth"), 1, IPOIB_OFFSET(rq_depth), IPOIB_SIZE(rq_depth), 512, 128, 1024}, - {NDIS_STRING_CONST("RqLowWatermark"), 0, IPOIB_OFFSET(rq_low_watermark), IPOIB_SIZE(rq_low_watermark), 4, 2, 8}, - {NDIS_STRING_CONST("SqDepth"), 1, IPOIB_OFFSET(sq_depth), IPOIB_SIZE(sq_depth), 512, 128, 1024}, - {NDIS_STRING_CONST("SendChksum"), 1, IPOIB_OFFSET(send_chksum_offload), IPOIB_SIZE(send_chksum_offload),CSUM_ENABLED,CSUM_DISABLED,CSUM_BYPASS}, - {NDIS_STRING_CONST("RecvChksum"), 1, IPOIB_OFFSET(recv_chksum_offload), IPOIB_SIZE(recv_chksum_offload),CSUM_ENABLED,CSUM_DISABLED,CSUM_BYPASS}, - {NDIS_STRING_CONST("SaTimeout"), 1, IPOIB_OFFSET(sa_timeout), IPOIB_SIZE(sa_timeout), 1000, 250, UINT_MAX}, - {NDIS_STRING_CONST("SaRetries"), 1, IPOIB_OFFSET(sa_retry_cnt), IPOIB_SIZE(sa_retry_cnt), 10, 1, UINT_MAX}, - {NDIS_STRING_CONST("RecvRatio"), 1, IPOIB_OFFSET(recv_pool_ratio), IPOIB_SIZE(recv_pool_ratio), 1, 1, 10}, - {NDIS_STRING_CONST("PayloadMtu"), 1, IPOIB_OFFSET(payload_mtu), IPOIB_SIZE(payload_mtu), 2044, 512, MAX_UD_PAYLOAD_MTU}, - {NDIS_STRING_CONST("lso"), 0, IPOIB_OFFSET(lso), IPOIB_SIZE(lso), 0, 0, 1}, - {NDIS_STRING_CONST("MCLeaveRescan"), 1, IPOIB_OFFSET(mc_leave_rescan), IPOIB_SIZE(mc_leave_rescan), 260, 1, 3600}, - {NDIS_STRING_CONST("BCJoinRetry"), 1, IPOIB_OFFSET(bc_join_retry), IPOIB_SIZE(bc_join_retry), 50, 0, 1000}, - {NDIS_STRING_CONST("CmEnabled"), 0, IPOIB_OFFSET(cm_enabled), IPOIB_SIZE(cm_enabled), FALSE, FALSE, TRUE}, - {NDIS_STRING_CONST("CmPayloadMtu"), 1, IPOIB_OFFSET(cm_payload_mtu), IPOIB_SIZE(cm_payload_mtu), MAX_CM_PAYLOAD_MTU, 512, MAX_CM_PAYLOAD_MTU} - -}; - -#define IPOIB_NUM_REG_PARAMS (sizeof (HCARegTable) / sizeof(IPOIB_REG_ENTRY)) - - -void -ipoib_create_log( - NDIS_HANDLE h_adapter, - UINT ind, - ULONG eventLogMsgId) - -{ -#define cMaxStrLen 40 -#define cArrLen 3 - - PWCHAR logMsgArray[cArrLen]; - WCHAR strVal[cMaxStrLen]; - NDIS_STRING AdapterInstanceName; - - IPOIB_INIT_NDIS_STRING(&AdapterInstanceName); - if (NdisMQueryAdapterInstanceName(&AdapterInstanceName, h_adapter)!= NDIS_STATUS_SUCCESS ){ - ASSERT(FALSE); - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR,IPOIB_DBG_ERROR, ("[IPoIB] Init:Failed to retreive adapter name.\n")); - return; - } - logMsgArray[0] = AdapterInstanceName.Buffer; - - if (RtlStringCbPrintfW(strVal, sizeof(strVal), L"0x%x", HCARegTable[ind].Default) != STATUS_SUCCESS) { - ASSERT(FALSE); - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR,IPOIB_DBG_ERROR, - ("[IPoIB] Init: Problem copying string value: exiting\n")); - return; - } - - logMsgArray[0] = AdapterInstanceName.Buffer; - logMsgArray[1] = HCARegTable[ind].RegName.Buffer; - logMsgArray[2] = strVal; - - NdisWriteEventLogEntry(g_p_drv_obj, eventLogMsgId, 0, cArrLen, &logMsgArray, 0, NULL); - -} - - - -NTSTATUS -DriverEntry( - IN PDRIVER_OBJECT p_drv_obj, - IN PUNICODE_STRING p_reg_path ); - -VOID -ipoib_unload( - IN PDRIVER_OBJECT p_drv_obj ); - -NDIS_STATUS -ipoib_initialize_ex( - IN NDIS_HANDLE h_adapter, - IN NDIS_HANDLE config_context, - IN PNDIS_MINIPORT_INIT_PARAMETERS MiniportInitParameters); - -NDIS_STATUS -MPInitializeTest( - IN NDIS_HANDLE MiniportAdapterHandle, - IN NDIS_HANDLE MiniportDriverContext, - IN PNDIS_MINIPORT_INIT_PARAMETERS MiniportInitParameters - ); - - - -BOOLEAN -ipoib_check_for_hang( - IN NDIS_HANDLE adapter_context ); - -void -ipoib_halt_ex( - IN NDIS_HANDLE adapter_context, - IN NDIS_HALT_ACTION HaltAction); - -NDIS_STATUS -ipoib_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 -ipoib_reset( - IN NDIS_HANDLE adapter_context, - OUT PBOOLEAN p_addr_reset); - -NDIS_STATUS -ipoib_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 ); - -//NDIS60 -void -ipoib_send_net_buffer_list( - IN NDIS_HANDLE adapter_context, - IN PNET_BUFFER_LIST net_buffer_list, - IN NDIS_PORT_NUMBER port_num, - IN ULONG send_flags); - -void -ipoib_pnp_notify( - IN NDIS_HANDLE adapter_context, - IN PNET_DEVICE_PNP_EVENT pnp_event); - -VOID -ipoib_shutdown_ex( - IN NDIS_HANDLE adapter_context, - IN NDIS_SHUTDOWN_ACTION shutdown_action); - - -void -ipoib_cancel_xmit( - IN NDIS_HANDLE adapter_context, - IN PVOID cancel_id ); - - -static void -ipoib_complete_query( - IN ipoib_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 -__ipoib_set_net_addr( - IN ipoib_adapter_t * p_adapter, - IN PVOID info_buf, - IN ULONG info_buf_len, - OUT PULONG p_bytes_read, - OUT PULONG p_bytes_needed ); - -static NDIS_STATUS -__ipoib_get_tcp_task_offload( - IN ipoib_adapter_t* p_adapter, - OUT pending_oid_t *pNdisRequest); - -static void -__ipoib_ats_reg_cb( - IN ib_reg_svc_rec_t *p_reg_svc_rec ); - -static void -__ipoib_ats_dereg_cb( - IN void *context ); - -static NTSTATUS -__ipoib_read_registry( - IN UNICODE_STRING* const p_registry_path ); - -static NDIS_STATUS -ipoib_set_options( - IN NDIS_HANDLE NdisMiniportDriverHandle, - IN NDIS_HANDLE MiniportDriverContext); - -static NDIS_STATUS -ipoib_oid_handler( - IN NDIS_HANDLE adapter_context, - IN PNDIS_OID_REQUEST pNdisRequest); - -static void -ipoib_cancel_oid_request( - IN NDIS_HANDLE adapter_context, - IN PVOID requestId); - -static NDIS_STATUS -ipoib_pause( - IN NDIS_HANDLE adapter_context, - IN PNDIS_MINIPORT_PAUSE_PARAMETERS pause_parameters); - -static NDIS_STATUS -ipoib_restart( - IN NDIS_HANDLE adapter_context, - IN PNDIS_MINIPORT_RESTART_PARAMETERS restart_parameters); - - - -//! Standard Windows Device Driver Entry Point -/*! DriverEntry is the first routine called after a driver is loaded, and -is responsible for initializing the driver. On W2k this occurs when the PnP -Manager matched a PnP ID to one in an INF file that references this driver. -Any not success return value will cause the driver to fail to load. -IRQL = PASSIVE_LEVEL - -@param p_drv_obj Pointer to Driver Object for this device driver -@param 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 -*/ -NTSTATUS -DriverEntry( - IN PDRIVER_OBJECT p_drv_obj, - IN PUNICODE_STRING p_registry_path ) -{ - NDIS_STATUS status; - NDIS_MINIPORT_DRIVER_CHARACTERISTICS characteristics; - - IPOIB_ENTER( IPOIB_DBG_INIT ); - g_p_drv_obj = p_drv_obj; - -#ifdef _DEBUG_ - PAGED_CODE(); -#endif -#if defined(EVENT_TRACING) - WPP_INIT_TRACING(p_drv_obj, p_registry_path); -#endif - status = CL_INIT; - if( !NT_SUCCESS( status ) ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("cl_init failed.\n") ); - return status; - } - - __ipoib_read_registry(p_registry_path); - - KeInitializeSpinLock( &g_ipoib.lock ); - cl_qlist_init( &g_ipoib.adapter_list ); - - NdisZeroMemory(&characteristics, sizeof(characteristics)); - - characteristics.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_DRIVER_CHARACTERISTICS, - characteristics.Header.Size = sizeof(NDIS_MINIPORT_DRIVER_CHARACTERISTICS); - characteristics.Header.Revision = NDIS_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_1; - - characteristics.MajorNdisVersion = MAJOR_NDIS_VERSION; - characteristics.MinorNdisVersion = MINOR_NDIS_VERSION; - characteristics.MajorDriverVersion = MAJOR_DRIVER_VERSION; - characteristics.MinorDriverVersion = MINOR_DRIVER_VERSION; - - - characteristics.CheckForHangHandlerEx = ipoib_check_for_hang; - characteristics.HaltHandlerEx = ipoib_halt_ex; - characteristics.InitializeHandlerEx = ipoib_initialize_ex;// MPInitializeTest - characteristics.OidRequestHandler = ipoib_oid_handler; - characteristics.CancelOidRequestHandler = ipoib_cancel_oid_request; - characteristics.ResetHandlerEx = ipoib_reset; - characteristics.DevicePnPEventNotifyHandler = ipoib_pnp_notify; - characteristics.ReturnNetBufferListsHandler = ipoib_return_net_buffer_list; - characteristics.SendNetBufferListsHandler = ipoib_send_net_buffer_list; - - characteristics.SetOptionsHandler = ipoib_set_options; - characteristics.PauseHandler = ipoib_pause; - characteristics.RestartHandler = ipoib_restart; - characteristics.UnloadHandler = ipoib_unload; - characteristics.CancelSendHandler = ipoib_cancel_xmit; - characteristics.ShutdownHandlerEx = ipoib_shutdown_ex; - - - -//TODO NDIS60 set g_ prefix to global variables - status = NdisMRegisterMiniportDriver( - p_drv_obj, p_registry_path,(PNDIS_HANDLE)&g_IpoibDriverContext, &characteristics,&g_IpoibMiniportDriverHandle ); - if( status != NDIS_STATUS_SUCCESS ) - { - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("NdisMRegisterMiniportDriver failed with status of %d\n", status) ); - CL_DEINIT; - } - - IPOIB_EXIT( IPOIB_DBG_INIT ); - return status; -} - -static NDIS_STATUS -ipoib_set_options( - IN NDIS_HANDLE NdisMiniportDriverHandle, - IN NDIS_HANDLE MiniportDriverContext - ) -{ - IPOIB_ENTER( IPOIB_DBG_INIT ); - - UNREFERENCED_PARAMETER(NdisMiniportDriverHandle); - UNREFERENCED_PARAMETER(MiniportDriverContext); - - IPOIB_EXIT( IPOIB_DBG_INIT ); - return NDIS_STATUS_SUCCESS; -} - -static NTSTATUS -__ipoib_read_registry( - IN UNICODE_STRING* const p_registry_path ) -{ - NTSTATUS status; - /* Remember the terminating entry in the table below. */ - RTL_QUERY_REGISTRY_TABLE table[4]; - UNICODE_STRING param_path; - - IPOIB_ENTER( IPOIB_DBG_INIT ); - 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 ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed to allocate parameters path buffer.\n") ); - return STATUS_INSUFFICIENT_RESOURCES; - } - - RtlAppendUnicodeStringToString( ¶m_path, p_registry_path ); - RtlAppendUnicodeToString( ¶m_path, L"\\Parameters" ); - - /* - * 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; - table[0].Name = L"DebugLevel"; - table[0].EntryContext = &g_ipoib_dbg_level; - table[0].DefaultType = REG_DWORD; - table[0].DefaultData = &g_ipoib_dbg_level; - table[0].DefaultLength = sizeof(ULONG); - - table[1].Flags = RTL_QUERY_REGISTRY_DIRECT; - table[1].Name = L"DebugFlags"; - table[1].EntryContext = &g_ipoib_dbg_flags; - table[1].DefaultType = REG_DWORD; - table[1].DefaultData = &g_ipoib_dbg_flags; - table[1].DefaultLength = sizeof(ULONG); - - table[2].Flags = RTL_QUERY_REGISTRY_DIRECT; - table[2].Name = L"bypass_check_bcast_rate"; - table[2].EntryContext = &g_ipoib.bypass_check_bcast_rate; - table[2].DefaultType = REG_DWORD; - table[2].DefaultData = &g_ipoib.bypass_check_bcast_rate; - table[2].DefaultLength = sizeof(ULONG); - - /* Have at it! */ - status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE, - param_path.Buffer, table, NULL, NULL ); - - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("debug level %d debug flags 0x%.8x\n", - g_ipoib_dbg_level, - g_ipoib_dbg_flags)); - -#if DBG - if( g_ipoib_dbg_flags & IPOIB_DBG_ERR ) - g_ipoib_dbg_flags |= CL_DBG_ERROR; -#endif - - cl_free( param_path.Buffer ); - IPOIB_EXIT( IPOIB_DBG_INIT ); - return status; -} - - -VOID -ipoib_unload( - IN PDRIVER_OBJECT p_drv_obj ) -{ - IPOIB_ENTER( IPOIB_DBG_INIT ); - UNREFERENCED_PARAMETER(p_drv_obj); - #if defined(EVENT_TRACING) - WPP_CLEANUP(p_drv_obj); - #endif - //NDIS6.0 - NdisMDeregisterMiniportDriver(g_IpoibMiniportDriverHandle); - UNREFERENCED_PARAMETER( p_drv_obj ); - CL_DEINIT; - IPOIB_EXIT( IPOIB_DBG_INIT ); -} - - - -NDIS_STATUS -ipoib_get_adapter_params( - IN NDIS_HANDLE* const wrapper_config_context, - IN OUT ipoib_adapter_t *p_adapter, - OUT PUCHAR *p_mac, - OUT UINT *p_len) -{ - NDIS_STATUS status; - NDIS_HANDLE h_config; - NDIS_CONFIGURATION_OBJECT config_obj; - NDIS_CONFIGURATION_PARAMETER *p_param; - UINT value; - PIPOIB_REG_ENTRY pRegEntry; - UINT i; - PUCHAR structPointer; - - int sq_depth_step = 128; - - UNUSED_PARAM(wrapper_config_context); - IPOIB_ENTER( IPOIB_DBG_INIT ); - - config_obj.Header.Type = NDIS_OBJECT_TYPE_CONFIGURATION_OBJECT; - config_obj.Header.Revision = NDIS_CONFIGURATION_OBJECT_REVISION_1; - config_obj.Header.Size = sizeof(NDIS_CONFIGURATION_OBJECT); - config_obj.NdisHandle = p_adapter->h_adapter; - config_obj.Flags = 0; - - status = NdisOpenConfigurationEx( &config_obj, &h_config); - if( status != NDIS_STATUS_SUCCESS ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("NdisOpenConfigurationEx returned 0x%.8x\n", status) ); - return status; - } - - // read all the registry values - for (i = 0, pRegEntry = HCARegTable; i < IPOIB_NUM_REG_PARAMS; ++i) - { - // initialize pointer to appropriate place inside 'params' - structPointer = (PUCHAR) &p_adapter->params + pRegEntry[i].FieldOffset; - - // Get the configuration value for a specific parameter. Under NT the - // parameters are all read in as DWORDs. - NdisReadConfiguration( - &status, - &p_param, - h_config, - &pRegEntry[i].RegName, - NdisParameterInteger); - - // If the parameter was present, then check its value for validity. - if (status == NDIS_STATUS_SUCCESS) - { - // Check that param value is not too small or too large - if (p_param->ParameterData.IntegerData < pRegEntry[i].Min || - p_param->ParameterData.IntegerData > pRegEntry[i].Max) - { - value = pRegEntry[i].Default; - ipoib_create_log(p_adapter->h_adapter, i, EVENT_IPOIB_WRONG_PARAMETER_WRN); - IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_INIT, ("Read configuration.Registry %S value is out of range, setting default value= 0x%x\n", pRegEntry[i].RegName.Buffer, value)); - - } - else - { - value = p_param->ParameterData.IntegerData; - IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_INIT, ("Read configuration. Registry %S, Value= 0x%x\n", pRegEntry[i].RegName.Buffer, value)); - } - } - - else - { - value = pRegEntry[i].Default; - status = NDIS_STATUS_SUCCESS; - if (pRegEntry[i].bRequired) - { - ipoib_create_log(p_adapter->h_adapter, i, EVENT_IPOIB_WRONG_PARAMETER_ERR); - IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_INIT, ("Read configuration.Registry %S value not found, setting default value= 0x%x\n", pRegEntry[i].RegName.Buffer, value)); - } - else - { - ipoib_create_log(p_adapter->h_adapter, i, EVENT_IPOIB_WRONG_PARAMETER_INFO); - IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_INIT, ("Read configuration. Registry %S value not found, Value= 0x%x\n", pRegEntry[i].RegName.Buffer, value)); - } - - } - // - // Store the value in the adapter structure. - // - switch(pRegEntry[i].FieldSize) - { - case 1: - *((PUCHAR) structPointer) = (UCHAR) value; - break; - - case 2: - *((PUSHORT) structPointer) = (USHORT) value; - break; - - case 4: - *((PULONG) structPointer) = (ULONG) value; - break; - - default: - IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, ("Bogus field size %d\n", pRegEntry[i].FieldSize)); - break; - } - } - - // Send queue depth needs to be a power of two - //static const INT sq_depth_step = 128; - - if (p_adapter->params.sq_depth % sq_depth_step) { - static const c_sq_ind = 2; - p_adapter->params.sq_depth = sq_depth_step *( - p_adapter->params.sq_depth / sq_depth_step + !!( (p_adapter->params.sq_depth % sq_depth_step) > (sq_depth_step/2) )); - ipoib_create_log(p_adapter->h_adapter, c_sq_ind, EVENT_IPOIB_WRONG_PARAMETER_WRN); - IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_INIT, ("SQ DEPTH value was rounded to the closest acceptable value of 0x%x\n", p_adapter->params.sq_depth )); - - } - - - // Adjusting the low watermark parameter - p_adapter->params.rq_low_watermark = - p_adapter->params.rq_depth / p_adapter->params.rq_low_watermark; - - /* disable CM if LSO is active */ - if( p_adapter->params.cm_enabled ) - { - p_adapter->params.cm_enabled = !p_adapter->params.lso; - if( !p_adapter->params.cm_enabled ) - { - NdisWriteErrorLogEntry( p_adapter->h_adapter, - EVENT_IPOIB_CONNECTED_MODE_ERR, 1, 0xbadc0de0 ); - } - } - - if( p_adapter->params.cm_enabled ) - { - p_adapter->params.cm_xfer_block_size = - (sizeof(eth_hdr_t) + p_adapter->params.cm_payload_mtu); - } - - p_adapter->params.xfer_block_size = - (sizeof(eth_hdr_t) + p_adapter->params.payload_mtu); - - NdisReadNetworkAddress( &status, p_mac, p_len, h_config ); - - NdisCloseConfiguration( h_config ); - - IPOIB_EXIT( IPOIB_DBG_INIT ); - return NDIS_STATUS_SUCCESS; -} - - -NDIS_STATUS -ipoib_get_adapter_guids( - IN NDIS_HANDLE* const h_adapter, - IN OUT ipoib_adapter_t *p_adapter ) -{ - NTSTATUS status; - ib_al_ifc_data_t data; - IO_STACK_LOCATION io_stack, *p_fwd_io_stack; - DEVICE_OBJECT *p_pdo; - IRP *p_irp; - KEVENT event; - IO_STATUS_BLOCK io_status; - - IPOIB_ENTER( IPOIB_DBG_INIT ); - - NdisMGetDeviceProperty( h_adapter, &p_pdo, NULL, NULL, NULL, NULL ); - - /* Query for our interface */ - data.size = sizeof(ipoib_ifc_data_t); - data.version = IPOIB_INTERFACE_DATA_VERSION; - data.type = &GUID_IPOIB_INTERFACE_DATA; - data.p_data = &p_adapter->guids; - - 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->p_ifc; - io_stack.Parameters.QueryInterface.InterfaceSpecificData = &data; - io_stack.Parameters.QueryInterface.InterfaceType = - &GUID_IB_AL_INTERFACE; - - KeInitializeEvent( &event, NotificationEvent, FALSE ); - - /* Build the IRP for the HCA. */ - p_irp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP, p_pdo, - NULL, 0, NULL, &event, &io_status ); - if( !p_irp ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed to allocate query interface IRP.\n") ); - return STATUS_INSUFFICIENT_RESOURCES; - } - - /* Copy the request query parameters. */ - p_fwd_io_stack = IoGetNextIrpStackLocation( p_irp ); - p_fwd_io_stack->MinorFunction = IRP_MN_QUERY_INTERFACE; - p_fwd_io_stack->Parameters.QueryInterface = - io_stack.Parameters.QueryInterface; - p_irp->IoStatus.Status = STATUS_NOT_SUPPORTED; - - /* Send the IRP. */ - status = IoCallDriver( p_pdo, p_irp ); - if( status == STATUS_PENDING ) - { - KeWaitForSingleObject( &event, Executive, KernelMode, - FALSE, NULL ); - status = io_status.Status; - } - - if( !NT_SUCCESS( status ) ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Query interface for IPOIB 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. - */ - if (p_adapter->p_ifc) - p_adapter->p_ifc->wdm.InterfaceDereference( - p_adapter->p_ifc->wdm.Context ); - IPOIB_EXIT( IPOIB_DBG_INIT ); - return NDIS_STATUS_SUCCESS; -} - - -//! 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_adapter 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 -*/ - -/*void foo1(int i) -{ - char temp[5200]; - if (i ==0) return; - cl_msg_out("i = %d\n", i); - foo1(i-1); - -}*/ - -NDIS_STATUS -SetDeviceRegistrationAttributes( - ipoib_adapter_t *p_adapter, - NDIS_HANDLE h_adapter - ) -{ - NDIS_MINIPORT_ADD_DEVICE_REGISTRATION_ATTRIBUTES atr; - NTSTATUS Status; - - NdisZeroMemory(&atr, sizeof(NDIS_MINIPORT_ADD_DEVICE_REGISTRATION_ATTRIBUTES)); - - // - // setting registration attributes - // - atr.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADD_DEVICE_REGISTRATION_ATTRIBUTES; - atr.Header.Revision = NDIS_MINIPORT_ADD_DEVICE_REGISTRATION_ATTRIBUTES_REVISION_1; - atr.Header.Size = NDIS_SIZEOF_MINIPORT_ADD_DEVICE_REGISTRATION_ATTRIBUTES_REVISION_1; - - - atr.MiniportAddDeviceContext = (NDIS_HANDLE)p_adapter; - atr.Flags = 0; - - Status = NdisMSetMiniportAttributes(h_adapter, - (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&atr); - - return Status; -} - -//NDIS 6.1 -#if 0 -NDIS_STATUS -SetHardwareAssistAttributes( - ipoib_adapter_t *p_adapter, - NDIS_HANDLE h_adapter - ) -{ - NDIS_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES atr; - NTSTATUS Status; - - NdisZeroMemory(&atr, sizeof(NDIS_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES)); - - // - // setting registration attributes - // - atr.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES; - atr.Header.Revision = NDIS_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES_REVISION_1; - atr.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES_REVISION_1; - - NDIS_HD_SPLIT_ATTRIBUTES nhsa; - NdisZeroMemory(&nhsa, sizeof(nhsa)); - - nhsa.Header.Type = NDIS_OBJECT_TYPE_HD_SPLIT_ATTRIBUTES; - nhsa.Header.Revision = NDIS_OFFLOAD_REVISION_1; - nhsa.Header.Size = NDIS_SIZEOF_HD_SPLIT_ATTRIBUTES_REVISION_1; - - // BUGBUG: We are just cheating here ... - nhsa.HardwareCapabilities = NDIS_HD_SPLIT_CAPS_SUPPORTS_HEADER_DATA_SPLIT; -#if 0 - ... Only supported on B0 - - NDIS_HD_SPLIT_CAPS_SUPPORTS_IPV4_OPTIONS | - NDIS_HD_SPLIT_CAPS_SUPPORTS_IPV6_EXTENSION_HEADERS | - NDIS_HD_SPLIT_CAPS_SUPPORTS_TCP_OPTIONS; -#endif - - // The bellow should be left zero - if (pPort->Config.HeaderDataSplit) { - nhsa.CurrentCapabilities = NDIS_HD_SPLIT_CAPS_SUPPORTS_HEADER_DATA_SPLIT; - } else { - nhsa.CurrentCapabilities = 0; - } - - nhsa.HDSplitFlags = 0; - nhsa.BackfillSize = 0; - nhsa.MaxHeaderSize = 0; - - atr.HDSplitAttributes = &nhsa; - - Status = NdisMSetMiniportAttributes(h_adapter, - (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&atr); - - if (nhsa.HDSplitFlags & NDIS_HD_SPLIT_ENABLE_HEADER_DATA_SPLIT) { - ASSERT(pPort->Config.HeaderDataSplit == TRUE); - pPort->Config.HeaderDataSplit = TRUE; - } - else { - ASSERT(pPort->Config.HeaderDataSplit == FALSE); - pPort->Config.HeaderDataSplit = FALSE; - } - - return Status; -} -#endif - -/*++ -Routine Description: - the routine sets attributes that are associated with a miniport adapter. - -Arguments: - pPort - Pointer to port object - -Return Value: - NDIS_STATUS - -Note: - Should be called in PASSIVE_LEVEL - ---*/ -NDIS_STATUS -SetAdapterRegistrationAttributes( - ipoib_adapter_t *p_adapter, - NDIS_HANDLE h_adapter - ) - { - NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES atr; - NTSTATUS Status; - - NdisZeroMemory(&atr, sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES)); - - /* setting registration attributes */ - - atr.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES; - atr.Header.Revision = NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1; - atr.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1; - //TODO NDIS60 Port or adapter - atr.MiniportAdapterContext = (NDIS_HANDLE)p_adapter; //(NDIS_HANDLE)pPort->p_adapter; - atr.AttributeFlags = NDIS_MINIPORT_ATTRIBUTES_BUS_MASTER; - atr.CheckForHangTimeInSeconds = 10; - atr.InterfaceType = NdisInterfacePci ; // ???? UH - //TODO NDIS60 PNP or PCI ? - //RegistrationAttributes.InterfaceType = NdisInterfacePNPBus; - - Status = NdisMSetMiniportAttributes(h_adapter, - (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&atr); - - return Status; -} - - -/*++ -Routine Description: - the routine sets generic attributes that are associated with a miniport - adapter. - -Arguments: - pPort - Pointer to port object - -Return Value: - NDIS_STATUS - -Note: - Should be called in PASSIVE_LEVEL - ---*/ -NDIS_STATUS -SetGenericAttributes( - ipoib_adapter_t *p_adapter, - NDIS_HANDLE h_adapter - ) -{ - NDIS_STATUS Status; - - NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES gat; - NdisZeroMemory(&gat, sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES)); - - /* set up generic attributes */ - - gat.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES; - gat.Header.Revision = NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1; - gat.Header.Size = sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES); - - gat.MediaType = NdisMedium802_3; - gat.MaxXmitLinkSpeed = IPOIB_MEDIA_MAX_SPEED; - gat.MaxRcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED; - gat.XmitLinkSpeed = IPOIB_MEDIA_MAX_SPEED; //TODO NDIS60 NDIS_LINK_SPEED_UNKNOWN - gat.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED; // TODO NDIS60 NDIS_LINK_SPEED_UNKNOWN ??? - - gat.MediaConnectState = MediaConnectStateConnected; //TODO NDIS60 Check the current state - gat.MediaDuplexState = MediaDuplexStateFull; - - gat.MtuSize = MAX_IB_MTU; - gat.LookaheadSize = MAX_XFER_BLOCK_SIZE; - gat.MacOptions = 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; //TODO NDIS60 - // DT: Enable for Header Data Split WHQL - // | NDIS_MAC_OPTION_8021Q_VLAN; - - gat.SupportedPacketFilters = NDIS_PACKET_TYPE_DIRECTED | - NDIS_PACKET_TYPE_MULTICAST | - //NDIS_PACKET_TYPE_ALL_MULTICAST | - NDIS_PACKET_TYPE_BROADCAST; - - gat.MaxMulticastListSize = MAX_MCAST; - - gat.MacAddressLength = HW_ADDR_LEN; - - NdisMoveMemory(gat.PermanentMacAddress, - p_adapter->mac.addr, - HW_ADDR_LEN); - - NdisMoveMemory(gat.CurrentMacAddress, - p_adapter->params.conf_mac.addr, - HW_ADDR_LEN); - - - gat.PhysicalMediumType = NdisPhysicalMedium802_3; - gat.AccessType = NET_IF_ACCESS_BROADCAST; - - gat.SupportedOidList = (PNDIS_OID)SUPPORTED_OIDS; - gat.SupportedOidListLength = sizeof(SUPPORTED_OIDS); - - - gat.DirectionType = NET_IF_DIRECTION_SENDRECEIVE; - gat.ConnectionType = NET_IF_CONNECTION_DEDICATED; - gat.IfType = IF_TYPE_ETHERNET_CSMACD; - gat.IfConnectorPresent = TRUE; - //TODO NDIS60 This value is absent for ETH driver - gat.AccessType = NET_IF_ACCESS_BROADCAST; // NET_IF_ACCESS_BROADCAST for a typical ethernet adapter - - - //TODO NDIS60 is it possible to reduce unsupported statistics - gat.SupportedStatistics = - NDIS_STATISTICS_XMIT_OK_SUPPORTED | - NDIS_STATISTICS_RCV_OK_SUPPORTED | - NDIS_STATISTICS_XMIT_ERROR_SUPPORTED | - NDIS_STATISTICS_RCV_ERROR_SUPPORTED | - NDIS_STATISTICS_RCV_CRC_ERROR_SUPPORTED | - NDIS_STATISTICS_RCV_NO_BUFFER_SUPPORTED | - NDIS_STATISTICS_TRANSMIT_QUEUE_LENGTH_SUPPORTED; - - //SupportedStatistics = NDIS_STATISTICS_XMIT_OK_SUPPORTED | - // NDIS_STATISTICS_GEN_STATISTICS_SUPPORTED; - - - // - // Set power management capabilities - // - gat.PowerManagementCapabilities = NULL; -#if 0 - NDIS_PNP_CAPABILITIES PowerManagementCapabilities; - NdisZeroMemory(&PowerManagementCapabilities, sizeof(NDIS_PNP_CAPABILITIES)); - if (MPIsPoMgmtSupported(pPort)) - { - MPFillPoMgmtCaps(pPort, &PowerManagementCapabilities, &Status, &unUsed); - ASSERT(NT_SUCCESS(Status)); - gat.PowerManagementCapabilities = &PowerManagementCapabilities; - } - else - { - - } -#endif - - // - // Set RSS attributes - // - gat.RecvScaleCapabilities = NULL; -#if 0 - NDIS_RECEIVE_SCALE_CAPABILITIES RssCapabilities; - NdisZeroMemory(&RssCapabilities, sizeof(PNDIS_RECEIVE_SCALE_CAPABILITIES)); - Status = MPFillRssCapabilities(pPort, &RssCapabilities, &unUsed); - if (NT_SUCCESS(Status)) - { - gat.RecvScaleCapabilities = &RssCapabilities; - } - else - { - // - // do not fail the call because of failure to get PM caps - // - Status = NDIS_STATUS_SUCCESS; - gat.RecvScaleCapabilities = NULL; - } -#endif - - Status = NdisMSetMiniportAttributes(h_adapter, - (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&gat); - - return Status; -} - - -/*++ -Routine Description: - The routine sets an NDIS_OFFLOAD structure indicates the current offload - capabilities that are provided by the miniport adapter - -Arguments: - pPort - a pointer to port object - offload - reference to NDIS_OFFLOAD object that should be filled - -Return Value: - None. - ---*/ -static -void -OffloadConfig( - ipoib_adapter_t *p_adapter, - NDIS_OFFLOAD *p_offload - ) -{ - - ULONG ulEncapsulation = NDIS_ENCAPSULATION_IEEE_802_3 | NDIS_ENCAPSULATION_IEEE_802_3_P_AND_Q; - - NdisZeroMemory(p_offload, NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_1); - - p_offload->Header.Type = NDIS_OBJECT_TYPE_OFFLOAD; - p_offload->Header.Revision = NDIS_OFFLOAD_REVISION_1; // BUGBUG: do we need to support revision 2? UH 17-May-2008 - p_offload->Header.Size = NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_1; - - p_offload->Checksum.IPv4Transmit.Encapsulation = ulEncapsulation; - p_offload->Checksum.IPv4Transmit.IpOptionsSupported = - p_offload->Checksum.IPv4Transmit.TcpOptionsSupported = - p_offload->Checksum.IPv4Transmit.TcpChecksum = - p_offload->Checksum.IPv4Transmit.UdpChecksum = - p_offload->Checksum.IPv4Transmit.IpChecksum =!!(p_adapter->params.send_chksum_offload); - - p_offload->Checksum.IPv4Receive.Encapsulation = ulEncapsulation; - p_offload->Checksum.IPv4Receive.IpOptionsSupported = - p_offload->Checksum.IPv4Receive.TcpOptionsSupported = - p_offload->Checksum.IPv4Receive.TcpChecksum = - p_offload->Checksum.IPv4Receive.UdpChecksum = - p_offload->Checksum.IPv4Receive.IpChecksum = !!(p_adapter->params.recv_chksum_offload); //TODO NDIS60 - - - p_offload->Checksum.IPv6Transmit.Encapsulation = ulEncapsulation; - p_offload->Checksum.IPv6Transmit.IpExtensionHeadersSupported = - p_offload->Checksum.IPv6Transmit.TcpOptionsSupported = - p_offload->Checksum.IPv6Transmit.TcpChecksum = - p_offload->Checksum.IPv6Transmit.UdpChecksum = FALSE; - - - p_offload->Checksum.IPv6Receive.Encapsulation = ulEncapsulation; - p_offload->Checksum.IPv6Receive.IpExtensionHeadersSupported = - p_offload->Checksum.IPv6Receive.TcpOptionsSupported = - p_offload->Checksum.IPv6Receive.TcpChecksum = - p_offload->Checksum.IPv6Receive.UdpChecksum = FALSE; - - if (p_adapter->params.lso) - { - p_offload->LsoV1.IPv4.Encapsulation = ulEncapsulation; - p_offload->LsoV1.IPv4.MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE; -#define LSO_MIN_SEG_COUNT 2 - p_offload->LsoV1.IPv4.MinSegmentCount = LSO_MIN_SEG_COUNT; - - - p_offload->LsoV1.IPv4.TcpOptions = NDIS_OFFLOAD_SUPPORTED; - p_offload->LsoV1.IPv4.IpOptions = NDIS_OFFLOAD_SUPPORTED; - - p_offload->LsoV2.IPv4.Encapsulation = ulEncapsulation; - p_offload->LsoV2.IPv4.MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE; - p_offload->LsoV2.IPv4.MinSegmentCount = LSO_MIN_SEG_COUNT; - - p_offload->LsoV2.IPv6.Encapsulation = ulEncapsulation; - p_offload->LsoV2.IPv6.MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE; - p_offload->LsoV2.IPv6.MinSegmentCount = LSO_MIN_SEG_COUNT; - - p_offload->LsoV2.IPv6.IpExtensionHeadersSupported = NDIS_OFFLOAD_NOT_SUPPORTED; - p_offload->LsoV2.IPv6.TcpOptionsSupported = NDIS_OFFLOAD_SUPPORTED; - } - -} - - -/*++ -Routine Description: - The routine sets an NDIS_OFFLOAD structure that indicates all the task - offload capabilites that are supported by the NIC. These capabilities include - capabilities that are currently disabled by standardized keywords in the registry. - -Arguments: - offload - reference to NDIS_OFFLOAD object that should be filled - -Return Value: - None. - ---*/ -static -void -OffloadCapabilities( - NDIS_OFFLOAD *p_offload - ) -{ - ULONG ulEncapsulation = NDIS_ENCAPSULATION_IEEE_802_3 | NDIS_ENCAPSULATION_IEEE_802_3_P_AND_Q ; - NdisZeroMemory(p_offload, NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_1); - - p_offload->Header.Type = NDIS_OBJECT_TYPE_OFFLOAD; - p_offload->Header.Revision = NDIS_OFFLOAD_REVISION_1; // BUGBUG: do we need to support revision 2? UH 17-May-2008 - p_offload->Header.Size = NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_1; - - p_offload->Checksum.IPv4Transmit.Encapsulation = ulEncapsulation; - p_offload->Checksum.IPv4Transmit.IpOptionsSupported = TRUE; - p_offload->Checksum.IPv4Transmit.TcpOptionsSupported = TRUE; - p_offload->Checksum.IPv4Transmit.TcpChecksum = TRUE; - p_offload->Checksum.IPv4Transmit.UdpChecksum = TRUE; - p_offload->Checksum.IPv4Transmit.IpChecksum = TRUE; - - p_offload->Checksum.IPv4Receive.Encapsulation = ulEncapsulation; - p_offload->Checksum.IPv4Receive.IpOptionsSupported = TRUE; - p_offload->Checksum.IPv4Receive.TcpOptionsSupported = TRUE; - p_offload->Checksum.IPv4Receive.TcpChecksum = TRUE; - p_offload->Checksum.IPv4Receive.UdpChecksum = TRUE; - p_offload->Checksum.IPv4Receive.IpChecksum = TRUE; - - - // - // BUGBUG:: - // During a HW bug that didn't handle correctly packets with - // IPv6 Extension Headers -> we set IpExtensionHeadersSupported to TRUE - // - p_offload->Checksum.IPv6Transmit.Encapsulation = ulEncapsulation; - p_offload->Checksum.IPv6Transmit.IpExtensionHeadersSupported = TRUE; - p_offload->Checksum.IPv6Transmit.TcpOptionsSupported = TRUE; - p_offload->Checksum.IPv6Transmit.TcpChecksum = TRUE; - p_offload->Checksum.IPv6Transmit.UdpChecksum = TRUE; - - - p_offload->Checksum.IPv6Receive.Encapsulation = ulEncapsulation; - p_offload->Checksum.IPv6Receive.IpExtensionHeadersSupported = TRUE; - p_offload->Checksum.IPv6Receive.TcpOptionsSupported = TRUE; - p_offload->Checksum.IPv6Receive.TcpChecksum = TRUE; - p_offload->Checksum.IPv6Receive.UdpChecksum = TRUE; - - p_offload->LsoV1.IPv4.Encapsulation = ulEncapsulation; - p_offload->LsoV1.IPv4.MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE; - p_offload->LsoV1.IPv4.MinSegmentCount = 2; - p_offload->LsoV1.IPv4.TcpOptions = NDIS_OFFLOAD_SUPPORTED; - p_offload->LsoV1.IPv4.IpOptions = NDIS_OFFLOAD_SUPPORTED; - - p_offload->LsoV2.IPv4.Encapsulation = ulEncapsulation; - p_offload->LsoV2.IPv4.MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE; - p_offload->LsoV2.IPv4.MinSegmentCount = 2; - - p_offload->LsoV2.IPv6.Encapsulation = ulEncapsulation; - p_offload->LsoV2.IPv6.MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE; - p_offload->LsoV2.IPv6.MinSegmentCount = 2; - - p_offload->LsoV2.IPv6.IpExtensionHeadersSupported = NDIS_OFFLOAD_NOT_SUPPORTED; - p_offload->LsoV2.IPv6.TcpOptionsSupported = NDIS_OFFLOAD_SUPPORTED; - - } - - -/*++ -Routine Description: - The routine sets offload attributes that are associated with a miniport - adapter. - -Arguments: - pPort - Pointer to port object - -Return Value: - NDIS_STATUS - -Note: - Should be called in PASSIVE_LEVEL - ---*/ -NDIS_STATUS -SetOffloadAttributes( - ipoib_adapter_t *p_adapter, - NDIS_HANDLE h_adapter - ) -{ - NDIS_STATUS Status; - NDIS_OFFLOAD offload,hwOffload; - //ULONG ulEncapsulation = NDIS_ENCAPSULATION_IEEE_802_3 | NDIS_ENCAPSULATION_IEEE_802_3_P_AND_Q; - - NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES oat; - NdisZeroMemory(&oat, sizeof(NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES)); - - oat.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES; - oat.Header.Revision = NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES_REVISION_1; - oat.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES_REVISION_1; - - - OffloadConfig(p_adapter, &offload); - - - OffloadCapabilities(&hwOffload); - - oat.DefaultOffloadConfiguration = &offload; - oat.HardwareOffloadCapabilities = &hwOffload; - - Status = NdisMSetMiniportAttributes(h_adapter, - (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&oat); - - return Status; -} - - -/*++ - -Routine Description: - An NDIS 6.0 miniport driver must call NdisMSetMiniportAttributes - at least twice. The first call is to register itself with NDIS. - The second call is to register the miniport driver's general - attributes with NDIS. - - NdisMSetMiniportAttributes takes a parameter of type - NDIS_MINIPORT_ADAPTER_ATTRIBUTES, which is a union of several miniport - adapter attributes. Miniport drivers must first call - NdisMSetMiniportAttributes and pass in an - NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES structure - that contains the pointer to its own context area, attribute flags, - check-for-hang time, and interface type. - - All NDIS 6.0 miniport drivers are deserialized by default. - -Arguments: - pPort - Pointer to port object - -Return Value: - NDIS_STATUS - -Note: - Should be called in PASSIVE_LEVEL - ---*/ - NDIS_STATUS - SetAttributes( - ipoib_adapter_t *p_adapter, - NDIS_HANDLE h_adapter - ) - { - NTSTATUS Status; - - - Status = SetDeviceRegistrationAttributes(p_adapter, h_adapter); - if (Status != NDIS_STATUS_SUCCESS) - { - //ETH_PRINT(TRACE_LEVEL_ERROR, ETH_INIT, "Set device registration failed Error=0x%x\n", Status); - return Status; - } - - - Status = SetAdapterRegistrationAttributes(p_adapter, h_adapter); - if (Status != NDIS_STATUS_SUCCESS) - { - //ETH_PRINT(TRACE_LEVEL_ERROR, ETH_INIT, "Set adapter attributes failed Error=0x%x\n", Status); - return Status; - } - - Status = SetOffloadAttributes(p_adapter, h_adapter); - if (Status != NDIS_STATUS_SUCCESS) - { - //ETH_PRINT(TRACE_LEVEL_ERROR, ETH_INIT, "Set OFFLOAD attributes failed Error=0x%x\n", Status); - return Status; - } - -#if 0 - if(!pPort->Config.fWHQL) - { - Status = SetHardwareAssistAttributes(pPort); - if (Status != NDIS_STATUS_SUCCESS) - { - //ETH_PRINT(TRACE_LEVEL_ERROR, ETH_INIT, "Set Hardware Assist Attributes failed Error=0x%x\n", Status); - return Status; - } - } -#endif - - Status = SetGenericAttributes(p_adapter, h_adapter); - if (Status != NDIS_STATUS_SUCCESS) - { - //ETH_PRINT(TRACE_LEVEL_ERROR, ETH_INIT, "Set generic attributes failed Error=0x%x\n", Status); - return Status; - } - - return Status; -} - - - -NDIS_STATUS -InitNdisScatterGatherDma( - ipoib_adapter_t *p_adapter, - NDIS_HANDLE h_adapter - ) -{ - NDIS_STATUS status; - NDIS_SG_DMA_DESCRIPTION DmaDescription; - - NdisZeroMemory(&DmaDescription, sizeof(DmaDescription)); - - DmaDescription.Header.Type = NDIS_OBJECT_TYPE_SG_DMA_DESCRIPTION; - DmaDescription.Header.Revision = NDIS_SG_DMA_DESCRIPTION_REVISION_1; - DmaDescription.Header.Size = sizeof(NDIS_SG_DMA_DESCRIPTION); - DmaDescription.Flags = NDIS_SG_DMA_64_BIT_ADDRESS; - // - // Even if offload is enabled, the packet size for mapping shouldn't change - // - DmaDescription.MaximumPhysicalMapping = LARGE_SEND_OFFLOAD_SIZE + LSO_MAX_HEADER; - - DmaDescription.ProcessSGListHandler = ipoib_process_sg_list; - DmaDescription.SharedMemAllocateCompleteHandler = NULL; - - DmaDescription.Header.Type = NDIS_OBJECT_TYPE_SG_DMA_DESCRIPTION; - DmaDescription.Header.Revision = NDIS_SG_DMA_DESCRIPTION_REVISION_1; - DmaDescription.Header.Size = sizeof(NDIS_SG_DMA_DESCRIPTION);//NDIS_SIZEOF_SG_DMA_DESCRIPTION_REVISION_1; - - DmaDescription.Flags = NDIS_SG_DMA_64_BIT_ADDRESS; - //DmaDescription.MaximumPhysicalMapping = pPort->p_adapter->params.xfer_block_size; - - DmaDescription.ProcessSGListHandler = ipoib_process_sg_list; - DmaDescription.SharedMemAllocateCompleteHandler = NULL; - - status = NdisMRegisterScatterGatherDma( - h_adapter, - &DmaDescription, - &p_adapter->NdisMiniportDmaHandle); - - if( status != NDIS_STATUS_SUCCESS ) - { - //TODO NDIS60 - //ipoib_destroy_adapter( p_adapter ); - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("NdisMRegisterScatterGatherDma returned 0x%.8x.\n", status) ); - - } - //NDIS sets this value before it returns from NdisMRegisterScatterGatherDma. - //Miniport drivers should use this size to preallocate memory for each scatter/gather list. - p_adapter->sg_list_size = DmaDescription.ScatterGatherListSize ; - - return status; -} - - -NDIS_STATUS -MPInitializeTest( - IN NDIS_HANDLE MiniportAdapterHandle, - IN NDIS_HANDLE MiniportDriverContext, - IN PNDIS_MINIPORT_INIT_PARAMETERS MiniportInitParameters - ) -/*++ -Routine Description: - - MiniportInitialize handler - -Arguments: - - MiniportAdapterHandle The handle NDIS uses to refer to us - MiniportDriverContext Handle passed to NDIS when we registered the driver - MiniportInitParameters Initialization parameters - -Return Value: - - NDIS_STATUS_SUCCESS unless something goes wrong - ---*/ -{ - - NDIS_STATUS Status = NDIS_STATUS_SUCCESS; - //PMP_PORT pPort = NULL; - ipoib_adapter_t *p_adapter; -// NDIS_MINIPORT_INTERRUPT_CHARACTERISTICS Interrupt; - NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES RegistrationAttributes; - NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES GeneralAttributes; - //NDIS_TIMER_CHARACTERISTICS Timer; - NDIS_PNP_CAPABILITIES PowerManagementCapabilities; - //PMP_ADAPTER Adapter = NULL; - //PVOID NetworkAddress; -// UINT index; -// UINT uiPnpCommandValue; -// ULONG ulInfoLen; - //ULONG InterruptVersion; -// LARGE_INTEGER liDueTime; - //BOOLEAN isTimerAlreadyInQueue = FALSE; -// uint8_t portId; - ib_api_status_t ib_status; -#if 0 -#if DBG - LARGE_INTEGER TS, TD, TE; -#endif -#endif - - cl_dbg_out ("====> MPInitialize\n"); - - UNREFERENCED_PARAMETER(MiniportDriverContext); - UNREFERENCED_PARAMETER(MiniportInitParameters); - - - - - - { - - ib_status = ipoib_create_adapter(MiniportDriverContext, MiniportAdapterHandle, &p_adapter ); - if( ib_status != IB_SUCCESS ) - { - ASSERT(FALSE); - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ipoib_create_adapter returned status %d.\n", ib_status ) ); - return NDIS_STATUS_FAILURE; - } - - - - NdisZeroMemory(&RegistrationAttributes, sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES)); - NdisZeroMemory(&GeneralAttributes, sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES)); - - // - // setting registration attributes - // - RegistrationAttributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES; - RegistrationAttributes.Header.Revision = NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1; - RegistrationAttributes.Header.Size = sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES); - - RegistrationAttributes.MiniportAdapterContext = (NDIS_HANDLE)p_adapter; - RegistrationAttributes.AttributeFlags = NDIS_MINIPORT_ATTRIBUTES_HARDWARE_DEVICE | - NDIS_MINIPORT_ATTRIBUTES_BUS_MASTER; - - RegistrationAttributes.CheckForHangTimeInSeconds = 2; - RegistrationAttributes.InterfaceType = NdisInterfacePci; - - Status = NdisMSetMiniportAttributes(MiniportAdapterHandle, - (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&RegistrationAttributes); - - if (Status != NDIS_STATUS_SUCCESS) - { - //break; - return Status; - } - -#if 0 - // - // Read the registry parameters - // - Status = NICReadRegParameters(Adapter); - - if (Status != NDIS_STATUS_SUCCESS) - { - break; - } - - - // - // Find the physical adapter - // - Status = MpFindAdapter(Adapter, MiniportInitParameters->AllocatedResources); - if (Status != NDIS_STATUS_SUCCESS) - { - break; - } - - // - // Map bus-relative IO range to system IO space - // - Status = NdisMRegisterIoPortRange( - (PVOID *)&Adapter->PortOffset, - Adapter->AdapterHandle, - Adapter->IoBaseAddress, - Adapter->IoRange); - if (Status != NDIS_STATUS_SUCCESS) - { - DBGPRINT(MP_ERROR, ("NdisMRegisterioPortRange failed\n")); - - NdisWriteErrorLogEntry( - Adapter->AdapterHandle, - NDIS_ERROR_CODE_BAD_IO_BASE_ADDRESS, - 0); - - break; - } - - // - // Read additional info from NIC such as MAC address - // - Status = NICReadAdapterInfo(Adapter); - if (Status != NDIS_STATUS_SUCCESS) - { - break; - } - -#endif - // - // set up generic attributes - // - - - GeneralAttributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES; - GeneralAttributes.Header.Revision = NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1; - GeneralAttributes.Header.Size = sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES); - - GeneralAttributes.MediaType = NdisMedium802_3; - - GeneralAttributes.MtuSize = DEFAULT_MTU; -#define LINE_SPEED_10_GBTS 10000000000 - GeneralAttributes.MaxXmitLinkSpeed = LINE_SPEED_10_GBTS; - GeneralAttributes.MaxRcvLinkSpeed = LINE_SPEED_10_GBTS; - GeneralAttributes.XmitLinkSpeed = NDIS_LINK_SPEED_UNKNOWN; - GeneralAttributes.RcvLinkSpeed = NDIS_LINK_SPEED_UNKNOWN; - GeneralAttributes.MediaConnectState = MediaConnectStateUnknown; - GeneralAttributes.MediaDuplexState = MediaDuplexStateUnknown; - GeneralAttributes.LookaheadSize = MAX_XFER_BLOCK_SIZE; -#if 0 - MPFillPoMgmtCaps (Adapter, - &PowerManagementCapabilities, - &Status, - &ulInfoLen); -#endif - NdisZeroMemory(&PowerManagementCapabilities, sizeof(NDIS_PNP_CAPABILITIES)); - Status = NDIS_STATUS_NOT_SUPPORTED; - // ulInfoLen = 0; - - if (Status == NDIS_STATUS_SUCCESS) - { - GeneralAttributes.PowerManagementCapabilities = &PowerManagementCapabilities; - } - else - { - GeneralAttributes.PowerManagementCapabilities = NULL; - } - - // - // do not fail the call because of failure to get PM caps - // - Status = NDIS_STATUS_SUCCESS; - - GeneralAttributes.MacOptions = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | - NDIS_MAC_OPTION_TRANSFERS_NOT_PEND | - NDIS_MAC_OPTION_NO_LOOPBACK; - - GeneralAttributes.SupportedPacketFilters = NDIS_PACKET_TYPE_DIRECTED | - NDIS_PACKET_TYPE_MULTICAST | - NDIS_PACKET_TYPE_ALL_MULTICAST | - NDIS_PACKET_TYPE_BROADCAST; - - GeneralAttributes.MaxMulticastListSize = MAX_MCAST; - GeneralAttributes.MacAddressLength = HW_ADDR_LEN; - NdisMoveMemory(GeneralAttributes.PermanentMacAddress, - p_adapter->mac.addr, - HW_ADDR_LEN); - - NdisMoveMemory(GeneralAttributes.CurrentMacAddress, - p_adapter->params.conf_mac.addr, - HW_ADDR_LEN); - GeneralAttributes.RecvScaleCapabilities = NULL; - GeneralAttributes.AccessType = NET_IF_ACCESS_BROADCAST; // NET_IF_ACCESS_BROADCAST for a typical ethernet adapter - GeneralAttributes.DirectionType = NET_IF_DIRECTION_SENDRECEIVE; // NET_IF_DIRECTION_SENDRECEIVE for a typical ethernet adapter - GeneralAttributes.ConnectionType = NET_IF_CONNECTION_DEDICATED; // NET_IF_CONNECTION_DEDICATED for a typical ethernet adapter - GeneralAttributes.IfType = IF_TYPE_ETHERNET_CSMACD; // IF_TYPE_ETHERNET_CSMACD for a typical ethernet adapter (regardless of speed) - GeneralAttributes.IfConnectorPresent = TRUE; // RFC 2665 TRUE if physical adapter - - GeneralAttributes.SupportedStatistics = NDIS_STATISTICS_XMIT_OK_SUPPORTED | - NDIS_STATISTICS_RCV_OK_SUPPORTED | - NDIS_STATISTICS_XMIT_ERROR_SUPPORTED | - NDIS_STATISTICS_RCV_ERROR_SUPPORTED | - NDIS_STATISTICS_RCV_CRC_ERROR_SUPPORTED | - NDIS_STATISTICS_RCV_NO_BUFFER_SUPPORTED | - NDIS_STATISTICS_TRANSMIT_QUEUE_LENGTH_SUPPORTED | - NDIS_STATISTICS_GEN_STATISTICS_SUPPORTED; - - GeneralAttributes.SupportedOidList = NICSupportedOidsTest; - GeneralAttributes.SupportedOidListLength = sizeof(NICSupportedOidsTest); - - Status = NdisMSetMiniportAttributes(MiniportAdapterHandle, - (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&GeneralAttributes); - - -#if 0 - // - // Allocate all other memory blocks including shared memory - // - Status = NICAllocAdapterMemory(Adapter); - if (Status != NDIS_STATUS_SUCCESS) - { - break; - } - // - // Init send data structures - // - NICInitSend(Adapter); - - // - // Init receive data structures - // - Status = NICInitRecv(Adapter); - if (Status != NDIS_STATUS_SUCCESS) - { - break; - } - // - // Map bus-relative registers to virtual system-space - // - Status = NdisMMapIoSpace( - (PVOID *) &(Adapter->CSRAddress), - Adapter->AdapterHandle, - Adapter->MemPhysAddress, - NIC_MAP_IOSPACE_LENGTH); - if (Status != NDIS_STATUS_SUCCESS) - { - DBGPRINT(MP_ERROR, ("NdisMMapIoSpace failed\n")); - - NdisWriteErrorLogEntry( - Adapter->AdapterHandle, - NDIS_ERROR_CODE_RESOURCE_CONFLICT, - 1, - ERRLOG_MAP_IO_SPACE); - - break; - } - - DBGPRINT(MP_INFO, ("CSRAddress="PTR_FORMAT"\n", Adapter->CSRAddress)); - - // - // Disable interrupts here which is as soon as possible - // - NICDisableInterrupt(Adapter); -#endif - - // - // Register the interrupt - // - // - - // - // the embeded NDIS interrupt structure is already zero'ed out - // as part of the adapter structure - // - #if 0 - NdisZeroMemory(&Interrupt, sizeof(NDIS_MINIPORT_INTERRUPT_CHARACTERISTICS)); - - Interrupt.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_INTERRUPT; - Interrupt.Header.Revision = NDIS_MINIPORT_INTERRUPT_REVISION_1; - Interrupt.Header.Size = sizeof(NDIS_MINIPORT_INTERRUPT_CHARACTERISTICS); - - Interrupt.InterruptHandler = MPIsr; - Interrupt.InterruptDpcHandler = MPHandleInterrupt; - Interrupt.DisableInterruptHandler = NULL; - Interrupt.EnableInterruptHandler = NULL; - - - - Status = NdisMRegisterInterruptEx(Adapter->AdapterHandle, - Adapter, - &Interrupt, - &Adapter->NdisInterruptHandle - ); - - - if (Status != NDIS_STATUS_SUCCESS) - { - DBGPRINT(MP_ERROR, ("NdisMRegisterInterrupt failed\n")); - - NdisWriteErrorLogEntry( - Adapter->AdapterHandle, - NDIS_ERROR_CODE_INTERRUPT_CONNECT, - 0); - - break; - } - - // - // If the driver support MSI - // - Adapter->InterruptType = Interrupt.InterruptType; - - if (Adapter->InterruptType == NDIS_CONNECT_MESSAGE_BASED) - { - Adapter->MessageInfoTable = Interrupt.MessageInfoTable; - } - - // - // If the driver supports MSI, here it should what kind of interrupt is granted. If MSI is granted, - // the driver can check Adapter->MessageInfoTable to get MSI information - // - - - MP_SET_FLAG(Adapter, fMP_ADAPTER_INTERRUPT_IN_USE); - - // - // Test our adapter hardware - // - Status = NICSelfTest(Adapter); - if (Status != NDIS_STATUS_SUCCESS) - { - break; - } - - // - // Init the hardware and set up everything - // - Status = NICInitializeAdapter(Adapter); - if (Status != NDIS_STATUS_SUCCESS) - { - break; - } - - // - // initial state is paused - // - Adapter->AdapterState = NicPaused; - - // - // Set the link detection flag - // - MP_SET_FLAG(Adapter, fMP_ADAPTER_LINK_DETECTION); - - // - // Increment the reference count so halt handler will wait - // - MP_INC_REF(Adapter); - - // - // Enable the interrupt - // - NICEnableInterrupt(Adapter); - - - NdisZeroMemory(&Timer, sizeof(NDIS_TIMER_CHARACTERISTICS)); - - Timer.Header.Type = NDIS_OBJECT_TYPE_TIMER_CHARACTERISTICS; - Timer.Header.Revision = NDIS_TIMER_CHARACTERISTICS_REVISION_1; - Timer.Header.Size = sizeof(NDIS_TIMER_CHARACTERISTICS); - - Timer.AllocationTag = NIC_TAG; - Timer.TimerFunction = MpLinkDetectionDpc; - Timer.FunctionContext = Adapter; - - // - // Minimize init-time - // - Status = NdisAllocateTimerObject( - Adapter->AdapterHandle, - &Timer, - &Adapter->LinkDetectionTimerHandle); - - if (Status != NDIS_STATUS_SUCCESS) - { - break; - } - - liDueTime.QuadPart = NIC_LINK_DETECTION_DELAY; - isTimerAlreadyInQueue =NdisSetTimerObject(Adapter->LinkDetectionTimerHandle, liDueTime, 0, NULL); - ASSERT(!isTimerAlreadyInQueue); -#endif - } -#if 0 - if (Adapter && (Status != NDIS_STATUS_SUCCESS)) - { - // - // Undo everything if it failed - // - MP_DEC_REF(Adapter); - MpFreeAdapter(Adapter); - } - - DBGPRINT_S(Status, ("<==== MPInitialize, Status=%x\n", Status)); -#endif - /* Create the adapter adapter */ - ib_status = ipoib_start_adapter( p_adapter ); - if( ib_status != IB_SUCCESS ) - { - ASSERT(FALSE); - - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ipoib_start_adapter returned status %d.\n", ib_status ) ); - return NDIS_STATUS_FAILURE; - } - - ipoib_ref_ibat(); - return NDIS_STATUS_SUCCESS; -} - - - -NDIS_STATUS -ipoib_initialize_ex( - IN NDIS_HANDLE h_adapter, - IN NDIS_HANDLE config_context, - IN PNDIS_MINIPORT_INIT_PARAMETERS MiniportInitParameters) - { - NDIS_STATUS status; - ib_api_status_t ib_status; - ipoib_adapter_t *p_adapter; - //NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES RegistrationAttributes; - //NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES GeneralAttributes; -#if IPOIB_USE_DMA - //NDIS_SG_DMA_DESCRIPTION DmaDescription; -#endif - IPOIB_ENTER( IPOIB_DBG_INIT ); - -#ifdef _DEBUG_ - PAGED_CODE(); -#endif - - UNUSED_PARAM( config_context ); - UNUSED_PARAM( MiniportInitParameters ); - - //foo1(100); - /* Create the adapter adapter */ - ib_status = ipoib_create_adapter(config_context, h_adapter, &p_adapter ); - if( ib_status != IB_SUCCESS ) - { - ASSERT(FALSE); - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ipoib_create_adapter returned status %d.\n", ib_status ) ); - return NDIS_STATUS_FAILURE; - } - p_adapter->ipoib_state = IPOIB_PAUSED; - status = SetAttributes(p_adapter, h_adapter); - if (status != NDIS_STATUS_SUCCESS) { - ASSERT(FALSE); - } -#if 0 - NdisZeroMemory(&RegistrationAttributes, sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES)); - NdisZeroMemory(&GeneralAttributes, sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES)); - - /* setting registration attributes */ - RegistrationAttributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES; - RegistrationAttributes.Header.Revision = NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1; - RegistrationAttributes.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1; - - RegistrationAttributes.MiniportAdapterContext = (NDIS_HANDLE)p_adapter; - RegistrationAttributes.AttributeFlags = NDIS_MINIPORT_ATTRIBUTES_BUS_MASTER; - - RegistrationAttributes.CheckForHangTimeInSeconds = 10; - RegistrationAttributes.InterfaceType = NdisInterfacePNPBus; - - status = NdisMSetMiniportAttributes(h_adapter, - (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&RegistrationAttributes); - - if (status != NDIS_STATUS_SUCCESS) - { - ipoib_destroy_adapter( p_adapter ); - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("NdisMSetMiniportAttributes returned 0x%.8x.\n", status) ); - return status; - } - - /* set up generic attributes */ - - GeneralAttributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES; - GeneralAttributes.Header.Revision = NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1; - GeneralAttributes.Header.Size = sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES); - - GeneralAttributes.MediaType = NdisMedium802_3; - //TODO - GeneralAttributes.MtuSize = MAX_IB_MTU; - GeneralAttributes.MaxXmitLinkSpeed = IPOIB_MEDIA_MAX_SPEED; - GeneralAttributes.MaxRcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED; - GeneralAttributes.XmitLinkSpeed = NDIS_LINK_SPEED_UNKNOWN; - GeneralAttributes.RcvLinkSpeed = NDIS_LINK_SPEED_UNKNOWN; - GeneralAttributes.MediaConnectState = MediaConnectStateUnknown; - GeneralAttributes.MediaDuplexState = MediaDuplexStateUnknown; - GeneralAttributes.LookaheadSize = MAX_XFER_BLOCK_SIZE; - - GeneralAttributes.PowerManagementCapabilities = NULL; - - GeneralAttributes.MacOptions = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | - NDIS_MAC_OPTION_TRANSFERS_NOT_PEND | - NDIS_MAC_OPTION_NO_LOOPBACK | - NDIS_MAC_OPTION_FULL_DUPLEX; - - GeneralAttributes.SupportedPacketFilters = NDIS_PACKET_TYPE_DIRECTED | - NDIS_PACKET_TYPE_MULTICAST | - NDIS_PACKET_TYPE_ALL_MULTICAST | - NDIS_PACKET_TYPE_BROADCAST; - - GeneralAttributes.MaxMulticastListSize = MAX_MCAST; - GeneralAttributes.MacAddressLength = HW_ADDR_LEN; - - NdisMoveMemory(GeneralAttributes.PermanentMacAddress, - p_adapter->mac.addr, - HW_ADDR_LEN); - - NdisMoveMemory(GeneralAttributes.CurrentMacAddress, - p_adapter->params.conf_mac.addr, - HW_ADDR_LEN); - - - GeneralAttributes.PhysicalMediumType = NdisPhysicalMediumUnspecified; - GeneralAttributes.RecvScaleCapabilities = NULL; - GeneralAttributes.AccessType = NET_IF_ACCESS_BROADCAST; // NET_IF_ACCESS_BROADCAST for a typical ethernet adapter - GeneralAttributes.DirectionType = NET_IF_DIRECTION_SENDRECEIVE; // NET_IF_DIRECTION_SENDRECEIVE for a typical ethernet adapter - GeneralAttributes.ConnectionType = NET_IF_CONNECTION_DEDICATED; // NET_IF_CONNECTION_DEDICATED for a typical ethernet adapter - GeneralAttributes.IfType = IF_TYPE_ETHERNET_CSMACD; // IF_TYPE_ETHERNET_CSMACD for a typical ethernet adapter (regardless of speed) - GeneralAttributes.IfConnectorPresent = TRUE; // RFC 2665 TRUE if physical adapter - - GeneralAttributes.SupportedStatistics = NDIS_STATISTICS_XMIT_OK_SUPPORTED | - NDIS_STATISTICS_RCV_OK_SUPPORTED | - NDIS_STATISTICS_XMIT_ERROR_SUPPORTED | - NDIS_STATISTICS_RCV_ERROR_SUPPORTED | - NDIS_STATISTICS_RCV_CRC_ERROR_SUPPORTED | - NDIS_STATISTICS_RCV_NO_BUFFER_SUPPORTED | - NDIS_STATISTICS_TRANSMIT_QUEUE_LENGTH_SUPPORTED | - NDIS_STATISTICS_GEN_STATISTICS_SUPPORTED; - - GeneralAttributes.SupportedOidList = (PNDIS_OID)SUPPORTED_OIDS; - GeneralAttributes.SupportedOidListLength = sizeof(SUPPORTED_OIDS); - - status = NdisMSetMiniportAttributes(h_adapter, - (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&GeneralAttributes); - - if (status != NDIS_STATUS_SUCCESS) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("NdisMSetMiniportAttributes returned 0x%.8x.\n", status) ); - } - -#if IPOIB_USE_DMA - - NdisZeroMemory(&DmaDescription, sizeof(DmaDescription)); - - DmaDescription.Header.Type = NDIS_OBJECT_TYPE_SG_DMA_DESCRIPTION; - DmaDescription.Header.Revision = NDIS_SG_DMA_DESCRIPTION_REVISION_1; - DmaDescription.Header.Size = sizeof(NDIS_SG_DMA_DESCRIPTION);//NDIS_SIZEOF_SG_DMA_DESCRIPTION_REVISION_1; - - DmaDescription.Flags = NDIS_SG_DMA_64_BIT_ADDRESS; - DmaDescription.MaximumPhysicalMapping = p_adapter->params.xfer_block_size; - - DmaDescription.ProcessSGListHandler = ipoib_process_sg_list; - DmaDescription.SharedMemAllocateCompleteHandler = NULL; - - status = NdisMRegisterScatterGatherDma( - p_adapter->h_adapter, - &DmaDescription, - &p_adapter->NdisMiniportDmaHandle); - - if( status != NDIS_STATUS_SUCCESS ) - { - ipoib_destroy_adapter( p_adapter ); - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("NdisMRegisterScatterGatherDma returned 0x%.8x.\n", status) ); - return status; - } - - - -#endif -#endif //if 0 - - - -#if IPOIB_USE_DMA - - InitNdisScatterGatherDma(p_adapter, h_adapter); - - - -#endif - /* Create the adapter adapter */ - ib_status = ipoib_start_adapter( p_adapter ); - if( ib_status != IB_SUCCESS ) - { - ASSERT(FALSE); - NdisWriteErrorLogEntry( h_adapter, - NDIS_ERROR_CODE_HARDWARE_FAILURE, 0 ); -#if IPOIB_USE_DMA - NdisMDeregisterScatterGatherDma(p_adapter->NdisMiniportDmaHandle); -#endif - ipoib_destroy_adapter( p_adapter ); - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ipoib_start_adapter returned status %d.\n", ib_status ) ); - return NDIS_STATUS_FAILURE; - } - - ipoib_ref_ibat(); - - IPOIB_EXIT( IPOIB_DBG_INIT ); - return status; - } - - -//! Deallocates resources when the NIC is removed and halts the NIC.. -//TODO: Dispatch or Passive ? -/* IRQL = DISPATCH_LEVEL - -@param adapter_context The adapter context allocated at start -*/ -void -ipoib_halt_ex( - IN NDIS_HANDLE adapter_context, - IN NDIS_HALT_ACTION HaltAction ) -{ - ipoib_adapter_t *p_adapter; - - IPOIB_ENTER( IPOIB_DBG_INIT ); - - UNUSED_PARAM(HaltAction); -//return; - ipoib_deref_ibat(); - - CL_ASSERT( adapter_context ); - p_adapter = (ipoib_adapter_t*)adapter_context; - - IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, - ("Port %016I64x (CA %016I64x port %d) halting\n", - p_adapter->guids.port_guid.guid, p_adapter->guids.ca_guid, - p_adapter->guids.port_num) ); - -#if IPOIB_USE_DMA - if (p_adapter->NdisMiniportDmaHandle != NULL) - { - NdisMDeregisterScatterGatherDma(p_adapter->NdisMiniportDmaHandle); - p_adapter->NdisMiniportDmaHandle = NULL; - } -#endif - ipoib_destroy_adapter( p_adapter ); - - IPOIB_EXIT( IPOIB_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 -ipoib_check_for_hang( - IN NDIS_HANDLE adapter_context ) -{ - ipoib_adapter_t *p_adapter; - - IPOIB_ENTER( IPOIB_DBG_INIT ); -//return FALSE; - CL_ASSERT( adapter_context ); - p_adapter = (ipoib_adapter_t*)adapter_context; - - if( p_adapter->reset ) - { - IPOIB_EXIT( IPOIB_DBG_INIT ); - return FALSE; - } - if (p_adapter->hung) { - ipoib_resume_oids(p_adapter); - } - - IPOIB_EXIT( IPOIB_DBG_INIT ); - return (p_adapter->hung? TRUE:FALSE); -} - - -/*++ -Routine Description: - The routine sets an NDIS_OFFLOAD structure indicates the current offload - capabilities that are provided by the miniport adapter - -Arguments: - pPort - a pointer to port object - offload - reference to NDIS_OFFLOAD object that should be filled - -Return Value: - None. - ---*/ -//TODO -#if 0 -static -void -__ipoib_get_offload_config( - ipoib_port_t *pPort, - NDIS_OFFLOAD *p_offload - ) -{ - NDIS_STATUS Status; - ULONG TxChksumOffload = ((MP_GET_PORT_CONFIG(pPort, TxChksumOffload) == TRUE) ? NDIS_OFFLOAD_SET_ON : NDIS_OFFLOAD_SET_OFF); - ULONG RxChksumOffload = ((MP_GET_PORT_CONFIG(pPort, RxChksumOffload) == TRUE) ? NDIS_OFFLOAD_SET_ON : NDIS_OFFLOAD_SET_OFF); - BOOLEAN fLargeSendOffload = MP_GET_PORT_CONFIG(pPort, LargeSendOffload); - ULONG ulEncapsulation = NDIS_ENCAPSULATION_IEEE_802_3 | NDIS_ENCAPSULATION_IEEE_802_3_P_AND_Q; - - NdisZeroMemory(&*p_offload, sizeof(NDIS_OFFLOAD)); - *p_offload.Header.Type = NDIS_OBJECT_TYPE_OFFLOAD; - *p_offload.Header.Revision = NDIS_OFFLOAD_REVISION_1; // BUGBUG: do we need to support revision 2? UH 17-May-2008 - *p_offload.Header.Size = NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_1; - - *p_offload.Checksum.IPv4Transmit.Encapsulation = ulEncapsulation; - *p_offload.Checksum.IPv4Transmit.IpOptionsSupported = TxChksumOffload; - *p_offload.Checksum.IPv4Transmit.TcpOptionsSupported = TxChksumOffload; - *p_offload.Checksum.IPv4Transmit.TcpChecksum = TxChksumOffload; - *p_offload.Checksum.IPv4Transmit.UdpChecksum = NDIS_OFFLOAD_NOT_SUPPORTED; - *p_offload.Checksum.IPv4Transmit.IpChecksum = TxChksumOffload; - - *p_offload.Checksum.IPv4Receive.Encapsulation = ulEncapsulation; - *p_offload.Checksum.IPv4Receive.IpOptionsSupported = RxChksumOffload; - *p_offload.Checksum.IPv4Receive.TcpOptionsSupported = RxChksumOffload; - *p_offload.Checksum.IPv4Receive.TcpChecksum = RxChksumOffload; - *p_offload.Checksum.IPv4Receive.UdpChecksum = NDIS_OFFLOAD_NOT_SUPPORTED; - *p_offload.Checksum.IPv4Receive.IpChecksum = RxChksumOffload; - - *p_offload.Checksum.IPv6Transmit.Encapsulation = ulEncapsulation; - *p_offload.Checksum.IPv6Transmit.IpExtensionHeadersSupported = TxChksumOffload; - *p_offload.Checksum.IPv6Transmit.TcpOptionsSupported = TxChksumOffload; - *p_offload.Checksum.IPv6Transmit.TcpChecksum = TxChksumOffload; - *p_offload.Checksum.IPv6Transmit.UdpChecksum = NDIS_OFFLOAD_NOT_SUPPORTED; - - - *p_offload.Checksum.IPv6Receive.Encapsulation = ulEncapsulation; - *p_offload.Checksum.IPv6Receive.IpExtensionHeadersSupported = RxChksumOffload; - *p_offload.Checksum.IPv6Receive.TcpOptionsSupported = RxChksumOffload; - *p_offload.Checksum.IPv6Receive.TcpChecksum = RxChksumOffload; - *p_offload.Checksum.IPv6Receive.UdpChecksum = NDIS_OFFLOAD_NOT_SUPPORTED; - - if (fLargeSendOffload) - { - *p_offload.LsoV1.IPv4.Encapsulation = ulEncapsulation; - *p_offload.LsoV1.IPv4.MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE; - *p_offload.LsoV1.IPv4.MinSegmentCount = 1; - *p_offload.LsoV1.IPv4.TcpOptions = NDIS_OFFLOAD_SUPPORTED; - *p_offload.LsoV1.IPv4.IpOptions = NDIS_OFFLOAD_SUPPORTED; - } -} -#endif - -//! 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 -ipoib_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 ) - { - ipoib_adapter_t *p_adapter; - NDIS_STATUS status; - USHORT version; - ULONG info; - PVOID src_buf; - ULONG buf_len; - pending_oid_t oid_info; - uint8_t port_num; - - IPOIB_ENTER( IPOIB_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 = (ipoib_adapter_t*)adapter_context; - - CL_ASSERT( p_bytes_written ); - CL_ASSERT( p_bytes_needed ); - CL_ASSERT( !p_adapter->pending_query ); - - status = NDIS_STATUS_SUCCESS; - src_buf = &info; - buf_len = sizeof(info); - - port_num = p_adapter->guids.port_num; - - switch( oid ) - { - /* Required General */ - case OID_GEN_SUPPORTED_LIST: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_GEN_SUPPORTED_LIST\n", port_num) ); - src_buf = (PVOID)SUPPORTED_OIDS; - buf_len = sizeof(SUPPORTED_OIDS); - break; - - case OID_GEN_HARDWARE_STATUS: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_GEN_HARDWARE_STATUS\n", port_num) ); - cl_obj_lock( &p_adapter->obj ); - switch( p_adapter->state ) - { - case IB_PNP_PORT_ADD: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d returning NdisHardwareStatusInitializing\n", port_num) ); - info = NdisHardwareStatusInitializing; - break; - - case IB_PNP_PORT_ACTIVE: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d returning NdisHardwareStatusReady\n", port_num) ); - info = NdisHardwareStatusReady; - break; - - default: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d returning NdisHardwareStatusNotReady\n", port_num) ); - info = NdisHardwareStatusNotReady; - } - cl_obj_unlock( &p_adapter->obj ); - break; - - case OID_GEN_MEDIA_SUPPORTED: - case OID_GEN_MEDIA_IN_USE: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_GEN_MEDIA_SUPPORTED " - "or OID_GEN_MEDIA_IN_USE\n", port_num) ); - info = NdisMedium802_3; - break; - - case OID_GEN_MAXIMUM_FRAME_SIZE: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_GEN_MAXIMUM_FRAME_SIZE\n", port_num) ); - if( p_adapter->params.cm_enabled ) - { - info = p_adapter->params.cm_payload_mtu; - } - else - { - info = p_adapter->params.payload_mtu; - } - break; - - case OID_GEN_LINK_SPEED: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_GEN_LINK_SPEED\n", port_num) ); - if (info_buf_len < buf_len) - { - break; - } - - cl_obj_lock( &p_adapter->obj ); - switch( p_adapter->state ) - { - case IB_PNP_PORT_ADD: - /* Mark the adapter as pending an OID */ - p_adapter->pending_query = TRUE; - - /* Save the request parameters. */ - p_adapter->query_oid = oid_info; - - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d returning NDIS_STATUS_PENDING\n", port_num) ); - status = NDIS_STATUS_PENDING; - break; - - case IB_PNP_PORT_REMOVE: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d returning NDIS_STATUS_NOT_ACCEPTED\n", port_num) ); - status = NDIS_STATUS_NOT_ACCEPTED; - break; - - default: - CL_ASSERT( p_adapter->p_port ); - info = p_adapter->port_rate; - break; - } - cl_obj_unlock( &p_adapter->obj ); - break; - - case OID_GEN_TRANSMIT_BUFFER_SPACE: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_GEN_TRANSMIT_BUFFER_SPACE\n", port_num) ); - if( p_adapter->params.cm_enabled ) - info = p_adapter->params.sq_depth * p_adapter->params.cm_xfer_block_size; - else - info = p_adapter->params.sq_depth * p_adapter->params.xfer_block_size; - break; - - case OID_GEN_RECEIVE_BUFFER_SPACE: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_GEN_TRANSMIT_BUFFER_SPACE " - "or OID_GEN_RECEIVE_BUFFER_SPACE\n", port_num) ); - if( p_adapter->params.cm_enabled ) - info = p_adapter->params.rq_depth * p_adapter->params.cm_xfer_block_size; - else - info = p_adapter->params.rq_depth * p_adapter->params.xfer_block_size; - break; - - case OID_GEN_MAXIMUM_LOOKAHEAD: - case OID_GEN_CURRENT_LOOKAHEAD: - case OID_GEN_TRANSMIT_BLOCK_SIZE: - case OID_GEN_RECEIVE_BLOCK_SIZE: - case OID_GEN_MAXIMUM_TOTAL_SIZE: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_GEN_MAXIMUM_LOOKAHEAD " - "or OID_GEN_CURRENT_LOOKAHEAD or " - "OID_GEN_TRANSMIT_BLOCK_SIZE or " - "OID_GEN_RECEIVE_BLOCK_SIZE or " - "OID_GEN_MAXIMUM_TOTAL_SIZE\n", port_num) ); - if( p_adapter->params.cm_enabled ) - info = p_adapter->params.cm_xfer_block_size; - else - info = p_adapter->params.xfer_block_size; - break; - - case OID_GEN_VENDOR_ID: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_GEN_VENDOR_ID\n", port_num) ); - src_buf = (void*)VENDOR_ID; - buf_len = sizeof(VENDOR_ID); - break; - - case OID_GEN_VENDOR_DESCRIPTION: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_GEN_VENDOR_DESCRIPTION\n", port_num) ); - src_buf = VENDOR_DESCRIPTION; - buf_len = sizeof(VENDOR_DESCRIPTION); - break; - - case OID_GEN_VENDOR_DRIVER_VERSION: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_GEN_VENDOR_DRIVER_VERSION\n", port_num) ); - src_buf = &version; - buf_len = sizeof(version); - //TODO: Figure out what the right version is. - version = 1 << 8 | 1; - break; - - case OID_GEN_PHYSICAL_MEDIUM: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_GEN_PHYSICAL_MEDIUM\n", port_num) ); - info = NdisPhysicalMediumUnspecified; - break; - - case OID_GEN_CURRENT_PACKET_FILTER: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_GEN_CURRENT_PACKET_FILTER\n", port_num) ); - info = p_adapter->packet_filter; - break; - - case OID_GEN_DRIVER_VERSION: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_GEN_DRIVER_VERSION\n", port_num) ); - src_buf = &version; - buf_len = sizeof(version); - version = MAJOR_NDIS_VERSION << 8 | MINOR_NDIS_VERSION; - break; - - case OID_GEN_MAC_OPTIONS: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_GEN_MAC_OPTIONS\n", port_num) ); - info = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | - NDIS_MAC_OPTION_TRANSFERS_NOT_PEND | - NDIS_MAC_OPTION_NO_LOOPBACK | - NDIS_MAC_OPTION_FULL_DUPLEX; - //TODO: Figure out if we will support priority and VLANs. - // NDIS_MAC_OPTION_8021P_PRIORITY; - //#ifdef NDIS51_MINIPORT - // info |= NDIS_MAC_OPTION_8021Q_VLAN; - //#endif - break; - - case OID_GEN_MEDIA_CONNECT_STATUS: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_GEN_MEDIA_CONNECT_STATUS\n", port_num) ); - cl_obj_lock( &p_adapter->obj ); - switch( p_adapter->state ) - { - case IB_PNP_PORT_ADD: - case IB_PNP_PORT_INIT: - /* - * Delay reporting media state until we know whether the port is - * either up or down. - */ - p_adapter->pending_query = TRUE; - p_adapter->query_oid = oid_info; - - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d returning NDIS_STATUS_PENDING\n", port_num) ); - status = NDIS_STATUS_PENDING; - break; - - case IB_PNP_PORT_ACTIVE: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d returning NdisMediaStateConnected\n", port_num) ); - info = NdisMediaStateConnected; - break; - - case IB_PNP_PORT_REMOVE: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d returning NDIS_STATUS_NOT_ACCEPTED\n", port_num) ); - status = NDIS_STATUS_NOT_ACCEPTED; - break; - - default: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d returning NdisMediaStateDisconnected\n", port_num) ); - info = NdisMediaStateDisconnected; - } - cl_obj_unlock( &p_adapter->obj ); - break; - - case OID_GEN_MAXIMUM_SEND_PACKETS: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_GEN_MAXIMUM_SEND_PACKETS\n", port_num) ); - info = MINIPORT_MAX_SEND_PACKETS; - break; - - /* Required General Statistics */ - case OID_GEN_STATISTICS: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_GEN_STATISTICS\n", port_num) ); - src_buf = NULL; - buf_len = sizeof(NDIS_STATISTICS_INFO); - if (info_buf_len < buf_len) - { - break; - } - status = ipoib_get_gen_stat(p_adapter, &oid_info ); - break; - - case OID_GEN_XMIT_OK: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_GEN_XMIT_OK\n", port_num) ); - src_buf = NULL; - status = ipoib_get_send_stat( p_adapter, IP_STAT_SUCCESS, &oid_info ); - break; - - case OID_GEN_RCV_OK: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_GEN_RCV_OK\n", port_num) ); - src_buf = NULL; - status = ipoib_get_recv_stat( p_adapter, IP_STAT_SUCCESS, &oid_info ); - break; - - case OID_GEN_XMIT_ERROR: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_GEN_XMIT_ERROR\n", port_num) ); - src_buf = NULL; - status = ipoib_get_send_stat( p_adapter, IP_STAT_ERROR, &oid_info ); - break; - - case OID_GEN_RCV_ERROR: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_GEN_RCV_ERROR\n", port_num) ); - src_buf = NULL; - status = ipoib_get_recv_stat( p_adapter, IP_STAT_ERROR, &oid_info ); - break; - - case OID_GEN_RCV_NO_BUFFER: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_GEN_RCV_NO_BUFFER\n", port_num) ); - src_buf = NULL; - status = ipoib_get_recv_stat( p_adapter, IP_STAT_DROPPED, &oid_info ); - break; - - case OID_GEN_DIRECTED_BYTES_XMIT: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_GEN_DIRECTED_BYTES_XMIT\n", port_num) ); - src_buf = NULL; - status = ipoib_get_send_stat( p_adapter, IP_STAT_UCAST_BYTES, &oid_info ); - break; - - case OID_GEN_DIRECTED_FRAMES_XMIT: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_GEN_DIRECTED_FRAMES_XMIT\n", port_num) ); - src_buf = NULL; - status = ipoib_get_send_stat( p_adapter, IP_STAT_UCAST_FRAMES, &oid_info ); - break; - - case OID_GEN_MULTICAST_BYTES_XMIT: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_GEN_MULTICAST_BYTES_XMIT\n", port_num) ); - src_buf = NULL; - status = ipoib_get_send_stat( p_adapter, IP_STAT_MCAST_BYTES, &oid_info ); - break; - - case OID_GEN_MULTICAST_FRAMES_XMIT: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_GEN_MULTICAST_FRAMES_XMIT\n", port_num) ); - src_buf = NULL; - status = ipoib_get_send_stat( p_adapter, IP_STAT_MCAST_FRAMES, &oid_info ); - break; - - case OID_GEN_BROADCAST_BYTES_XMIT: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_GEN_BROADCAST_BYTES_XMIT\n", port_num) ); - src_buf = NULL; - status = ipoib_get_send_stat( p_adapter, IP_STAT_BCAST_BYTES, &oid_info ); - break; - - case OID_GEN_BROADCAST_FRAMES_XMIT: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_GEN_BROADCAST_FRAMES_XMIT\n", port_num) ); - src_buf = NULL; - status = ipoib_get_send_stat( p_adapter, IP_STAT_BCAST_FRAMES, &oid_info ); - break; - - case OID_GEN_DIRECTED_BYTES_RCV: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_GEN_DIRECTED_BYTES_RCV\n", port_num) ); - src_buf = NULL; - status = ipoib_get_recv_stat( p_adapter, IP_STAT_UCAST_BYTES, &oid_info ); - break; - - case OID_GEN_DIRECTED_FRAMES_RCV: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_GEN_DIRECTED_FRAMES_RCV\n", port_num) ); - src_buf = NULL; - status = ipoib_get_recv_stat( p_adapter, IP_STAT_UCAST_FRAMES, &oid_info ); - break; - - case OID_GEN_MULTICAST_BYTES_RCV: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_GEN_MULTICAST_BYTES_RCV\n", port_num) ); - src_buf = NULL; - status = ipoib_get_recv_stat( p_adapter, IP_STAT_MCAST_BYTES, &oid_info ); - break; - - case OID_GEN_MULTICAST_FRAMES_RCV: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_GEN_MULTICAST_FRAMES_RCV\n", port_num) ); - src_buf = NULL; - status = ipoib_get_recv_stat( p_adapter, IP_STAT_MCAST_FRAMES, &oid_info ); - break; - - case OID_GEN_BROADCAST_BYTES_RCV: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_GEN_BROADCAST_BYTES_RCV\n", port_num) ); - src_buf = NULL; - status = ipoib_get_recv_stat( p_adapter, IP_STAT_BCAST_BYTES, &oid_info ); - break; - - case OID_GEN_BROADCAST_FRAMES_RCV: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_GEN_BROADCAST_FRAMES_RCV\n", port_num) ); - src_buf = NULL; - status = ipoib_get_recv_stat( p_adapter, IP_STAT_BCAST_FRAMES, &oid_info ); - break; - - /* Required Ethernet operational characteristics */ - case OID_802_3_PERMANENT_ADDRESS: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_802_3_PERMANENT_ADDRESS\n", port_num) ); - src_buf = &p_adapter->mac; - buf_len = sizeof(p_adapter->mac); - break; - - case OID_802_3_CURRENT_ADDRESS: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_802_3_CURRENT_ADDRESS\n", port_num) ); - src_buf = &p_adapter->params.conf_mac; - buf_len = sizeof(p_adapter->params.conf_mac); - break; - - case OID_802_3_MULTICAST_LIST: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_802_3_MULTICAST_LIST\n", port_num) ); - src_buf = p_adapter->mcast_array; - buf_len = p_adapter->mcast_array_size * sizeof(mac_addr_t); - break; - - case OID_802_3_MAXIMUM_LIST_SIZE: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_802_3_MAXIMUM_LIST_SIZE\n", port_num) ); - info = MAX_MCAST; - break; - - case OID_802_3_MAC_OPTIONS: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_802_3_MAC_OPTIONS\n", port_num) ); - info = 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: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_802_3_RCV_ERROR_ALIGNMENT or " - "OID_802_3_XMIT_ONE_COLLISION or " - "OID_802_3_XMIT_MORE_COLLISIONS\n", port_num) ); - info = 0; - break; - - case OID_TCP_TASK_OFFLOAD: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_TCP_TASK_OFFLOAD\n", port_num) ); - src_buf = NULL; - status = __ipoib_get_tcp_task_offload( p_adapter, &oid_info ); - break; - - /* Optional General */ - case OID_GEN_SUPPORTED_GUIDS: -#ifdef NDIS51_MINIPORT - case OID_GEN_VLAN_ID: -#endif - - /* 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; - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received an unsupported oid of 0x%.8X!\n", port_num, oid) ); - break; - - case OID_GEN_PROTOCOL_OPTIONS: - case OID_GEN_NETWORK_LAYER_ADDRESSES: - case OID_GEN_TRANSPORT_HEADER_OFFSET: - case OID_PNP_ENABLE_WAKE_UP: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_GEN_PROTOCOL_OPTIONS or OID_GEN_NETWORK_LAYER_ADDRESSES or OID_GEN_TRANSPORT_HEADER_OFFSET OID_PNP_ENABLE_WAKE_UPn", port_num) ); - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Number of OID: 0x%.8X!\n", oid) ); - status = NDIS_STATUS_SUCCESS; - break; - - case OID_PNP_QUERY_POWER: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_TCP_TASK_OFFLOAD\n", port_num) ); - // Status is pre-set in this routine to Success - status = NDIS_STATUS_SUCCESS; - break; - - case OID_TCP_OFFLOAD_CURRENT_CONFIG: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_PNP_QUERY_POWER\n", port_num) ); - //ulBytesAvailable = ulInfoLen = sizeof(NDIS_OFFLOAD); - if (info_buf_len < sizeof(NDIS_OFFLOAD)) - { - status = NDIS_STATUS_BUFFER_TOO_SHORT; - *p_bytes_needed = sizeof(NDIS_OFFLOAD) ; - break; - } - - //ipoib_offload_config(pPort, &offload); - //pInfo = &offload; - break; - - default: - status = NDIS_STATUS_INVALID_OID; - // IPOIB_PRINT( TRACE_LEVEL_ERROR,IPOIB_DBG_OID, - // ("Port %d received an invalid oid of 0x%.8X!\n", port_num, 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 - */ - if( status != NDIS_STATUS_PENDING ) - { - ipoib_complete_query( - p_adapter, &oid_info, status, src_buf, buf_len ); - return status; - } - - IPOIB_EXIT( IPOIB_DBG_OID ); - return NDIS_STATUS_PENDING; - } - - -static void -ipoib_complete_query( - IN ipoib_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; - - IPOIB_ENTER( IPOIB_DBG_OID ); - - CL_ASSERT( status != NDIS_STATUS_PENDING ); - - if( status == NDIS_STATUS_SUCCESS ) - { - if( p_oid_info->buf_len < buf_len ) - { - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_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 - { - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Returning NDIS_NOT_ACCEPTED") ); - oid_status = NDIS_STATUS_NOT_ACCEPTED; - } - } - else - { - *p_oid_info->p_bytes_used = 0; - } - - if (p_adapter->query_oid.p_pending_oid) - { - NdisMOidRequestComplete(p_adapter->h_adapter,p_adapter->query_oid.p_pending_oid,oid_status); - p_adapter->query_oid.p_pending_oid = NULL; - } - p_adapter->pending_query = FALSE; - - IPOIB_EXIT( IPOIB_DBG_OID ); -} - - -static NDIS_STATUS -__ipoib_get_tcp_task_offload( - IN ipoib_adapter_t* p_adapter, - OUT pending_oid_t *pNdisRequest ) -{ -#ifndef NDIS60_MINIPORT - NDIS_TASK_OFFLOAD_HEADER *p_offload_hdr; - NDIS_TASK_OFFLOAD *p_offload_task; - NDIS_TASK_TCP_IP_CHECKSUM *p_offload_chksum; - - NDIS_TASK_TCP_LARGE_SEND *p_offload_lso; - ULONG buf_len; - - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received query for OID_TCP_TASK_OFFLOAD\n", - p_adapter->guids.port_num) ); - - buf_len = sizeof(NDIS_TASK_OFFLOAD_HEADER) + - offsetof( NDIS_TASK_OFFLOAD, TaskBuffer ) + - sizeof(NDIS_TASK_TCP_IP_CHECKSUM) + - (p_adapter->params.lso ? - sizeof(NDIS_TASK_OFFLOAD) + sizeof(NDIS_TASK_TCP_LARGE_SEND) - : 0); - - pNdisRequest->DATA.QUERY_INFORMATION.BytesNeeded = buf_len; - - if( pNdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength < buf_len ) - return NDIS_STATUS_INVALID_LENGTH; - - p_offload_hdr = (NDIS_TASK_OFFLOAD_HEADER*)pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer; - 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; - } - - 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 = - p_offload_chksum->V4Transmit.TcpOptionsSupported = - p_offload_chksum->V4Transmit.TcpChecksum = - p_offload_chksum->V4Transmit.UdpChecksum = - p_offload_chksum->V4Transmit.IpChecksum = - !!(p_adapter->params.send_chksum_offload); - - 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_adapter->params.recv_chksum_offload); - - p_offload_chksum->V6Transmit.IpOptionsSupported = FALSE; - p_offload_chksum->V6Transmit.TcpOptionsSupported = FALSE; - p_offload_chksum->V6Transmit.TcpChecksum = FALSE; - p_offload_chksum->V6Transmit.UdpChecksum = FALSE; - - p_offload_chksum->V6Receive.IpOptionsSupported = FALSE; - p_offload_chksum->V6Receive.TcpOptionsSupported = FALSE; - p_offload_chksum->V6Receive.TcpChecksum = FALSE; - p_offload_chksum->V6Receive.UdpChecksum = FALSE; - - - if (p_adapter->params.lso) { - // set the previous pointer to the correct place - p_offload_task->OffsetNextTask = FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer) + - p_offload_task->TaskBufferLength; - // set the LSO packet - p_offload_task = (PNDIS_TASK_OFFLOAD) - ((PUCHAR)p_offload_task + p_offload_task->OffsetNextTask); - - p_offload_task->Version = NDIS_TASK_OFFLOAD_VERSION; - p_offload_task->Size = sizeof(NDIS_TASK_OFFLOAD); - p_offload_task->Task = TcpLargeSendNdisTask; - p_offload_task->OffsetNextTask = 0; - p_offload_task->TaskBufferLength = sizeof(NDIS_TASK_TCP_LARGE_SEND); - - p_offload_lso = (PNDIS_TASK_TCP_LARGE_SEND) p_offload_task->TaskBuffer; - - p_offload_lso->Version = 0; - //TODO optimal size: 60000, 64000 or 65536 - //TODO LSO_MIN_SEG_COUNT to be 1 - p_offload_lso->MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE; -#define LSO_MIN_SEG_COUNT 2 - p_offload_lso->MinSegmentCount = LSO_MIN_SEG_COUNT; - p_offload_lso->TcpOptions = TRUE; - p_offload_lso->IpOptions = TRUE; - } - - pNdisRequest->DATA.QUERY_INFORMATION.BytesWritten = buf_len - - return NDIS_STATUS_SUCCESS; -#endif - UNUSED_PARAM(p_adapter); - UNUSED_PARAM(pNdisRequest); - return NDIS_STATUS_NOT_SUPPORTED; - -} - - -static NDIS_STATUS -__ipoib_set_tcp_task_offload( - IN ipoib_adapter_t* p_adapter, - IN void* const p_info_buf, - IN ULONG* const p_info_len ) -{ -#ifndef NDIS60_MINIPORT - NDIS_TASK_OFFLOAD_HEADER *p_offload_hdr; - NDIS_TASK_OFFLOAD *p_offload_task; - NDIS_TASK_TCP_IP_CHECKSUM *p_offload_chksum; - - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received set for OID_TCP_TASK_OFFLOAD\n", - p_adapter->guids.port_num) ); - - 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; - - if( !p_adapter->params.send_chksum_offload && - (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) ) - { - return NDIS_STATUS_NOT_SUPPORTED; - } - - if( !p_adapter->params.recv_chksum_offload && - (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) ) - { - return NDIS_STATUS_NOT_SUPPORTED; - } - - return NDIS_STATUS_SUCCESS; -#endif - UNUSED_PARAM(p_adapter); - UNUSED_PARAM(p_info_buf); - UNUSED_PARAM(p_info_len); - return NDIS_STATUS_NOT_SUPPORTED; -} - - -//! 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 -ipoib_reset( - IN NDIS_HANDLE adapter_context, - OUT PBOOLEAN p_addr_reset) -{ - ipoib_adapter_t* p_adapter; - - IPOIB_ENTER( IPOIB_DBG_INIT ); -//return NDIS_STATUS_SUCCESS; - CL_ASSERT( p_addr_reset ); - CL_ASSERT( adapter_context ); - p_adapter = (ipoib_adapter_t*)adapter_context; - - switch( ipoib_reset_adapter( p_adapter ) ) - { - case IB_NOT_DONE: - IPOIB_EXIT( IPOIB_DBG_INIT ); - return NDIS_STATUS_PENDING; - - case IB_SUCCESS: - IPOIB_EXIT( IPOIB_DBG_INIT ); - *p_addr_reset = TRUE; - return NDIS_STATUS_SUCCESS; - - case IB_INVALID_STATE: - IPOIB_EXIT( IPOIB_DBG_INIT ); - return NDIS_STATUS_RESET_IN_PROGRESS; - - default: - IPOIB_EXIT( IPOIB_DBG_INIT ); - 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 -ipoib_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 ) -{ - ipoib_adapter_t* p_adapter; - NDIS_STATUS status; - - ULONG buf_len; - uint8_t port_num; - - KLOCK_QUEUE_HANDLE hdl; - - IPOIB_ENTER( IPOIB_DBG_OID ); - - CL_ASSERT( adapter_context ); - p_adapter = (ipoib_adapter_t*)adapter_context; - - 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); - - port_num = p_adapter->guids.port_num; - - cl_obj_lock( &p_adapter->obj ); - - if( p_adapter->state == IB_PNP_PORT_REMOVE ) - { - *p_bytes_read = 0; - cl_obj_unlock( &p_adapter->obj ); - return NDIS_STATUS_NOT_ACCEPTED; - } - - cl_obj_unlock( &p_adapter->obj ); - - switch( oid ) - { - /* Required General */ - case OID_GEN_CURRENT_PACKET_FILTER: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received set for OID_GEN_CURRENT_PACKET_FILTER\n", port_num)); - if( info_buf_len < sizeof(p_adapter->packet_filter) ) - { - status = NDIS_STATUS_INVALID_LENGTH; - } - else if( !info_buf ) - { - status = NDIS_STATUS_INVALID_DATA; - } - else - { - KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl ); - cl_obj_lock( &p_adapter->obj ); - switch( p_adapter->state ) - { - case IB_PNP_PORT_ADD: - p_adapter->set_oid.oid = oid; - p_adapter->set_oid.p_buf = info_buf; - p_adapter->set_oid.buf_len = info_buf_len; - p_adapter->set_oid.p_bytes_used = p_bytes_read; - p_adapter->set_oid.p_bytes_needed = p_bytes_needed; - p_adapter->pending_set = TRUE; - status = NDIS_STATUS_PENDING; - break; - - case IB_PNP_PORT_REMOVE: - status = NDIS_STATUS_NOT_ACCEPTED; - break; - - default: - if( !p_adapter->packet_filter && (*(uint32_t*)info_buf) ) - { - cl_qlist_insert_tail( - &g_ipoib.adapter_list, &p_adapter->entry ); - - /* - * Filter was zero, now non-zero. Register IP addresses - * with SA. - */ - ipoib_reg_addrs( p_adapter ); - } - else if( p_adapter->packet_filter && !(*(uint32_t*)info_buf) ) - { - /* - * Filter was non-zero, now zero. Deregister IP addresses. - */ - ipoib_dereg_addrs( p_adapter ); - - ASSERT( cl_qlist_count( &g_ipoib.adapter_list ) ); - cl_qlist_remove_item( - &g_ipoib.adapter_list, &p_adapter->entry ); - } - - p_adapter->packet_filter = *(uint32_t*)info_buf; - } - cl_obj_unlock( &p_adapter->obj ); - KeReleaseInStackQueuedSpinLock( &hdl ); - } - break; - - case OID_GEN_CURRENT_LOOKAHEAD: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received set for OID_GEN_CURRENT_LOOKAHEAD\n", port_num)); - if( info_buf_len < buf_len ) - status = NDIS_STATUS_INVALID_LENGTH; - break; - - case OID_GEN_PROTOCOL_OPTIONS: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received set for OID_GEN_PROTOCOL_OPTIONS\n", port_num)); - if( info_buf_len < buf_len ) - status = NDIS_STATUS_INVALID_LENGTH; - break; - - case OID_GEN_NETWORK_LAYER_ADDRESSES: - status = __ipoib_set_net_addr( p_adapter, info_buf, info_buf_len, p_bytes_read, p_bytes_needed); - break; - -#ifdef NDIS51_MINIPORT - case OID_GEN_MACHINE_NAME: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID, - ("Port %d received set for OID_GEN_MACHINE_NAME\n", port_num) ); - break; -#endif - - /* Required Ethernet operational characteristics */ - case OID_802_3_MULTICAST_LIST: - IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID, - ("Port %d received set for OID_802_3_MULTICAST_LIST\n", port_num) ); - if( info_buf_len > MAX_MCAST * sizeof(mac_addr_t) ) - { - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d OID_802_3_MULTICAST_LIST - Multicast list full.\n", port_num) ); - status = NDIS_STATUS_MULTICAST_FULL; - *p_bytes_needed = MAX_MCAST * sizeof(mac_addr_t); - } - else if( info_buf_len % sizeof(mac_addr_t) ) - { - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d OID_802_3_MULTICAST_LIST - Invalid input buffer.\n", port_num) ); - status = NDIS_STATUS_INVALID_DATA; - } - else if( !info_buf && info_buf_len ) - { - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d OID_802_3_MULTICAST_LIST - Invalid input buffer.\n", port_num) ); - status = NDIS_STATUS_INVALID_DATA; - } - else - { - ipoib_refresh_mcast( p_adapter, (mac_addr_t*)info_buf, - (uint8_t)(info_buf_len / sizeof(mac_addr_t)) ); - - buf_len = info_buf_len; - /* - * Note that we don't return pending. It will likely take longer - * for our SA transactions to complete than NDIS will give us - * before reseting the adapter. If an SA failure is encountered, - * the adapter will be marked as hung and we will get reset. - */ - status = NDIS_STATUS_SUCCESS; - } - break; - - case OID_TCP_TASK_OFFLOAD: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received set for OID_TCP_TASK_OFFLOAD\n", port_num) ); - - buf_len = info_buf_len; - status = - __ipoib_set_tcp_task_offload( p_adapter, info_buf, &buf_len ); - break; - - /* Optional General */ - case OID_GEN_TRANSPORT_HEADER_OFFSET: -#ifdef NDIS51_MINIPORT - case OID_GEN_RNDIS_CONFIG_PARAMETER: - case OID_GEN_VLAN_ID: -#endif - status = NDIS_STATUS_NOT_SUPPORTED; - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received an unsupported oid of 0x%.8X!\n", port_num, oid)); - 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; - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received an invalid oid of 0x%.8X!\n", port_num, 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; - } - - IPOIB_EXIT( IPOIB_DBG_OID ); - return status; -} - -#ifdef NNN -NDIS_STATUS -ipoib_set_info( - ipoib_adapter_t* p_adapter, - IN PNDIS_OID_REQUEST pNdisRequest) -{ - NDIS_STATUS status; - NDIS_OID oid; - UINT info_buf_len; - UINT buf_len; - uint8_t port_num; - PVOID info_buf; - UINT *p_bytes_needed; - KLOCK_QUEUE_HANDLE hdl; - - IPOIB_ENTER( IPOIB_DBG_OID ); - - oid = pNdisRequest->DATA.SET_INFORMATION.Oid; - info_buf = pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer; - info_buf_len = pNdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength; - p_bytes_needed = &pNdisRequest->DATA.QUERY_INFORMATION.BytesNeeded; - status = NDIS_STATUS_SUCCESS; - - buf_len = sizeof(UINT); - port_num = p_adapter->guids.port_num; - - switch( oid ) - { - /* Required General */ - case OID_GEN_CURRENT_PACKET_FILTER: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received set for OID_GEN_CURRENT_PACKET_FILTER\n", port_num)); - if( info_buf_len < sizeof(p_adapter->packet_filter) ) - { - status = NDIS_STATUS_INVALID_LENGTH; - } - else if( !info_buf ) - { - status = NDIS_STATUS_INVALID_DATA; - } - else - { - KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl ); - cl_obj_lock( &p_adapter->obj ); - switch( p_adapter->state ) - { - case IB_PNP_PORT_ADD: - p_adapter->p_oid_request = pNdisRequest; - status = NDIS_STATUS_PENDING; - break; - - case IB_PNP_PORT_REMOVE: - status = NDIS_STATUS_NOT_ACCEPTED; - break; - - default: - if( !p_adapter->packet_filter && (*(uint32_t*)info_buf) ) - { - cl_qlist_insert_tail( - &g_ipoib.adapter_list, &p_adapter->entry ); - - /* - * Filter was zero, now non-zero. Register IP addresses - * with SA. - */ - ipoib_reg_addrs( p_adapter ); - } - else if( p_adapter->packet_filter && !(*(uint32_t*)info_buf) ) - { - /* - * Filter was non-zero, now zero. Deregister IP addresses. - */ - ipoib_dereg_addrs( p_adapter ); - - ASSERT( cl_qlist_count( &g_ipoib.adapter_list ) ); - cl_qlist_remove_item( - &g_ipoib.adapter_list, &p_adapter->entry ); - } - - p_adapter->packet_filter = *(uint32_t*)info_buf; - } - cl_obj_unlock( &p_adapter->obj ); - KeReleaseInStackQueuedSpinLock( &hdl ); - } - break; - - case OID_GEN_CURRENT_LOOKAHEAD: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received set for OID_GEN_CURRENT_LOOKAHEAD\n", port_num)); - if( info_buf_len < buf_len ) - status = NDIS_STATUS_INVALID_LENGTH; - break; - - case OID_GEN_PROTOCOL_OPTIONS: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received set for OID_GEN_PROTOCOL_OPTIONS\n", port_num)); - if( info_buf_len < buf_len ) - status = NDIS_STATUS_INVALID_LENGTH; - break; - - case OID_GEN_NETWORK_LAYER_ADDRESSES: - status = __ipoib_set_net_addr( p_adapter, pNdisRequest); - break; - - case OID_GEN_MACHINE_NAME: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID, - ("Port %d received set for OID_GEN_MACHINE_NAME\n", port_num) ); - break; - - - /* Required Ethernet operational characteristics */ - case OID_802_3_MULTICAST_LIST: - IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID, - ("Port %d received set for OID_802_3_MULTICAST_LIST\n", port_num) ); - if( info_buf_len > MAX_MCAST * sizeof(mac_addr_t) ) - { - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d OID_802_3_MULTICAST_LIST - Multicast list full.\n", port_num) ); - status = NDIS_STATUS_MULTICAST_FULL; - *p_bytes_needed = MAX_MCAST * sizeof(mac_addr_t); - } - else if( info_buf_len % sizeof(mac_addr_t) ) - { - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d OID_802_3_MULTICAST_LIST - Invalid input buffer.\n", port_num) ); - status = NDIS_STATUS_INVALID_DATA; - } - else if( !info_buf && info_buf_len ) - { - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d OID_802_3_MULTICAST_LIST - Invalid input buffer.\n", port_num) ); - status = NDIS_STATUS_INVALID_DATA; - } - else - { - ipoib_refresh_mcast( p_adapter, (mac_addr_t*)info_buf, - (uint8_t)(info_buf_len / sizeof(mac_addr_t)) ); - - buf_len = info_buf_len; - /* - * Note that we don't return pending. It will likely take longer - * for our SA transactions to complete than NDIS will give us - * before reseting the adapter. If an SA failure is encountered, - * the adapter will be marked as hung and we will get reset. - */ - status = NDIS_STATUS_SUCCESS; - } - break; - - case OID_TCP_TASK_OFFLOAD: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received set for OID_TCP_TASK_OFFLOAD\n", port_num) ); - - buf_len = info_buf_len; - status = - __ipoib_set_tcp_task_offload( p_adapter, pNdisRequest ); - break; - - /* Optional General */ - case OID_GEN_TRANSPORT_HEADER_OFFSET: -#ifdef NDIS51_MINIPORT - case OID_GEN_RNDIS_CONFIG_PARAMETER: - case OID_GEN_VLAN_ID: -#endif - status = NDIS_STATUS_NOT_SUPPORTED; - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received an unsupported oid of 0x%.8X!\n", port_num, oid)); - 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; - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received an invalid oid of 0x%.8X!\n", port_num, oid)); - break; - } - - if( status == NDIS_STATUS_SUCCESS ) - { - pNdisRequest->DATA.SET_INFORMATION.BytesRead = buf_len; - } - else - { - if( status == NDIS_STATUS_INVALID_LENGTH ) - { - if ( !*p_bytes_needed ) - { - *p_bytes_needed = buf_len; - } - } - - pNdisRequest->DATA.SET_INFORMATION.BytesRead = 0; - } - - IPOIB_EXIT( IPOIB_DBG_OID ); - return status; -} -#endif -static NDIS_STATUS -ipoib_oid_handler( - IN NDIS_HANDLE adapter_context, - IN PNDIS_OID_REQUEST pNdisRequest) -{ - NDIS_REQUEST_TYPE RequestType; - NDIS_STATUS status = NDIS_STATUS_SUCCESS; - - IPOIB_ENTER( IPOIB_DBG_OID ); - - RequestType = pNdisRequest->RequestType; - - switch(RequestType) - { - case NdisRequestSetInformation: - status = ipoib_set_info(adapter_context, - pNdisRequest->DATA.SET_INFORMATION.Oid, - pNdisRequest->DATA.SET_INFORMATION.InformationBuffer, - pNdisRequest->DATA.SET_INFORMATION.InformationBufferLength, - (PULONG)&pNdisRequest->DATA.SET_INFORMATION.BytesRead, - (PULONG)&pNdisRequest->DATA.SET_INFORMATION.BytesNeeded); - break; - - case NdisRequestQueryInformation: - case NdisRequestQueryStatistics: - status = ipoib_query_info(adapter_context, - pNdisRequest->DATA.QUERY_INFORMATION.Oid, - pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer, - pNdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength, - (PULONG)&pNdisRequest->DATA.QUERY_INFORMATION.BytesWritten, - (PULONG)&pNdisRequest->DATA.QUERY_INFORMATION.BytesNeeded); - - break; - - default: - status = NDIS_STATUS_NOT_SUPPORTED; - break; - } - IPOIB_EXIT( IPOIB_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 ipoib_adapter_t structure with per NIC state -@param packet_array Array of packets to send -@param numPackets Number of packets in the array -*/ -void -ipoib_send_net_buffer_list( - IN NDIS_HANDLE adapter_context, - IN PNET_BUFFER_LIST net_buffer_list, - IN NDIS_PORT_NUMBER port_num, - IN ULONG send_flags - ) -{ - ipoib_adapter_t *p_adapter; - ipoib_port_t *p_port; - ULONG send_complete_flags; - PNET_BUFFER_LIST curr_net_buffer_list; - PNET_BUFFER_LIST next_net_buffer_list; - NDIS_STATUS status = NDIS_STATUS_SUCCESS; - - UNREFERENCED_PARAMETER(port_num); - PERF_DECLARE( SendPackets ); - PERF_DECLARE( PortSend ); - - IPOIB_ENTER( IPOIB_DBG_SEND ); - cl_perf_start( SendPackets ); - - CL_ASSERT( adapter_context ); - p_adapter = (ipoib_adapter_t*)adapter_context; - p_port = p_adapter->p_port; - - cl_obj_lock( &p_adapter->obj ); - if( p_adapter->ipoib_state == IPOIB_PAUSING || - p_adapter->ipoib_state == IPOIB_PAUSED) - { - status = NDIS_STATUS_PAUSED; - cl_obj_unlock( &p_adapter->obj ); - goto compl_status; - } - - if( p_adapter->state != IB_PNP_PORT_ACTIVE || !p_adapter->p_port ) - { - cl_obj_unlock( &p_adapter->obj ); - status = NDIS_STATUS_FAILURE; - goto compl_status; - } - - p_port = p_adapter->p_port; - ipoib_port_ref( p_port, ref_send_packets ); - cl_obj_unlock( &p_adapter->obj ); - //IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - // ("Starting NET BUFFER LIST \n") ); - for (curr_net_buffer_list = net_buffer_list; - curr_net_buffer_list != NULL; - curr_net_buffer_list = next_net_buffer_list) - { - next_net_buffer_list = NET_BUFFER_LIST_NEXT_NBL(curr_net_buffer_list); - cl_perf_start( PortSend ); - - ipoib_port_send( p_port, curr_net_buffer_list, send_flags); - cl_perf_stop( &adapter->perf, PortSend ); - } - ipoib_port_deref( p_port, ref_send_packets ); - - cl_perf_stop( &p_adapter->perf, SendPackets ); - - cl_perf_log( &p_adapter->perf, SendBundle, num_packets ); - -compl_status: - if (status != NDIS_STATUS_SUCCESS) - { - //ASSERT(FALSE); //???? - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Got bad status \n") ); - send_complete_flags = 0; - - for (curr_net_buffer_list = net_buffer_list; - curr_net_buffer_list != NULL; - curr_net_buffer_list = next_net_buffer_list) - { - next_net_buffer_list = NET_BUFFER_LIST_NEXT_NBL(curr_net_buffer_list); - NET_BUFFER_LIST_STATUS(curr_net_buffer_list) = status; - ipoib_inc_send_stat( p_adapter, IP_STAT_DROPPED, 0 ); - } - - - if (NDIS_TEST_SEND_AT_DISPATCH_LEVEL(send_flags)) - { - NDIS_SET_SEND_COMPLETE_FLAG(send_complete_flags, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL); - } - - NdisMSendNetBufferListsComplete( - p_adapter->h_adapter, - net_buffer_list, - send_complete_flags); - } - IPOIB_EXIT( IPOIB_DBG_SEND ); -} - -void -ipoib_pnp_notify( - IN NDIS_HANDLE adapter_context, - IN PNET_DEVICE_PNP_EVENT pnp_event) -{ - ipoib_adapter_t *p_adapter; - - IPOIB_ENTER( IPOIB_DBG_PNP ); - - p_adapter = (ipoib_adapter_t*)adapter_context; - - IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_PNP, ("Event %d\n", pnp_event->DevicePnPEvent) ); - if( pnp_event->DevicePnPEvent != NdisDevicePnPEventPowerProfileChanged ) - { - cl_obj_lock( &p_adapter->obj ); - p_adapter->state = IB_PNP_PORT_REMOVE; - cl_obj_unlock( &p_adapter->obj ); - - ipoib_resume_oids( p_adapter ); - } - - IPOIB_EXIT( IPOIB_DBG_PNP ); -} - - -VOID -ipoib_shutdown_ex( - IN NDIS_HANDLE adapter_context, - IN NDIS_SHUTDOWN_ACTION shutdown_action) -{ - IPOIB_ENTER( IPOIB_DBG_INIT ); - UNUSED_PARAM( adapter_context ); - UNUSED_PARAM( shutdown_action ); - IPOIB_EXIT( IPOIB_DBG_INIT ); -} - - -void -ipoib_resume_oids( - IN ipoib_adapter_t* const p_adapter ) -{ - ULONG info; - NDIS_STATUS status; - boolean_t pending_query, pending_set; - pending_oid_t query_oid = {0}; - pending_oid_t set_oid = {0}; - KLOCK_QUEUE_HANDLE hdl; - - IPOIB_ENTER( IPOIB_DBG_INIT ); - - cl_obj_lock( &p_adapter->obj ); - /* - * Set the status depending on our state. Fail OID requests that - * are pending while we reset the adapter. - */ - switch( p_adapter->state ) - { - case IB_PNP_PORT_ADD: - status = NDIS_STATUS_FAILURE; - break; - - case IB_PNP_PORT_REMOVE: - status = NDIS_STATUS_NOT_ACCEPTED; - break; - - default: - status = NDIS_STATUS_SUCCESS; - } - - pending_query = p_adapter->pending_query; - if( pending_query ) - { - query_oid = p_adapter->query_oid; - p_adapter->pending_query = FALSE; - } - pending_set = p_adapter->pending_set; - if( pending_set ) - { - set_oid = p_adapter->set_oid; - p_adapter->pending_set = FALSE; - } - cl_obj_unlock( &p_adapter->obj ); - - /* - * 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_GEN_LINK_SPEED: - ipoib_complete_query( p_adapter, &query_oid, - status, &p_adapter->port_rate, sizeof(p_adapter->port_rate) ); - break; - - case OID_GEN_MEDIA_CONNECT_STATUS: - info = NdisMediaStateConnected; - ipoib_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 ); - break; - } - } - - if( pending_set ) - { - switch( set_oid.oid ) - { - case OID_GEN_CURRENT_PACKET_FILTER: - /* Validation already performed in the SetInformation path. */ - - KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl ); - cl_obj_lock( &p_adapter->obj ); - if( !p_adapter->packet_filter && (*(PULONG)set_oid.p_buf) ) - { - cl_qlist_insert_tail( - &g_ipoib.adapter_list, &p_adapter->entry ); - /* - * Filter was zero, now non-zero. Register IP addresses - * with SA. - */ - ipoib_reg_addrs( p_adapter ); - } - else if( p_adapter->packet_filter && !(*(PULONG)set_oid.p_buf) ) - { - /* Filter was non-zero, now zero. Deregister IP addresses. */ - ipoib_dereg_addrs( p_adapter ); - - ASSERT( cl_qlist_count( &g_ipoib.adapter_list ) ); - cl_qlist_remove_item( - &g_ipoib.adapter_list, &p_adapter->entry ); - } - p_adapter->packet_filter = *(PULONG)set_oid.p_buf; - - cl_obj_unlock( &p_adapter->obj ); - KeReleaseInStackQueuedSpinLock( &hdl ); - p_adapter->set_oid.p_pending_oid = NULL; - NdisMOidRequestComplete( p_adapter->h_adapter, set_oid.p_pending_oid, status ); - break; - - case OID_GEN_NETWORK_LAYER_ADDRESSES: - status = __ipoib_set_net_addr( p_adapter, - p_adapter->set_oid.p_buf, - p_adapter->set_oid.buf_len, - p_adapter->set_oid.p_bytes_used, - p_adapter->set_oid.p_bytes_needed ); - - if( status != NDIS_STATUS_PENDING ) - { - p_adapter->set_oid.p_pending_oid = NULL; - NdisMOidRequestComplete( p_adapter->h_adapter, set_oid.p_pending_oid, status ); - } - break; - - default: - CL_ASSERT( set_oid.oid && 0 ); - break; - } - } - - IPOIB_EXIT( IPOIB_DBG_INIT ); -} - - -static NDIS_STATUS -__ipoib_set_net_addr( - IN ipoib_adapter_t * p_adapter, - IN PVOID info_buf, - IN ULONG info_buf_len, - OUT PULONG p_bytes_read, - OUT PULONG p_bytes_needed ) -{ - NDIS_STATUS status; - PNETWORK_ADDRESS_LIST p_net_addrs; - PNETWORK_ADDRESS p_net_addr_oid; - PNETWORK_ADDRESS_IP p_ip_addr; - - net_address_item_t *p_addr_item; - - cl_status_t cl_status; - - size_t idx; - LONG i; - ULONG addr_size; - ULONG total_size; - - uint8_t port_num; - - IPOIB_ENTER( IPOIB_DBG_OID ); - - status = NDIS_STATUS_SUCCESS; - port_num = p_adapter->guids.port_num; - - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d received set for OID_GEN_NETWORK_LAYER_ADDRESSES\n", - port_num) ); - - if( !info_buf ) - { - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Port %d - OID_GEN_NETWORK_LAYER_ADDRESSES - " - "NULL buffer\n", port_num) ); - IPOIB_EXIT( IPOIB_DBG_OID ); - return NDIS_STATUS_INVALID_DATA; - } - - /* - * Must use field offset because the structures define array's of size one - * of a the incorrect type for what is really stored. - */ - if( info_buf_len < FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address) ) - { - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - " - "bad length of %d, not enough " - "for NETWORK_ADDRESS_LIST (%d)\n", port_num, info_buf_len, - FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address)) ); - *p_bytes_needed = FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address); - IPOIB_EXIT( IPOIB_DBG_OID ); - return NDIS_STATUS_INVALID_LENGTH; - } - - p_net_addrs = (PNETWORK_ADDRESS_LIST)info_buf; - if( p_net_addrs->AddressCount == 0) - { - if( p_net_addrs->AddressType == NDIS_PROTOCOL_ID_TCP_IP ) - { - IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID, - ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - " - "clear TCP/IP addresses\n", port_num) ); - } - else - { - IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID, - ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - " - "Non TCP/IP address type of 0x%.4X on clear\n", - port_num, p_net_addrs->AddressType) ); - IPOIB_EXIT( IPOIB_DBG_OID ); - return NDIS_STATUS_SUCCESS; - } - } - - addr_size = FIELD_OFFSET(NETWORK_ADDRESS, Address) + - NETWORK_ADDRESS_LENGTH_IP; - total_size = FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address) + - addr_size * p_net_addrs->AddressCount; - - if( info_buf_len < total_size ) - { - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - " - "bad length of %d, %d required for %d addresses\n", - port_num, info_buf_len, total_size, p_net_addrs->AddressCount) ); - *p_bytes_needed = total_size; - IPOIB_EXIT( IPOIB_DBG_OID ); - return NDIS_STATUS_INVALID_LENGTH; - } - - /* Lock lists for duration since SA callbacks can occur on other CPUs */ - cl_obj_lock( &p_adapter->obj ); - - /* Set the capacity of the vector to accomodate all assinged addresses. */ - cl_status = cl_vector_set_capacity( - &p_adapter->ip_vector, p_net_addrs->AddressCount ); - if( cl_status != CL_SUCCESS ) - { - cl_obj_unlock( &p_adapter->obj ); - IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Port %d - OID_GEN_NETWORK_LAYER_ADDRESSES - " - "Failed to set IP vector capacity: %#x\n", port_num, - cl_status) ); - IPOIB_EXIT( IPOIB_DBG_OID ); - return NDIS_STATUS_RESOURCES; - } - - *p_bytes_read = total_size; - - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - List contains %d addresses\n", - port_num, p_net_addrs->AddressCount)); - - /* First look for addresses we had that should be removed */ - for( idx = 0; idx != cl_vector_get_size( &p_adapter->ip_vector ); idx++ ) - { - p_addr_item = (net_address_item_t*) - cl_vector_get_ptr( &p_adapter->ip_vector, idx ); - p_net_addr_oid = (PNETWORK_ADDRESS)p_net_addrs->Address; - - for( i = 0; i < p_net_addrs->AddressCount; ++i, p_net_addr_oid = - (PNETWORK_ADDRESS)((uint8_t *)p_net_addr_oid + - FIELD_OFFSET(NETWORK_ADDRESS, Address) + - p_net_addr_oid->AddressLength) ) - { - - if( p_net_addr_oid->AddressType != NDIS_PROTOCOL_ID_TCP_IP ) - { - IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_OID, - ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Address %d is wrong type of 0x%.4X, " - "should be 0x%.4X\n", port_num, i, p_net_addr_oid->AddressType, - NDIS_PROTOCOL_ID_TCP_IP)); - continue; - } - - if( p_net_addr_oid->AddressLength != NETWORK_ADDRESS_LENGTH_IP) - { - IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_OID, - ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Address %d is wrong size of %d, " - "should be %d\n", port_num, i, p_net_addr_oid->AddressLength, - NETWORK_ADDRESS_LENGTH_IP)); - continue; - } - - p_ip_addr = (PNETWORK_ADDRESS_IP)p_net_addr_oid->Address; - if( !cl_memcmp( &p_ip_addr->in_addr, - &p_addr_item->address.as_ulong, sizeof(ULONG) ) ) - { - break; - } - } - - if( i == p_net_addrs->AddressCount ) - { - /* Didn't find a match, delete from SA */ - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Deleting Address %d.%d.%d.%d\n", - port_num, - p_addr_item->address.as_bytes[0], - p_addr_item->address.as_bytes[1], - p_addr_item->address.as_bytes[2], - p_addr_item->address.as_bytes[3])); - - if( p_addr_item->p_reg ) - { - if( p_addr_item->p_reg->h_reg_svc ) - { - p_adapter->p_ifc->dereg_svc( - p_addr_item->p_reg->h_reg_svc, __ipoib_ats_dereg_cb ); - } - else - { - cl_free( p_addr_item->p_reg ); - } - p_addr_item->p_reg = NULL; - } - p_addr_item->address.as_ulong = 0; - } - } - - /* Now look for new addresses */ - p_net_addr_oid = (NETWORK_ADDRESS *)p_net_addrs->Address; - idx = 0; - for( i = 0; i < p_net_addrs->AddressCount; i++, p_net_addr_oid = - (PNETWORK_ADDRESS)((uint8_t *)p_net_addr_oid + - FIELD_OFFSET(NETWORK_ADDRESS, Address) + p_net_addr_oid->AddressLength) ) - { - - if( p_net_addr_oid->AddressType != NDIS_PROTOCOL_ID_TCP_IP ) - { - IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID, - ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Address %d is wrong type of 0x%.4X, " - "should be 0x%.4X\n", port_num, i, p_net_addr_oid->AddressType, - NDIS_PROTOCOL_ID_TCP_IP)); - continue; - } - - if( p_net_addr_oid->AddressLength != NETWORK_ADDRESS_LENGTH_IP) - { - IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID, - ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Address %d is wrong size of %d, " - "should be %d\n", port_num, i, p_net_addr_oid->AddressLength, - NETWORK_ADDRESS_LENGTH_IP)); - continue; - } - - p_ip_addr = (PNETWORK_ADDRESS_IP)p_net_addr_oid->Address; - - /* Size the vector as needed. */ - if( cl_vector_get_size( &p_adapter->ip_vector ) <= idx ) - cl_vector_set_size( &p_adapter->ip_vector, idx + 1 ); - - p_addr_item = cl_vector_get_ptr( &p_adapter->ip_vector, idx ); - if( !cl_memcmp( &p_ip_addr->in_addr, &p_addr_item->address.as_ulong, - sizeof(ULONG) ) ) - { - idx++; - /* Already have this address - no change needed */ - continue; - } - - /* - * Copy the address information, but don't register yet - the port - * could be down. - */ - if( p_addr_item->p_reg ) - { - /* If in use by some other address, deregister. */ - if( p_addr_item->p_reg->h_reg_svc ) - { - p_adapter->p_ifc->dereg_svc( - p_addr_item->p_reg->h_reg_svc, __ipoib_ats_dereg_cb ); - } - else - { - cl_free( p_addr_item->p_reg ); - } - p_addr_item->p_reg = NULL; - } - memcpy ((void *)&p_addr_item->address.as_ulong, (const void *)&p_ip_addr->in_addr, sizeof(ULONG) ); - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Adding Address %d.%d.%d.%d\n", - port_num, - p_addr_item->address.as_bytes[0], - p_addr_item->address.as_bytes[1], - p_addr_item->address.as_bytes[2], - p_addr_item->address.as_bytes[3]) ); - idx++; - } - - /* Now clear any extra entries that shouldn't be there. */ - while( idx < cl_vector_get_size( &p_adapter->ip_vector ) ) - { - p_addr_item = (net_address_item_t*) - cl_vector_get_ptr( &p_adapter->ip_vector, - cl_vector_get_size( &p_adapter->ip_vector ) - 1 ); - - if( p_addr_item->p_reg ) - { - if( p_addr_item->p_reg->h_reg_svc ) - { - p_adapter->p_ifc->dereg_svc( - p_addr_item->p_reg->h_reg_svc, __ipoib_ats_dereg_cb ); - } - else - { - cl_free( p_addr_item->p_reg ); - } - p_addr_item->p_reg = NULL; - p_addr_item->address.as_ulong = 0; - } - - /* No need to check return value - shrinking always succeeds. */ - cl_vector_set_size( &p_adapter->ip_vector, - cl_vector_get_size( &p_adapter->ip_vector ) - 1 ); - } - - if( p_adapter->state == IB_PNP_PORT_ACTIVE && p_adapter->packet_filter ) - ipoib_reg_addrs( p_adapter ); - - cl_obj_unlock( &p_adapter->obj ); - - IPOIB_EXIT( IPOIB_DBG_OID ); - return NDIS_STATUS_SUCCESS; -} - - -/* Object lock is held when this function is called. */ -void -ipoib_reg_addrs( - IN ipoib_adapter_t* const p_adapter ) -{ - net_address_item_t *p_addr_item; - - size_t idx; - - uint8_t port_num; - - ib_api_status_t ib_status; - ib_reg_svc_req_t ib_service; - ib_gid_t port_gid; - - IPOIB_ENTER( IPOIB_DBG_OID ); - - if(p_adapter->guids.port_guid.pkey != IB_DEFAULT_PKEY) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR,IPOIB_DBG_ERROR, - ("ATS Service available for default pkey only\n")); - return; - } - port_num = p_adapter->guids.port_num; - - /* Setup our service call with things common to all calls */ - cl_memset( &ib_service, 0, sizeof(ib_service) ); - - /* BUGBUG Only register local subnet GID prefix for now */ - ib_gid_set_default( &port_gid, p_adapter->guids.port_guid.guid ); - ib_service.svc_rec.service_gid = port_gid; - - ib_service.svc_rec.service_pkey = IB_DEFAULT_PKEY; - ib_service.svc_rec.service_lease = IB_INFINITE_SERVICE_LEASE; - - /* Must cast here because the service name is an array of unsigned chars but - * strcpy want a pointer to a signed char */ - if ( StringCchCopy( (char *)ib_service.svc_rec.service_name, - sizeof(ib_service.svc_rec.service_name) / sizeof(char), ATS_NAME ) != S_OK) { - ASSERT(FALSE); - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR,IPOIB_DBG_ERROR, - ("Problem copying ATS name: exiting\n")); - return; - } - - /* IP Address in question will be put in below */ - ib_service.port_guid = p_adapter->guids.port_guid.guid; - ib_service.timeout_ms = p_adapter->params.sa_timeout; - ib_service.retry_cnt = p_adapter->params.sa_retry_cnt; - - /* Can't set IB_FLAGS_SYNC here because I can't wait at dispatch */ - ib_service.flags = 0; - - /* Service context will be put in below */ - - ib_service.svc_data_mask = IB_SR_COMPMASK_SID | - IB_SR_COMPMASK_SGID | - IB_SR_COMPMASK_SPKEY | - IB_SR_COMPMASK_SLEASE | - IB_SR_COMPMASK_SNAME | - IB_SR_COMPMASK_SDATA8_12 | - IB_SR_COMPMASK_SDATA8_13 | - IB_SR_COMPMASK_SDATA8_14 | - IB_SR_COMPMASK_SDATA8_15; - ib_service.pfn_reg_svc_cb = __ipoib_ats_reg_cb; - - for( idx = 0; idx < cl_vector_get_size( &p_adapter->ip_vector); idx++ ) - { - p_addr_item = (net_address_item_t*) - cl_vector_get_ptr( &p_adapter->ip_vector, idx ); - - if( p_addr_item->p_reg ) - continue; - - p_addr_item->p_reg = cl_zalloc( sizeof(ats_reg_t) ); - if( !p_addr_item->p_reg ) - break; - - p_addr_item->p_reg->p_adapter = p_adapter; - - ib_service.svc_context = p_addr_item->p_reg; - - ib_service.svc_rec.service_id = - ATS_SERVICE_ID & CL_HTON64(0xFFFFFFFFFFFFFF00); - /* ATS service IDs start at 0x10000CE100415453 */ - ib_service.svc_rec.service_id |= ((uint64_t)(idx + 0x53)) << 56; - - cl_memcpy( &ib_service.svc_rec.service_data8[ATS_IPV4_OFFSET], - p_addr_item->address.as_bytes, IPV4_ADDR_SIZE ); - - /* Take a reference for each service request. */ - cl_obj_ref(&p_adapter->obj); - ib_status = p_adapter->p_ifc->reg_svc( - p_adapter->h_al, &ib_service, &p_addr_item->p_reg->h_reg_svc ); - if( ib_status != IB_SUCCESS ) - { - if( ib_status == IB_INVALID_GUID ) - { - /* If this occurs, we log the error but do not fail the OID yet */ - IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_OID, - ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - " - "Failed to register IP Address " - "of %d.%d.%d.%d with error IB_INVALID_GUID\n", - port_num, - p_addr_item->address.as_bytes[0], - p_addr_item->address.as_bytes[1], - p_addr_item->address.as_bytes[2], - p_addr_item->address.as_bytes[3]) ); - } - else - { - /* Fatal error. */ - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Failed to register IP Address " - "of %d.%d.%d.%d with error %s\n", - port_num, - p_addr_item->address.as_bytes[0], - p_addr_item->address.as_bytes[1], - p_addr_item->address.as_bytes[2], - p_addr_item->address.as_bytes[3], - p_adapter->p_ifc->get_err_str( ib_status )) ); - p_adapter->hung = TRUE; - } - cl_obj_deref(&p_adapter->obj); - cl_free( p_addr_item->p_reg ); - p_addr_item->p_reg = NULL; - } - } - - IPOIB_EXIT( IPOIB_DBG_OID ); -} - - -/* Object lock is held when this function is called. */ -void -ipoib_dereg_addrs( - IN ipoib_adapter_t* const p_adapter ) -{ - net_address_item_t *p_addr_item; - - size_t idx; - - IPOIB_ENTER( IPOIB_DBG_OID ); - - for( idx = 0; idx < cl_vector_get_size( &p_adapter->ip_vector); idx++ ) - { - p_addr_item = (net_address_item_t*) - cl_vector_get_ptr( &p_adapter->ip_vector, idx ); - - if( !p_addr_item->p_reg ) - continue; - - if( p_addr_item->p_reg->h_reg_svc ) - { - p_adapter->p_ifc->dereg_svc( - p_addr_item->p_reg->h_reg_svc, __ipoib_ats_dereg_cb ); - } - else - { - cl_free( p_addr_item->p_reg ); - } - p_addr_item->p_reg = NULL; - } - - IPOIB_EXIT( IPOIB_DBG_OID ); -} - - -void -ipoib_cancel_xmit( - IN NDIS_HANDLE adapter_context, - IN PVOID cancel_id ) -{ -/* ipoib_adapter_t* const p_adapter = - (ipoib_adapter_t* const )adapter_context; - - -if 0 - if( p_adapter && p_adapter->p_port ) - { - ipoib_port_cancel_xmit( p_adapter->p_port, cancel_id ); - } -endif -*/ - - UNUSED_PARAM(adapter_context); - UNUSED_PARAM(cancel_id); - - return; //TODO return this functionality - -} - - -static void -__ipoib_ats_reg_cb( - IN ib_reg_svc_rec_t *p_reg_svc_rec ) -{ - ats_reg_t *p_reg; - uint8_t port_num; - - IPOIB_ENTER( IPOIB_DBG_OID ); - - CL_ASSERT( p_reg_svc_rec ); - CL_ASSERT( p_reg_svc_rec->svc_context ); - - p_reg = (ats_reg_t*)p_reg_svc_rec->svc_context; - port_num = p_reg->p_adapter->guids.port_num; - - cl_obj_lock( &p_reg->p_adapter->obj ); - - if( p_reg_svc_rec->req_status == IB_SUCCESS && - !p_reg_svc_rec->resp_status ) - { - IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, - ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Registered IP Address " - "of %d.%d.%d.%d\n", - port_num, - p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET], - p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+1], - p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+2], - p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+3]) ); - } - else if( p_reg_svc_rec->req_status != IB_CANCELED ) - { - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_OID, - ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Failed to register IP Address " - "of %d.%d.%d.%d with error %s\n", - port_num, - p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET], - p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+1], - p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+2], - p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+3], - p_reg->p_adapter->p_ifc->get_err_str( p_reg_svc_rec->resp_status )) ); - p_reg->p_adapter->hung = TRUE; - p_reg->h_reg_svc = NULL; - } - - cl_obj_unlock( &p_reg->p_adapter->obj ); - cl_obj_deref(&p_reg->p_adapter->obj); - - IPOIB_EXIT( IPOIB_DBG_OID ); -} - - -static void -__ipoib_ats_dereg_cb( - IN void *context ) -{ - cl_free( context ); -} - -static NDIS_STATUS -ipoib_pause( - IN NDIS_HANDLE adapter_context, - IN PNDIS_MINIPORT_PAUSE_PARAMETERS pause_parameters) -{ - ipoib_adapter_t *p_adapter; - KLOCK_QUEUE_HANDLE hdl; - - UNREFERENCED_PARAMETER(pause_parameters); - IPOIB_ENTER( IPOIB_DBG_INIT ); -//return NDIS_STATUS_SUCCESS; - CL_ASSERT(adapter_context); - p_adapter = (ipoib_adapter_t*)adapter_context; - CL_ASSERT(p_adapter->ipoib_state == IPOIB_RUNNING); - - KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl ); - p_adapter->ipoib_state = IPOIB_PAUSING; - KeReleaseInStackQueuedSpinLock( &hdl ); - - //TODO: - ipoib_port_resume(p_adapter->p_port,FALSE); -// ASSERT(FALSE); - - KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl ); - p_adapter->ipoib_state = IPOIB_PAUSED; - KeReleaseInStackQueuedSpinLock( &hdl ); - - IPOIB_EXIT( IPOIB_DBG_INIT ); - return NDIS_STATUS_SUCCESS; -} - -static NDIS_STATUS -ipoib_restart( - IN NDIS_HANDLE adapter_context, - IN PNDIS_MINIPORT_RESTART_PARAMETERS restart_parameters) -{ - ipoib_adapter_t *p_adapter; - KLOCK_QUEUE_HANDLE hdl; - PNDIS_RESTART_ATTRIBUTES NdisRestartAttributes; - PNDIS_RESTART_GENERAL_ATTRIBUTES NdisGeneralAttributes; - - IPOIB_ENTER( IPOIB_DBG_INIT ); - p_adapter = (ipoib_adapter_t*)adapter_context; - - NdisRestartAttributes = restart_parameters->RestartAttributes; - - if (NdisRestartAttributes != NULL) - { - CL_ASSERT(NdisRestartAttributes->Oid == OID_GEN_MINIPORT_RESTART_ATTRIBUTES); - NdisGeneralAttributes = (PNDIS_RESTART_GENERAL_ATTRIBUTES)NdisRestartAttributes->Data; - // - // Check to see if we need to change any attributes - } - - KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl ); - p_adapter->ipoib_state = IPOIB_RUNNING; - KeReleaseInStackQueuedSpinLock( &hdl ); - - - IPOIB_EXIT( IPOIB_DBG_INIT ); - return NDIS_STATUS_SUCCESS; -} - -/*++ -Routine Description: - - This function aborts the request pending in the miniport. - -Arguments: - - MiniportAdapterContext Pointer to the adapter structure - RequestId Specify the request to be cancelled. - -Return Value: - ---*/ -static void -ipoib_cancel_oid_request( - IN NDIS_HANDLE adapter_context, - IN PVOID requestId - ) -{ - PNDIS_OID_REQUEST pending_request; - ipoib_adapter_t *p_adapter; - - IPOIB_ENTER( IPOIB_DBG_OID ); - p_adapter = (ipoib_adapter_t*)adapter_context; - - cl_obj_lock( &p_adapter->obj ); - - if ( p_adapter->query_oid.p_pending_oid && - p_adapter->query_oid.p_pending_oid->RequestId == requestId) - { - pending_request = p_adapter->query_oid.p_pending_oid; - p_adapter->query_oid.p_pending_oid = NULL; - p_adapter->pending_query = FALSE; - } - else if(p_adapter->set_oid.p_pending_oid && - p_adapter->set_oid.p_pending_oid->RequestId == requestId) - { - pending_request = p_adapter->set_oid.p_pending_oid; - p_adapter->set_oid.p_pending_oid = NULL; - p_adapter->pending_set = FALSE; - } - else - { - cl_obj_unlock( &p_adapter->obj ); - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("No Pending OID found\n") ); - return; - } - cl_obj_unlock( &p_adapter->obj ); - - NdisMOidRequestComplete(p_adapter->h_adapter, - pending_request, - NDIS_STATUS_REQUEST_ABORTED); - - IPOIB_EXIT( IPOIB_DBG_OID ); -} diff --git a/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_driver.cpp b/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_driver.cpp new file mode 100644 index 00000000..236a81f5 --- /dev/null +++ b/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_driver.cpp @@ -0,0 +1,4570 @@ +/* + * Copyright (c) 2005 SilverStorm Technologies. All rights reserved. + * Copyright (c) 2006 Mellanox Technologies. All rights reserved. + * Portions Copyright (c) 2008 Microsoft 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: ipoib_driver.c 4506 2009-06-23 14:40:54Z xalex $ + */ + +#include "limits.h" +#include "ipoib_driver.h" +#include "ipoib_debug.h" + +#if defined(EVENT_TRACING) +#ifdef offsetof +#undef offsetof +#endif +#include "ipoib_driver.tmh" +#endif + +#include "ipoib_port.h" +#include "ipoib_ibat.h" +#include +#include +#include +#include +#include "ntstrsafe.h" +#include "strsafe.h" +#include + + + +#define MAJOR_DRIVER_VERSION 2 +#define MINOR_DRIVER_VERSION 1 +#if defined(NDIS60_MINIPORT) +#define MAJOR_NDIS_VERSION 6 +#define MINOR_NDIS_VERSION 0 + +#else +#error NDIS Version not defined, try defining NDIS60_MINIPORT +#endif + +PDRIVER_OBJECT g_p_drv_obj; + + +#if 0 +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_NETWORK_LAYER_ADDRESSES, + 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_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 +}; +#endif + +NDIS_OID NICSupportedOidsTest[] = +{ + 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_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_VENDOR_DRIVER_VERSION, + OID_GEN_CURRENT_PACKET_FILTER, + OID_GEN_CURRENT_LOOKAHEAD, + OID_GEN_DRIVER_VERSION, + OID_GEN_MAXIMUM_TOTAL_SIZE, + OID_GEN_MAC_OPTIONS, + OID_GEN_MAXIMUM_SEND_PACKETS, + OID_GEN_XMIT_OK, + OID_GEN_RCV_OK, + OID_GEN_XMIT_ERROR, + OID_GEN_RCV_ERROR, + OID_GEN_RCV_NO_BUFFER, + OID_GEN_RCV_CRC_ERROR, + OID_GEN_TRANSMIT_QUEUE_LENGTH, + OID_802_3_PERMANENT_ADDRESS, + OID_802_3_CURRENT_ADDRESS, + OID_802_3_MULTICAST_LIST, + OID_802_3_MAXIMUM_LIST_SIZE, + OID_802_3_RCV_ERROR_ALIGNMENT, + OID_802_3_XMIT_ONE_COLLISION, + OID_802_3_XMIT_MORE_COLLISIONS, + OID_802_3_XMIT_DEFERRED, + OID_802_3_XMIT_MAX_COLLISIONS, + OID_802_3_RCV_OVERRUN, + OID_802_3_XMIT_UNDERRUN, + OID_802_3_XMIT_HEARTBEAT_FAILURE, + OID_802_3_XMIT_TIMES_CRS_LOST, + OID_802_3_XMIT_LATE_COLLISIONS, + +#if !BUILD_W2K + OID_GEN_PHYSICAL_MEDIUM, +#endif + + OID_TCP_TASK_OFFLOAD, + +/* powermanagement */ + + OID_PNP_CAPABILITIES, + OID_PNP_SET_POWER, + OID_PNP_QUERY_POWER, + OID_PNP_ADD_WAKE_UP_PATTERN, + OID_PNP_REMOVE_WAKE_UP_PATTERN, + OID_PNP_ENABLE_WAKE_UP, + + +/* custom oid WMI support */ +// OID_CUSTOM_PERF_COUNTERS, + // OID_CUSTOM_STRING, + + OID_GEN_RECEIVE_SCALE_CAPABILITIES, + OID_GEN_RECEIVE_SCALE_PARAMETERS, + +// +// new and required for NDIS 6 miniports +// + OID_GEN_LINK_PARAMETERS, + OID_GEN_INTERRUPT_MODERATION, + OID_GEN_STATISTICS, + +/* Offload */ + OID_TCP_OFFLOAD_CURRENT_CONFIG, + OID_TCP_OFFLOAD_PARAMETERS, + OID_TCP_OFFLOAD_HARDWARE_CAPABILITIES, + OID_OFFLOAD_ENCAPSULATION, + +/* Header - Data seperation */ + // OID_GEN_HD_SPLIT_PARAMETERS, + // OID_GEN_HD_SPLIT_CURRENT_CONFIG, + +/* VLAN */ + // OID_ADD_VALN_ID, + // OID_DELETE_VLAN_ID, + +/* Set MAC */ + // OID_SET_MAC_ADDRESS + +}; + +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_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_VENDOR_DRIVER_VERSION, + OID_GEN_CURRENT_PACKET_FILTER, + OID_GEN_CURRENT_LOOKAHEAD, + OID_GEN_DRIVER_VERSION, + OID_GEN_MAXIMUM_TOTAL_SIZE, + OID_GEN_MAC_OPTIONS, + OID_GEN_MAXIMUM_SEND_PACKETS, + OID_GEN_XMIT_OK, + OID_GEN_RCV_OK, + OID_GEN_XMIT_ERROR, + OID_GEN_RCV_ERROR, + OID_GEN_RCV_NO_BUFFER, + OID_GEN_RCV_CRC_ERROR, + OID_GEN_TRANSMIT_QUEUE_LENGTH, + OID_802_3_PERMANENT_ADDRESS, + OID_802_3_CURRENT_ADDRESS, + OID_802_3_MULTICAST_LIST, + OID_802_3_MAXIMUM_LIST_SIZE, + OID_802_3_RCV_ERROR_ALIGNMENT, + OID_802_3_XMIT_ONE_COLLISION, + OID_802_3_XMIT_MORE_COLLISIONS, + OID_802_3_XMIT_DEFERRED, + OID_802_3_XMIT_MAX_COLLISIONS, + OID_802_3_RCV_OVERRUN, + OID_802_3_XMIT_UNDERRUN, + OID_802_3_XMIT_HEARTBEAT_FAILURE, + OID_802_3_XMIT_TIMES_CRS_LOST, + OID_802_3_XMIT_LATE_COLLISIONS, + +#if !BUILD_W2K + OID_GEN_PHYSICAL_MEDIUM, +#endif + + OID_TCP_TASK_OFFLOAD, + +/* powermanagement */ + + OID_PNP_CAPABILITIES, + OID_PNP_SET_POWER, + OID_PNP_QUERY_POWER, + OID_PNP_ADD_WAKE_UP_PATTERN, + OID_PNP_REMOVE_WAKE_UP_PATTERN, + OID_PNP_ENABLE_WAKE_UP, + +#if 0 +/* custom oid WMI support */ + OID_CUSTOM_PERF_COUNTERS, + OID_CUSTOM_STRING, +#endif + + OID_GEN_RECEIVE_SCALE_CAPABILITIES, + OID_GEN_RECEIVE_SCALE_PARAMETERS, + + +// +// new and required for NDIS 6 miniports +// + OID_GEN_LINK_PARAMETERS, + OID_GEN_INTERRUPT_MODERATION, + OID_GEN_STATISTICS, + +/* Offload */ + OID_TCP_OFFLOAD_CURRENT_CONFIG, + OID_TCP_OFFLOAD_PARAMETERS, + OID_TCP_OFFLOAD_HARDWARE_CAPABILITIES, + OID_OFFLOAD_ENCAPSULATION, + +#if 0 + +/* Header - Data seperation */ + OID_GEN_HD_SPLIT_PARAMETERS, + OID_GEN_HD_SPLIT_CURRENT_CONFIG, + +/* VLAN */ + OID_ADD_VALN_ID, + OID_DELETE_VLAN_ID, + + +/* Set MAC */ + OID_SET_MAC_ADDRESS +#endif + +}; + +static const unsigned char VENDOR_ID[] = {0x00, 0x06, 0x6A, 0x00}; + +#define VENDOR_DESCRIPTION "Internet Protocol over InfiniBand" + +#define IB_INFINITE_SERVICE_LEASE 0xFFFFFFFF + +//The mask is 8 bit and can't contain more than 6 non-zero bits +#define MAX_GUID_MAX 0xFC + + +/* Global driver debug level */ +uint32_t g_ipoib_dbg_level = TRACE_LEVEL_ERROR; +uint32_t g_ipoib_dbg_flags = 0x00000fff; +ipoib_globals_t g_ipoib = {0}; +NDIS_HANDLE g_IpoibMiniportDriverHandle = NULL; +NDIS_HANDLE g_IpoibDriverContext = NULL; + + + +typedef struct _IPOIB_REG_ENTRY +{ + NDIS_STRING RegName; // variable name text + BOOLEAN bRequired; // 1 -> required, 0 -> optional + UINT FieldOffset; // offset in parent struct + UINT FieldSize; // size (in bytes) of the field + UINT Default; // default value to use + UINT Min; // minimum value allowed + UINT Max; // maximum value allowed +} IPOIB_REG_ENTRY, *PIPOIB_REG_ENTRY; + +IPOIB_REG_ENTRY HCARegTable[] = { + // reg value name If Required Offset in parentr struct Field size Default Min Max + {NDIS_STRING_CONST("GUIDMask"), 0, IPOIB_OFFSET(guid_mask), IPOIB_SIZE(guid_mask), 0, 0, MAX_GUID_MAX}, + /* GUIDMask should be the first element */ + {NDIS_STRING_CONST("RqDepth"), 1, IPOIB_OFFSET(rq_depth), IPOIB_SIZE(rq_depth), 512, 128, 1024}, + {NDIS_STRING_CONST("RqLowWatermark"), 0, IPOIB_OFFSET(rq_low_watermark), IPOIB_SIZE(rq_low_watermark), 4, 2, 8}, + {NDIS_STRING_CONST("SqDepth"), 1, IPOIB_OFFSET(sq_depth), IPOIB_SIZE(sq_depth), 512, 128, 1024}, + {NDIS_STRING_CONST("SendChksum"), 1, IPOIB_OFFSET(send_chksum_offload), IPOIB_SIZE(send_chksum_offload),CSUM_ENABLED,CSUM_DISABLED,CSUM_BYPASS}, + {NDIS_STRING_CONST("RecvChksum"), 1, IPOIB_OFFSET(recv_chksum_offload), IPOIB_SIZE(recv_chksum_offload),CSUM_ENABLED,CSUM_DISABLED,CSUM_BYPASS}, + {NDIS_STRING_CONST("SaTimeout"), 1, IPOIB_OFFSET(sa_timeout), IPOIB_SIZE(sa_timeout), 1000, 250, UINT_MAX}, + {NDIS_STRING_CONST("SaRetries"), 1, IPOIB_OFFSET(sa_retry_cnt), IPOIB_SIZE(sa_retry_cnt), 10, 1, UINT_MAX}, + {NDIS_STRING_CONST("RecvRatio"), 1, IPOIB_OFFSET(recv_pool_ratio), IPOIB_SIZE(recv_pool_ratio), 1, 1, 10}, + {NDIS_STRING_CONST("PayloadMtu"), 1, IPOIB_OFFSET(payload_mtu), IPOIB_SIZE(payload_mtu), 2044, 512, MAX_UD_PAYLOAD_MTU}, + {NDIS_STRING_CONST("lso"), 0, IPOIB_OFFSET(lso), IPOIB_SIZE(lso), 0, 0, 1}, + {NDIS_STRING_CONST("MCLeaveRescan"), 1, IPOIB_OFFSET(mc_leave_rescan), IPOIB_SIZE(mc_leave_rescan), 260, 1, 3600}, + {NDIS_STRING_CONST("BCJoinRetry"), 1, IPOIB_OFFSET(bc_join_retry), IPOIB_SIZE(bc_join_retry), 50, 0, 1000}, + {NDIS_STRING_CONST("CmEnabled"), 0, IPOIB_OFFSET(cm_enabled), IPOIB_SIZE(cm_enabled), FALSE, FALSE, TRUE}, + {NDIS_STRING_CONST("CmPayloadMtu"), 1, IPOIB_OFFSET(cm_payload_mtu), IPOIB_SIZE(cm_payload_mtu), MAX_CM_PAYLOAD_MTU, 512, MAX_CM_PAYLOAD_MTU} + +}; + +#define IPOIB_NUM_REG_PARAMS (sizeof (HCARegTable) / sizeof(IPOIB_REG_ENTRY)) + + +void +ipoib_create_log( + NDIS_HANDLE h_adapter, + UINT ind, + ULONG eventLogMsgId) + +{ +#define cMaxStrLen 40 +#define cArrLen 3 + + PWCHAR logMsgArray[cArrLen]; + WCHAR strVal[cMaxStrLen]; + NDIS_STRING AdapterInstanceName; + + IPOIB_INIT_NDIS_STRING(&AdapterInstanceName); + if (NdisMQueryAdapterInstanceName(&AdapterInstanceName, h_adapter)!= NDIS_STATUS_SUCCESS ){ + ASSERT(FALSE); + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR,IPOIB_DBG_ERROR, ("[IPoIB] Init:Failed to retreive adapter name.\n")); + return; + } + logMsgArray[0] = AdapterInstanceName.Buffer; + + if (RtlStringCbPrintfW(strVal, sizeof(strVal), L"0x%x", HCARegTable[ind].Default) != STATUS_SUCCESS) { + ASSERT(FALSE); + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR,IPOIB_DBG_ERROR, + ("[IPoIB] Init: Problem copying string value: exiting\n")); + return; + } + + logMsgArray[0] = AdapterInstanceName.Buffer; + logMsgArray[1] = HCARegTable[ind].RegName.Buffer; + logMsgArray[2] = strVal; + + NdisWriteEventLogEntry(g_p_drv_obj, eventLogMsgId, 0, cArrLen, &logMsgArray, 0, NULL); + +} + + +extern "C" +NTSTATUS +DriverEntry( + IN PDRIVER_OBJECT p_drv_obj, + IN PUNICODE_STRING p_reg_path ); + +VOID +ipoib_unload( + IN PDRIVER_OBJECT p_drv_obj ); + +NDIS_STATUS +ipoib_initialize_ex( + IN NDIS_HANDLE h_adapter, + IN NDIS_HANDLE config_context, + IN PNDIS_MINIPORT_INIT_PARAMETERS MiniportInitParameters); + +NDIS_STATUS +MPInitializeTest( + IN NDIS_HANDLE MiniportAdapterHandle, + IN NDIS_HANDLE MiniportDriverContext, + IN PNDIS_MINIPORT_INIT_PARAMETERS MiniportInitParameters + ); + + + +BOOLEAN +ipoib_check_for_hang( + IN NDIS_HANDLE adapter_context ); + +void +ipoib_halt_ex( + IN NDIS_HANDLE adapter_context, + IN NDIS_HALT_ACTION HaltAction); + +NDIS_STATUS +ipoib_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 +ipoib_reset( + IN NDIS_HANDLE adapter_context, + OUT PBOOLEAN p_addr_reset); + +NDIS_STATUS +ipoib_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 ); + +//NDIS60 +void +ipoib_send_net_buffer_list( + IN NDIS_HANDLE adapter_context, + IN PNET_BUFFER_LIST net_buffer_list, + IN NDIS_PORT_NUMBER port_num, + IN ULONG send_flags); + +void +ipoib_pnp_notify( + IN NDIS_HANDLE adapter_context, + IN PNET_DEVICE_PNP_EVENT pnp_event); + +VOID +ipoib_shutdown_ex( + IN NDIS_HANDLE adapter_context, + IN NDIS_SHUTDOWN_ACTION shutdown_action); + + +void +ipoib_cancel_xmit( + IN NDIS_HANDLE adapter_context, + IN PVOID cancel_id ); + + +static void +ipoib_complete_query( + IN ipoib_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 +__ipoib_set_net_addr( + IN ipoib_adapter_t * p_adapter, + IN PVOID info_buf, + IN ULONG info_buf_len, + OUT PULONG p_bytes_read, + OUT PULONG p_bytes_needed ); + +static NDIS_STATUS +__ipoib_get_tcp_task_offload( + IN ipoib_adapter_t* p_adapter, + OUT pending_oid_t *pNdisRequest); + +static void +__ipoib_ats_reg_cb( + IN ib_reg_svc_rec_t *p_reg_svc_rec ); + +static void +__ipoib_ats_dereg_cb( + IN void *context ); + +static NTSTATUS +__ipoib_read_registry( + IN UNICODE_STRING* const p_registry_path ); + +static NDIS_STATUS +ipoib_set_options( + IN NDIS_HANDLE NdisMiniportDriverHandle, + IN NDIS_HANDLE MiniportDriverContext); + +static NDIS_STATUS +ipoib_oid_handler( + IN NDIS_HANDLE adapter_context, + IN PNDIS_OID_REQUEST pNdisRequest); + +static void +ipoib_cancel_oid_request( + IN NDIS_HANDLE adapter_context, + IN PVOID requestId); + +static NDIS_STATUS +ipoib_pause( + IN NDIS_HANDLE adapter_context, + IN PNDIS_MINIPORT_PAUSE_PARAMETERS pause_parameters); + +static NDIS_STATUS +ipoib_restart( + IN NDIS_HANDLE adapter_context, + IN PNDIS_MINIPORT_RESTART_PARAMETERS restart_parameters); + + + +//! Standard Windows Device Driver Entry Point +/*! DriverEntry is the first routine called after a driver is loaded, and +is responsible for initializing the driver. On W2k this occurs when the PnP +Manager matched a PnP ID to one in an INF file that references this driver. +Any not success return value will cause the driver to fail to load. +IRQL = PASSIVE_LEVEL + +@param p_drv_obj Pointer to Driver Object for this device driver +@param 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 +*/ +extern "C" +NTSTATUS +DriverEntry( + IN PDRIVER_OBJECT p_drv_obj, + IN PUNICODE_STRING p_registry_path ) +{ + NDIS_STATUS status; + NDIS_MINIPORT_DRIVER_CHARACTERISTICS characteristics; + + IPOIB_ENTER( IPOIB_DBG_INIT ); + g_p_drv_obj = p_drv_obj; + +#ifdef _DEBUG_ + PAGED_CODE(); +#endif +#if defined(EVENT_TRACING) + WPP_INIT_TRACING(p_drv_obj, p_registry_path); +#endif + status = CL_INIT; + if( !NT_SUCCESS( status ) ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("cl_init failed.\n") ); + return status; + } + + __ipoib_read_registry(p_registry_path); + + KeInitializeSpinLock( &g_ipoib.lock ); + cl_qlist_init( &g_ipoib.adapter_list ); + + NdisZeroMemory(&characteristics, sizeof(characteristics)); + + characteristics.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_DRIVER_CHARACTERISTICS, + characteristics.Header.Size = sizeof(NDIS_MINIPORT_DRIVER_CHARACTERISTICS); + characteristics.Header.Revision = NDIS_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_1; + + characteristics.MajorNdisVersion = MAJOR_NDIS_VERSION; + characteristics.MinorNdisVersion = MINOR_NDIS_VERSION; + characteristics.MajorDriverVersion = MAJOR_DRIVER_VERSION; + characteristics.MinorDriverVersion = MINOR_DRIVER_VERSION; + + + characteristics.CheckForHangHandlerEx = ipoib_check_for_hang; + characteristics.HaltHandlerEx = ipoib_halt_ex; + characteristics.InitializeHandlerEx = ipoib_initialize_ex;// MPInitializeTest + characteristics.OidRequestHandler = ipoib_oid_handler; + characteristics.CancelOidRequestHandler = ipoib_cancel_oid_request; + characteristics.ResetHandlerEx = ipoib_reset; + characteristics.DevicePnPEventNotifyHandler = ipoib_pnp_notify; + characteristics.ReturnNetBufferListsHandler = ipoib_return_net_buffer_list; + characteristics.SendNetBufferListsHandler = ipoib_send_net_buffer_list; + + characteristics.SetOptionsHandler = ipoib_set_options; + characteristics.PauseHandler = ipoib_pause; + characteristics.RestartHandler = ipoib_restart; + characteristics.UnloadHandler = ipoib_unload; + characteristics.CancelSendHandler = ipoib_cancel_xmit; + characteristics.ShutdownHandlerEx = ipoib_shutdown_ex; + + + +//TODO NDIS60 set g_ prefix to global variables + status = NdisMRegisterMiniportDriver( + p_drv_obj, p_registry_path,(PNDIS_HANDLE)&g_IpoibDriverContext, &characteristics,&g_IpoibMiniportDriverHandle ); + if( status != NDIS_STATUS_SUCCESS ) + { + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("NdisMRegisterMiniportDriver failed with status of %d\n", status) ); + CL_DEINIT; + } + + IPOIB_EXIT( IPOIB_DBG_INIT ); + return status; +} + +static NDIS_STATUS +ipoib_set_options( + IN NDIS_HANDLE NdisMiniportDriverHandle, + IN NDIS_HANDLE MiniportDriverContext + ) +{ + IPOIB_ENTER( IPOIB_DBG_INIT ); + + UNREFERENCED_PARAMETER(NdisMiniportDriverHandle); + UNREFERENCED_PARAMETER(MiniportDriverContext); + + IPOIB_EXIT( IPOIB_DBG_INIT ); + return NDIS_STATUS_SUCCESS; +} + +static NTSTATUS +__ipoib_read_registry( + IN UNICODE_STRING* const p_registry_path ) +{ + NTSTATUS status; + /* Remember the terminating entry in the table below. */ + RTL_QUERY_REGISTRY_TABLE table[4]; + UNICODE_STRING param_path; + + IPOIB_ENTER( IPOIB_DBG_INIT ); + RtlInitUnicodeString( ¶m_path, NULL ); + param_path.MaximumLength = p_registry_path->Length + + sizeof(L"\\Parameters"); + param_path.Buffer = (PWCH) cl_zalloc( param_path.MaximumLength ); + if( !param_path.Buffer ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed to allocate parameters path buffer.\n") ); + return STATUS_INSUFFICIENT_RESOURCES; + } + + RtlAppendUnicodeStringToString( ¶m_path, p_registry_path ); + RtlAppendUnicodeToString( ¶m_path, L"\\Parameters" ); + + /* + * 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; + table[0].Name = L"DebugLevel"; + table[0].EntryContext = &g_ipoib_dbg_level; + table[0].DefaultType = REG_DWORD; + table[0].DefaultData = &g_ipoib_dbg_level; + table[0].DefaultLength = sizeof(ULONG); + + table[1].Flags = RTL_QUERY_REGISTRY_DIRECT; + table[1].Name = L"DebugFlags"; + table[1].EntryContext = &g_ipoib_dbg_flags; + table[1].DefaultType = REG_DWORD; + table[1].DefaultData = &g_ipoib_dbg_flags; + table[1].DefaultLength = sizeof(ULONG); + + table[2].Flags = RTL_QUERY_REGISTRY_DIRECT; + table[2].Name = L"bypass_check_bcast_rate"; + table[2].EntryContext = &g_ipoib.bypass_check_bcast_rate; + table[2].DefaultType = REG_DWORD; + table[2].DefaultData = &g_ipoib.bypass_check_bcast_rate; + table[2].DefaultLength = sizeof(ULONG); + + /* Have at it! */ + status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE, + param_path.Buffer, table, NULL, NULL ); + + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("debug level %d debug flags 0x%.8x\n", + g_ipoib_dbg_level, + g_ipoib_dbg_flags)); + +#if DBG + if( g_ipoib_dbg_flags & IPOIB_DBG_ERR ) + g_ipoib_dbg_flags |= CL_DBG_ERROR; +#endif + + cl_free( param_path.Buffer ); + IPOIB_EXIT( IPOIB_DBG_INIT ); + return status; +} + + +VOID +ipoib_unload( + IN PDRIVER_OBJECT p_drv_obj ) +{ + IPOIB_ENTER( IPOIB_DBG_INIT ); + UNREFERENCED_PARAMETER(p_drv_obj); + #if defined(EVENT_TRACING) + WPP_CLEANUP(p_drv_obj); + #endif + //NDIS6.0 + NdisMDeregisterMiniportDriver(g_IpoibMiniportDriverHandle); + UNREFERENCED_PARAMETER( p_drv_obj ); + CL_DEINIT; + IPOIB_EXIT( IPOIB_DBG_INIT ); +} + + + +NDIS_STATUS +ipoib_get_adapter_params( + IN OUT ipoib_adapter_t *p_adapter, + OUT PUCHAR *p_mac, + OUT UINT *p_len) +{ + NDIS_STATUS status; + NDIS_HANDLE h_config; + NDIS_CONFIGURATION_OBJECT config_obj; + NDIS_CONFIGURATION_PARAMETER *p_param; + UINT value; + PIPOIB_REG_ENTRY pRegEntry; + UINT i; + PUCHAR structPointer; + + int sq_depth_step = 128; + + IPOIB_ENTER( IPOIB_DBG_INIT ); + + config_obj.Header.Type = NDIS_OBJECT_TYPE_CONFIGURATION_OBJECT; + config_obj.Header.Revision = NDIS_CONFIGURATION_OBJECT_REVISION_1; + config_obj.Header.Size = sizeof(NDIS_CONFIGURATION_OBJECT); + config_obj.NdisHandle = p_adapter->h_adapter; + config_obj.Flags = 0; + + status = NdisOpenConfigurationEx( &config_obj, &h_config); + if( status != NDIS_STATUS_SUCCESS ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("NdisOpenConfigurationEx returned 0x%.8x\n", status) ); + return status; + } + + // read all the registry values + for (i = 0, pRegEntry = HCARegTable; i < IPOIB_NUM_REG_PARAMS; ++i) + { + // initialize pointer to appropriate place inside 'params' + structPointer = (PUCHAR) &p_adapter->params + pRegEntry[i].FieldOffset; + + // Get the configuration value for a specific parameter. Under NT the + // parameters are all read in as DWORDs. + NdisReadConfiguration( + &status, + &p_param, + h_config, + &pRegEntry[i].RegName, + NdisParameterInteger); + + // If the parameter was present, then check its value for validity. + if (status == NDIS_STATUS_SUCCESS) + { + // Check that param value is not too small or too large + if (p_param->ParameterData.IntegerData < pRegEntry[i].Min || + p_param->ParameterData.IntegerData > pRegEntry[i].Max) + { + value = pRegEntry[i].Default; + ipoib_create_log(p_adapter->h_adapter, i, EVENT_IPOIB_WRONG_PARAMETER_WRN); + IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_INIT, ("Read configuration.Registry %S value is out of range, setting default value= 0x%x\n", pRegEntry[i].RegName.Buffer, value)); + + } + else + { + value = p_param->ParameterData.IntegerData; + IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_INIT, ("Read configuration. Registry %S, Value= 0x%x\n", pRegEntry[i].RegName.Buffer, value)); + } + } + + else + { + value = pRegEntry[i].Default; + status = NDIS_STATUS_SUCCESS; + if (pRegEntry[i].bRequired) + { + ipoib_create_log(p_adapter->h_adapter, i, EVENT_IPOIB_WRONG_PARAMETER_ERR); + IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_INIT, ("Read configuration.Registry %S value not found, setting default value= 0x%x\n", pRegEntry[i].RegName.Buffer, value)); + } + else + { + ipoib_create_log(p_adapter->h_adapter, i, EVENT_IPOIB_WRONG_PARAMETER_INFO); + IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_INIT, ("Read configuration. Registry %S value not found, Value= 0x%x\n", pRegEntry[i].RegName.Buffer, value)); + } + + } + // + // Store the value in the adapter structure. + // + switch(pRegEntry[i].FieldSize) + { + case 1: + *((PUCHAR) structPointer) = (UCHAR) value; + break; + + case 2: + *((PUSHORT) structPointer) = (USHORT) value; + break; + + case 4: + *((PULONG) structPointer) = (ULONG) value; + break; + + default: + IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, ("Bogus field size %d\n", pRegEntry[i].FieldSize)); + break; + } + } + + // Send queue depth needs to be a power of two + //static const INT sq_depth_step = 128; + + if (p_adapter->params.sq_depth % sq_depth_step) { + static const c_sq_ind = 2; + p_adapter->params.sq_depth = sq_depth_step *( + p_adapter->params.sq_depth / sq_depth_step + !!( (p_adapter->params.sq_depth % sq_depth_step) > (sq_depth_step/2) )); + ipoib_create_log(p_adapter->h_adapter, c_sq_ind, EVENT_IPOIB_WRONG_PARAMETER_WRN); + IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_INIT, ("SQ DEPTH value was rounded to the closest acceptable value of 0x%x\n", p_adapter->params.sq_depth )); + + } + + + // Adjusting the low watermark parameter + p_adapter->params.rq_low_watermark = + p_adapter->params.rq_depth / p_adapter->params.rq_low_watermark; + + /* disable CM if LSO is active */ + if( p_adapter->params.cm_enabled ) + { + p_adapter->params.cm_enabled = !p_adapter->params.lso; + if( !p_adapter->params.cm_enabled ) + { + NdisWriteErrorLogEntry( p_adapter->h_adapter, + EVENT_IPOIB_CONNECTED_MODE_ERR, 1, 0xbadc0de0 ); + } + } + + if( p_adapter->params.cm_enabled ) + { + p_adapter->params.cm_xfer_block_size = + (sizeof(eth_hdr_t) + p_adapter->params.cm_payload_mtu); + } + + p_adapter->params.xfer_block_size = + (sizeof(eth_hdr_t) + p_adapter->params.payload_mtu); + + NdisReadNetworkAddress( &status, (PVOID *) p_mac, p_len, h_config ); + + NdisCloseConfiguration( h_config ); + + IPOIB_EXIT( IPOIB_DBG_INIT ); + return NDIS_STATUS_SUCCESS; +} + + +NDIS_STATUS +ipoib_get_adapter_guids( + IN NDIS_HANDLE* const h_adapter, + IN OUT ipoib_adapter_t *p_adapter ) +{ + NTSTATUS status; + ib_al_ifc_data_t data; + IO_STACK_LOCATION io_stack, *p_fwd_io_stack; + DEVICE_OBJECT *p_pdo; + IRP *p_irp; + KEVENT event; + IO_STATUS_BLOCK io_status; + + IPOIB_ENTER( IPOIB_DBG_INIT ); + + NdisMGetDeviceProperty( h_adapter, &p_pdo, NULL, NULL, NULL, NULL ); + + /* Query for our interface */ + data.size = sizeof(ipoib_ifc_data_t); + data.version = IPOIB_INTERFACE_DATA_VERSION; + data.type = &GUID_IPOIB_INTERFACE_DATA; + data.p_data = &p_adapter->guids; + + 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->p_ifc; + io_stack.Parameters.QueryInterface.InterfaceSpecificData = &data; + io_stack.Parameters.QueryInterface.InterfaceType = + &GUID_IB_AL_INTERFACE; + + KeInitializeEvent( &event, NotificationEvent, FALSE ); + + /* Build the IRP for the HCA. */ + p_irp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP, p_pdo, + NULL, 0, NULL, &event, &io_status ); + if( !p_irp ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed to allocate query interface IRP.\n") ); + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* Copy the request query parameters. */ + p_fwd_io_stack = IoGetNextIrpStackLocation( p_irp ); + p_fwd_io_stack->MinorFunction = IRP_MN_QUERY_INTERFACE; + p_fwd_io_stack->Parameters.QueryInterface = + io_stack.Parameters.QueryInterface; + p_irp->IoStatus.Status = STATUS_NOT_SUPPORTED; + + /* Send the IRP. */ + status = IoCallDriver( p_pdo, p_irp ); + if( status == STATUS_PENDING ) + { + KeWaitForSingleObject( &event, Executive, KernelMode, + FALSE, NULL ); + status = io_status.Status; + } + + if( !NT_SUCCESS( status ) ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Query interface for IPOIB 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. + */ + if (p_adapter->p_ifc) + p_adapter->p_ifc->wdm.InterfaceDereference( + p_adapter->p_ifc->wdm.Context ); + IPOIB_EXIT( IPOIB_DBG_INIT ); + return NDIS_STATUS_SUCCESS; +} + + +//! 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_adapter 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 +*/ + +/*void foo1(int i) +{ + char temp[5200]; + if (i ==0) return; + cl_msg_out("i = %d\n", i); + foo1(i-1); + +}*/ + +NDIS_STATUS +SetDeviceRegistrationAttributes( + ipoib_adapter_t *p_adapter, + NDIS_HANDLE h_adapter + ) +{ + NDIS_MINIPORT_ADD_DEVICE_REGISTRATION_ATTRIBUTES atr; + NTSTATUS Status; + + NdisZeroMemory(&atr, sizeof(NDIS_MINIPORT_ADD_DEVICE_REGISTRATION_ATTRIBUTES)); + + // + // setting registration attributes + // + atr.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADD_DEVICE_REGISTRATION_ATTRIBUTES; + atr.Header.Revision = NDIS_MINIPORT_ADD_DEVICE_REGISTRATION_ATTRIBUTES_REVISION_1; + atr.Header.Size = NDIS_SIZEOF_MINIPORT_ADD_DEVICE_REGISTRATION_ATTRIBUTES_REVISION_1; + + + atr.MiniportAddDeviceContext = (NDIS_HANDLE)p_adapter; + atr.Flags = 0; + + Status = NdisMSetMiniportAttributes(h_adapter, + (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&atr); + + return Status; +} + +//NDIS 6.1 +#if 0 +NDIS_STATUS +SetHardwareAssistAttributes( + ipoib_adapter_t *p_adapter, + NDIS_HANDLE h_adapter + ) +{ + NDIS_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES atr; + NTSTATUS Status; + + NdisZeroMemory(&atr, sizeof(NDIS_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES)); + + // + // setting registration attributes + // + atr.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES; + atr.Header.Revision = NDIS_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES_REVISION_1; + atr.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES_REVISION_1; + + NDIS_HD_SPLIT_ATTRIBUTES nhsa; + NdisZeroMemory(&nhsa, sizeof(nhsa)); + + nhsa.Header.Type = NDIS_OBJECT_TYPE_HD_SPLIT_ATTRIBUTES; + nhsa.Header.Revision = NDIS_OFFLOAD_REVISION_1; + nhsa.Header.Size = NDIS_SIZEOF_HD_SPLIT_ATTRIBUTES_REVISION_1; + + // BUGBUG: We are just cheating here ... + nhsa.HardwareCapabilities = NDIS_HD_SPLIT_CAPS_SUPPORTS_HEADER_DATA_SPLIT; +#if 0 + ... Only supported on B0 + + NDIS_HD_SPLIT_CAPS_SUPPORTS_IPV4_OPTIONS | + NDIS_HD_SPLIT_CAPS_SUPPORTS_IPV6_EXTENSION_HEADERS | + NDIS_HD_SPLIT_CAPS_SUPPORTS_TCP_OPTIONS; +#endif + + // The bellow should be left zero + if (pPort->Config.HeaderDataSplit) { + nhsa.CurrentCapabilities = NDIS_HD_SPLIT_CAPS_SUPPORTS_HEADER_DATA_SPLIT; + } else { + nhsa.CurrentCapabilities = 0; + } + + nhsa.HDSplitFlags = 0; + nhsa.BackfillSize = 0; + nhsa.MaxHeaderSize = 0; + + atr.HDSplitAttributes = &nhsa; + + Status = NdisMSetMiniportAttributes(h_adapter, + (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&atr); + + if (nhsa.HDSplitFlags & NDIS_HD_SPLIT_ENABLE_HEADER_DATA_SPLIT) { + ASSERT(pPort->Config.HeaderDataSplit == TRUE); + pPort->Config.HeaderDataSplit = TRUE; + } + else { + ASSERT(pPort->Config.HeaderDataSplit == FALSE); + pPort->Config.HeaderDataSplit = FALSE; + } + + return Status; +} +#endif + +/*++ +Routine Description: + the routine sets attributes that are associated with a miniport adapter. + +Arguments: + pPort - Pointer to port object + +Return Value: + NDIS_STATUS + +Note: + Should be called in PASSIVE_LEVEL + +--*/ +NDIS_STATUS +SetAdapterRegistrationAttributes( + ipoib_adapter_t *p_adapter, + NDIS_HANDLE h_adapter + ) + { + NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES atr; + NTSTATUS Status; + + NdisZeroMemory(&atr, sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES)); + + /* setting registration attributes */ + + atr.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES; + atr.Header.Revision = NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1; + atr.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1; + //TODO NDIS60 Port or adapter + atr.MiniportAdapterContext = (NDIS_HANDLE)p_adapter; //(NDIS_HANDLE)pPort->p_adapter; + atr.AttributeFlags = NDIS_MINIPORT_ATTRIBUTES_BUS_MASTER; + atr.CheckForHangTimeInSeconds = 10; + atr.InterfaceType = NdisInterfacePci ; // ???? UH + //TODO NDIS60 PNP or PCI ? + //RegistrationAttributes.InterfaceType = NdisInterfacePNPBus; + + Status = NdisMSetMiniportAttributes(h_adapter, + (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&atr); + + return Status; +} + + +/*++ +Routine Description: + the routine sets generic attributes that are associated with a miniport + adapter. + +Arguments: + pPort - Pointer to port object + +Return Value: + NDIS_STATUS + +Note: + Should be called in PASSIVE_LEVEL + +--*/ +NDIS_STATUS +SetGenericAttributes( + ipoib_adapter_t *p_adapter, + NDIS_HANDLE h_adapter + ) +{ + NDIS_STATUS Status; + + NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES gat; + NdisZeroMemory(&gat, sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES)); + + /* set up generic attributes */ + + gat.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES; + gat.Header.Revision = NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1; + gat.Header.Size = sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES); + + gat.MediaType = NdisMedium802_3; + gat.MaxXmitLinkSpeed = IPOIB_MEDIA_MAX_SPEED; + gat.MaxRcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED; + gat.XmitLinkSpeed = IPOIB_MEDIA_MAX_SPEED; //TODO NDIS60 NDIS_LINK_SPEED_UNKNOWN + gat.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED; // TODO NDIS60 NDIS_LINK_SPEED_UNKNOWN ??? + + gat.MediaConnectState = MediaConnectStateConnected; //TODO NDIS60 Check the current state + gat.MediaDuplexState = MediaDuplexStateFull; + + gat.MtuSize = MAX_IB_MTU; + gat.LookaheadSize = MAX_XFER_BLOCK_SIZE; + gat.MacOptions = 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; //TODO NDIS60 + // DT: Enable for Header Data Split WHQL + // | NDIS_MAC_OPTION_8021Q_VLAN; + + gat.SupportedPacketFilters = NDIS_PACKET_TYPE_DIRECTED | + NDIS_PACKET_TYPE_MULTICAST | + //NDIS_PACKET_TYPE_ALL_MULTICAST | + NDIS_PACKET_TYPE_BROADCAST; + + gat.MaxMulticastListSize = MAX_MCAST; + + gat.MacAddressLength = HW_ADDR_LEN; + + NdisMoveMemory(gat.PermanentMacAddress, + p_adapter->mac.addr, + HW_ADDR_LEN); + + NdisMoveMemory(gat.CurrentMacAddress, + p_adapter->params.conf_mac.addr, + HW_ADDR_LEN); + + + gat.PhysicalMediumType = NdisPhysicalMedium802_3; + gat.AccessType = NET_IF_ACCESS_BROADCAST; + + gat.SupportedOidList = (PNDIS_OID)SUPPORTED_OIDS; + gat.SupportedOidListLength = sizeof(SUPPORTED_OIDS); + + + gat.DirectionType = NET_IF_DIRECTION_SENDRECEIVE; + gat.ConnectionType = NET_IF_CONNECTION_DEDICATED; + gat.IfType = IF_TYPE_ETHERNET_CSMACD; + gat.IfConnectorPresent = TRUE; + //TODO NDIS60 This value is absent for ETH driver + gat.AccessType = NET_IF_ACCESS_BROADCAST; // NET_IF_ACCESS_BROADCAST for a typical ethernet adapter + + + //TODO NDIS60 is it possible to reduce unsupported statistics + gat.SupportedStatistics = + NDIS_STATISTICS_XMIT_OK_SUPPORTED | + NDIS_STATISTICS_RCV_OK_SUPPORTED | + NDIS_STATISTICS_XMIT_ERROR_SUPPORTED | + NDIS_STATISTICS_RCV_ERROR_SUPPORTED | + NDIS_STATISTICS_RCV_CRC_ERROR_SUPPORTED | + NDIS_STATISTICS_RCV_NO_BUFFER_SUPPORTED | + NDIS_STATISTICS_TRANSMIT_QUEUE_LENGTH_SUPPORTED; + + //SupportedStatistics = NDIS_STATISTICS_XMIT_OK_SUPPORTED | + // NDIS_STATISTICS_GEN_STATISTICS_SUPPORTED; + + + // + // Set power management capabilities + // + gat.PowerManagementCapabilities = NULL; +#if 0 + NDIS_PNP_CAPABILITIES PowerManagementCapabilities; + NdisZeroMemory(&PowerManagementCapabilities, sizeof(NDIS_PNP_CAPABILITIES)); + if (MPIsPoMgmtSupported(pPort)) + { + MPFillPoMgmtCaps(pPort, &PowerManagementCapabilities, &Status, &unUsed); + ASSERT(NT_SUCCESS(Status)); + gat.PowerManagementCapabilities = &PowerManagementCapabilities; + } + else + { + + } +#endif + + // + // Set RSS attributes + // + gat.RecvScaleCapabilities = NULL; +#if 0 + NDIS_RECEIVE_SCALE_CAPABILITIES RssCapabilities; + NdisZeroMemory(&RssCapabilities, sizeof(PNDIS_RECEIVE_SCALE_CAPABILITIES)); + Status = MPFillRssCapabilities(pPort, &RssCapabilities, &unUsed); + if (NT_SUCCESS(Status)) + { + gat.RecvScaleCapabilities = &RssCapabilities; + } + else + { + // + // do not fail the call because of failure to get PM caps + // + Status = NDIS_STATUS_SUCCESS; + gat.RecvScaleCapabilities = NULL; + } +#endif + + Status = NdisMSetMiniportAttributes(h_adapter, + (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&gat); + + return Status; +} + + +/*++ +Routine Description: + The routine sets an NDIS_OFFLOAD structure indicates the current offload + capabilities that are provided by the miniport adapter + +Arguments: + pPort - a pointer to port object + offload - reference to NDIS_OFFLOAD object that should be filled + +Return Value: + None. + +--*/ +static +void +OffloadConfig( + ipoib_adapter_t *p_adapter, + NDIS_OFFLOAD *p_offload + ) +{ + + ULONG ulEncapsulation = NDIS_ENCAPSULATION_IEEE_802_3 | NDIS_ENCAPSULATION_IEEE_802_3_P_AND_Q; + + NdisZeroMemory(p_offload, NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_1); + + p_offload->Header.Type = NDIS_OBJECT_TYPE_OFFLOAD; + p_offload->Header.Revision = NDIS_OFFLOAD_REVISION_1; // BUGBUG: do we need to support revision 2? UH 17-May-2008 + p_offload->Header.Size = NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_1; + + p_offload->Checksum.IPv4Transmit.Encapsulation = ulEncapsulation; + p_offload->Checksum.IPv4Transmit.IpOptionsSupported = + p_offload->Checksum.IPv4Transmit.TcpOptionsSupported = + p_offload->Checksum.IPv4Transmit.TcpChecksum = + p_offload->Checksum.IPv4Transmit.UdpChecksum = + p_offload->Checksum.IPv4Transmit.IpChecksum =!!(p_adapter->params.send_chksum_offload); + + p_offload->Checksum.IPv4Receive.Encapsulation = ulEncapsulation; + p_offload->Checksum.IPv4Receive.IpOptionsSupported = + p_offload->Checksum.IPv4Receive.TcpOptionsSupported = + p_offload->Checksum.IPv4Receive.TcpChecksum = + p_offload->Checksum.IPv4Receive.UdpChecksum = + p_offload->Checksum.IPv4Receive.IpChecksum = !!(p_adapter->params.recv_chksum_offload); //TODO NDIS60 + + + p_offload->Checksum.IPv6Transmit.Encapsulation = ulEncapsulation; + p_offload->Checksum.IPv6Transmit.IpExtensionHeadersSupported = + p_offload->Checksum.IPv6Transmit.TcpOptionsSupported = + p_offload->Checksum.IPv6Transmit.TcpChecksum = + p_offload->Checksum.IPv6Transmit.UdpChecksum = FALSE; + + + p_offload->Checksum.IPv6Receive.Encapsulation = ulEncapsulation; + p_offload->Checksum.IPv6Receive.IpExtensionHeadersSupported = + p_offload->Checksum.IPv6Receive.TcpOptionsSupported = + p_offload->Checksum.IPv6Receive.TcpChecksum = + p_offload->Checksum.IPv6Receive.UdpChecksum = FALSE; + + if (p_adapter->params.lso) + { + p_offload->LsoV1.IPv4.Encapsulation = ulEncapsulation; + p_offload->LsoV1.IPv4.MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE; +#define LSO_MIN_SEG_COUNT 2 + p_offload->LsoV1.IPv4.MinSegmentCount = LSO_MIN_SEG_COUNT; + + + p_offload->LsoV1.IPv4.TcpOptions = NDIS_OFFLOAD_SUPPORTED; + p_offload->LsoV1.IPv4.IpOptions = NDIS_OFFLOAD_SUPPORTED; + + p_offload->LsoV2.IPv4.Encapsulation = ulEncapsulation; + p_offload->LsoV2.IPv4.MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE; + p_offload->LsoV2.IPv4.MinSegmentCount = LSO_MIN_SEG_COUNT; + + p_offload->LsoV2.IPv6.Encapsulation = ulEncapsulation; + p_offload->LsoV2.IPv6.MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE; + p_offload->LsoV2.IPv6.MinSegmentCount = LSO_MIN_SEG_COUNT; + + p_offload->LsoV2.IPv6.IpExtensionHeadersSupported = NDIS_OFFLOAD_NOT_SUPPORTED; + p_offload->LsoV2.IPv6.TcpOptionsSupported = NDIS_OFFLOAD_SUPPORTED; + } + +} + + +/*++ +Routine Description: + The routine sets an NDIS_OFFLOAD structure that indicates all the task + offload capabilites that are supported by the NIC. These capabilities include + capabilities that are currently disabled by standardized keywords in the registry. + +Arguments: + offload - reference to NDIS_OFFLOAD object that should be filled + +Return Value: + None. + +--*/ +static +void +OffloadCapabilities( + NDIS_OFFLOAD *p_offload + ) +{ + ULONG ulEncapsulation = NDIS_ENCAPSULATION_IEEE_802_3 | NDIS_ENCAPSULATION_IEEE_802_3_P_AND_Q ; + NdisZeroMemory(p_offload, NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_1); + + p_offload->Header.Type = NDIS_OBJECT_TYPE_OFFLOAD; + p_offload->Header.Revision = NDIS_OFFLOAD_REVISION_1; // BUGBUG: do we need to support revision 2? UH 17-May-2008 + p_offload->Header.Size = NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_1; + + p_offload->Checksum.IPv4Transmit.Encapsulation = ulEncapsulation; + p_offload->Checksum.IPv4Transmit.IpOptionsSupported = TRUE; + p_offload->Checksum.IPv4Transmit.TcpOptionsSupported = TRUE; + p_offload->Checksum.IPv4Transmit.TcpChecksum = TRUE; + p_offload->Checksum.IPv4Transmit.UdpChecksum = TRUE; + p_offload->Checksum.IPv4Transmit.IpChecksum = TRUE; + + p_offload->Checksum.IPv4Receive.Encapsulation = ulEncapsulation; + p_offload->Checksum.IPv4Receive.IpOptionsSupported = TRUE; + p_offload->Checksum.IPv4Receive.TcpOptionsSupported = TRUE; + p_offload->Checksum.IPv4Receive.TcpChecksum = TRUE; + p_offload->Checksum.IPv4Receive.UdpChecksum = TRUE; + p_offload->Checksum.IPv4Receive.IpChecksum = TRUE; + + + // + // BUGBUG:: + // During a HW bug that didn't handle correctly packets with + // IPv6 Extension Headers -> we set IpExtensionHeadersSupported to TRUE + // + p_offload->Checksum.IPv6Transmit.Encapsulation = ulEncapsulation; + p_offload->Checksum.IPv6Transmit.IpExtensionHeadersSupported = TRUE; + p_offload->Checksum.IPv6Transmit.TcpOptionsSupported = TRUE; + p_offload->Checksum.IPv6Transmit.TcpChecksum = TRUE; + p_offload->Checksum.IPv6Transmit.UdpChecksum = TRUE; + + + p_offload->Checksum.IPv6Receive.Encapsulation = ulEncapsulation; + p_offload->Checksum.IPv6Receive.IpExtensionHeadersSupported = TRUE; + p_offload->Checksum.IPv6Receive.TcpOptionsSupported = TRUE; + p_offload->Checksum.IPv6Receive.TcpChecksum = TRUE; + p_offload->Checksum.IPv6Receive.UdpChecksum = TRUE; + + p_offload->LsoV1.IPv4.Encapsulation = ulEncapsulation; + p_offload->LsoV1.IPv4.MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE; + p_offload->LsoV1.IPv4.MinSegmentCount = 2; + p_offload->LsoV1.IPv4.TcpOptions = NDIS_OFFLOAD_SUPPORTED; + p_offload->LsoV1.IPv4.IpOptions = NDIS_OFFLOAD_SUPPORTED; + + p_offload->LsoV2.IPv4.Encapsulation = ulEncapsulation; + p_offload->LsoV2.IPv4.MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE; + p_offload->LsoV2.IPv4.MinSegmentCount = 2; + + p_offload->LsoV2.IPv6.Encapsulation = ulEncapsulation; + p_offload->LsoV2.IPv6.MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE; + p_offload->LsoV2.IPv6.MinSegmentCount = 2; + + p_offload->LsoV2.IPv6.IpExtensionHeadersSupported = NDIS_OFFLOAD_NOT_SUPPORTED; + p_offload->LsoV2.IPv6.TcpOptionsSupported = NDIS_OFFLOAD_SUPPORTED; + + } + + +/*++ +Routine Description: + The routine sets offload attributes that are associated with a miniport + adapter. + +Arguments: + pPort - Pointer to port object + +Return Value: + NDIS_STATUS + +Note: + Should be called in PASSIVE_LEVEL + +--*/ +NDIS_STATUS +SetOffloadAttributes( + ipoib_adapter_t *p_adapter, + NDIS_HANDLE h_adapter + ) +{ + NDIS_STATUS Status; + NDIS_OFFLOAD offload,hwOffload; + //ULONG ulEncapsulation = NDIS_ENCAPSULATION_IEEE_802_3 | NDIS_ENCAPSULATION_IEEE_802_3_P_AND_Q; + + NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES oat; + NdisZeroMemory(&oat, sizeof(NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES)); + + oat.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES; + oat.Header.Revision = NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES_REVISION_1; + oat.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES_REVISION_1; + + + OffloadConfig(p_adapter, &offload); + + + OffloadCapabilities(&hwOffload); + + oat.DefaultOffloadConfiguration = &offload; + oat.HardwareOffloadCapabilities = &hwOffload; + + Status = NdisMSetMiniportAttributes(h_adapter, + (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&oat); + + return Status; +} + + +/*++ + +Routine Description: + An NDIS 6.0 miniport driver must call NdisMSetMiniportAttributes + at least twice. The first call is to register itself with NDIS. + The second call is to register the miniport driver's general + attributes with NDIS. + + NdisMSetMiniportAttributes takes a parameter of type + NDIS_MINIPORT_ADAPTER_ATTRIBUTES, which is a union of several miniport + adapter attributes. Miniport drivers must first call + NdisMSetMiniportAttributes and pass in an + NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES structure + that contains the pointer to its own context area, attribute flags, + check-for-hang time, and interface type. + + All NDIS 6.0 miniport drivers are deserialized by default. + +Arguments: + pPort - Pointer to port object + +Return Value: + NDIS_STATUS + +Note: + Should be called in PASSIVE_LEVEL + +--*/ + NDIS_STATUS + SetAttributes( + ipoib_adapter_t *p_adapter, + NDIS_HANDLE h_adapter + ) + { + NTSTATUS Status; + + + Status = SetDeviceRegistrationAttributes(p_adapter, h_adapter); + if (Status != NDIS_STATUS_SUCCESS) + { + //ETH_PRINT(TRACE_LEVEL_ERROR, ETH_INIT, "Set device registration failed Error=0x%x\n", Status); + return Status; + } + + + Status = SetAdapterRegistrationAttributes(p_adapter, h_adapter); + if (Status != NDIS_STATUS_SUCCESS) + { + //ETH_PRINT(TRACE_LEVEL_ERROR, ETH_INIT, "Set adapter attributes failed Error=0x%x\n", Status); + return Status; + } + + Status = SetOffloadAttributes(p_adapter, h_adapter); + if (Status != NDIS_STATUS_SUCCESS) + { + //ETH_PRINT(TRACE_LEVEL_ERROR, ETH_INIT, "Set OFFLOAD attributes failed Error=0x%x\n", Status); + return Status; + } + +#if 0 + if(!pPort->Config.fWHQL) + { + Status = SetHardwareAssistAttributes(pPort); + if (Status != NDIS_STATUS_SUCCESS) + { + //ETH_PRINT(TRACE_LEVEL_ERROR, ETH_INIT, "Set Hardware Assist Attributes failed Error=0x%x\n", Status); + return Status; + } + } +#endif + + Status = SetGenericAttributes(p_adapter, h_adapter); + if (Status != NDIS_STATUS_SUCCESS) + { + //ETH_PRINT(TRACE_LEVEL_ERROR, ETH_INIT, "Set generic attributes failed Error=0x%x\n", Status); + return Status; + } + + return Status; +} + + + +NDIS_STATUS +InitNdisScatterGatherDma( + ipoib_adapter_t *p_adapter, + NDIS_HANDLE h_adapter + ) +{ + NDIS_STATUS status; + NDIS_SG_DMA_DESCRIPTION DmaDescription; + + NdisZeroMemory(&DmaDescription, sizeof(DmaDescription)); + + DmaDescription.Header.Type = NDIS_OBJECT_TYPE_SG_DMA_DESCRIPTION; + DmaDescription.Header.Revision = NDIS_SG_DMA_DESCRIPTION_REVISION_1; + DmaDescription.Header.Size = sizeof(NDIS_SG_DMA_DESCRIPTION); + DmaDescription.Flags = NDIS_SG_DMA_64_BIT_ADDRESS; + // + // Even if offload is enabled, the packet size for mapping shouldn't change + // + DmaDescription.MaximumPhysicalMapping = LARGE_SEND_OFFLOAD_SIZE + LSO_MAX_HEADER; + + DmaDescription.ProcessSGListHandler = ipoib_process_sg_list; + DmaDescription.SharedMemAllocateCompleteHandler = NULL; + + DmaDescription.Header.Type = NDIS_OBJECT_TYPE_SG_DMA_DESCRIPTION; + DmaDescription.Header.Revision = NDIS_SG_DMA_DESCRIPTION_REVISION_1; + DmaDescription.Header.Size = sizeof(NDIS_SG_DMA_DESCRIPTION);//NDIS_SIZEOF_SG_DMA_DESCRIPTION_REVISION_1; + + DmaDescription.Flags = NDIS_SG_DMA_64_BIT_ADDRESS; + //DmaDescription.MaximumPhysicalMapping = pPort->p_adapter->params.xfer_block_size; + + DmaDescription.ProcessSGListHandler = ipoib_process_sg_list; + DmaDescription.SharedMemAllocateCompleteHandler = NULL; + + status = NdisMRegisterScatterGatherDma( + h_adapter, + &DmaDescription, + &p_adapter->NdisMiniportDmaHandle); + + if( status != NDIS_STATUS_SUCCESS ) + { + //TODO NDIS60 + //ipoib_destroy_adapter( p_adapter ); + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("NdisMRegisterScatterGatherDma returned 0x%.8x.\n", status) ); + + } + //NDIS sets this value before it returns from NdisMRegisterScatterGatherDma. + //Miniport drivers should use this size to preallocate memory for each scatter/gather list. + p_adapter->sg_list_size = DmaDescription.ScatterGatherListSize ; + + return status; +} + + +NDIS_STATUS +MPInitializeTest( + IN NDIS_HANDLE MiniportAdapterHandle, + IN NDIS_HANDLE MiniportDriverContext, + IN PNDIS_MINIPORT_INIT_PARAMETERS MiniportInitParameters + ) +/*++ +Routine Description: + + MiniportInitialize handler + +Arguments: + + MiniportAdapterHandle The handle NDIS uses to refer to us + MiniportDriverContext Handle passed to NDIS when we registered the driver + MiniportInitParameters Initialization parameters + +Return Value: + + NDIS_STATUS_SUCCESS unless something goes wrong + +--*/ +{ + + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + //PMP_PORT pPort = NULL; + ipoib_adapter_t *p_adapter; +// NDIS_MINIPORT_INTERRUPT_CHARACTERISTICS Interrupt; + NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES RegistrationAttributes; + NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES GeneralAttributes; + //NDIS_TIMER_CHARACTERISTICS Timer; + NDIS_PNP_CAPABILITIES PowerManagementCapabilities; + //PMP_ADAPTER Adapter = NULL; + //PVOID NetworkAddress; +// UINT index; +// UINT uiPnpCommandValue; +// ULONG ulInfoLen; + //ULONG InterruptVersion; +// LARGE_INTEGER liDueTime; + //BOOLEAN isTimerAlreadyInQueue = FALSE; +// uint8_t portId; + ib_api_status_t ib_status; +#if 0 +#if DBG + LARGE_INTEGER TS, TD, TE; +#endif +#endif + + cl_dbg_out ("====> MPInitialize\n"); + + UNREFERENCED_PARAMETER(MiniportDriverContext); + UNREFERENCED_PARAMETER(MiniportInitParameters); + + + + + + { + + ib_status = ipoib_create_adapter( MiniportAdapterHandle, &p_adapter ); + if( ib_status != IB_SUCCESS ) + { + ASSERT(FALSE); + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ipoib_create_adapter returned status %d.\n", ib_status ) ); + return NDIS_STATUS_FAILURE; + } + + + + NdisZeroMemory(&RegistrationAttributes, sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES)); + NdisZeroMemory(&GeneralAttributes, sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES)); + + // + // setting registration attributes + // + RegistrationAttributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES; + RegistrationAttributes.Header.Revision = NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1; + RegistrationAttributes.Header.Size = sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES); + + RegistrationAttributes.MiniportAdapterContext = (NDIS_HANDLE)p_adapter; + RegistrationAttributes.AttributeFlags = NDIS_MINIPORT_ATTRIBUTES_HARDWARE_DEVICE | + NDIS_MINIPORT_ATTRIBUTES_BUS_MASTER; + + RegistrationAttributes.CheckForHangTimeInSeconds = 2; + RegistrationAttributes.InterfaceType = NdisInterfacePci; + + Status = NdisMSetMiniportAttributes(MiniportAdapterHandle, + (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&RegistrationAttributes); + + if (Status != NDIS_STATUS_SUCCESS) + { + //break; + return Status; + } + +#if 0 + // + // Read the registry parameters + // + Status = NICReadRegParameters(Adapter); + + if (Status != NDIS_STATUS_SUCCESS) + { + break; + } + + + // + // Find the physical adapter + // + Status = MpFindAdapter(Adapter, MiniportInitParameters->AllocatedResources); + if (Status != NDIS_STATUS_SUCCESS) + { + break; + } + + // + // Map bus-relative IO range to system IO space + // + Status = NdisMRegisterIoPortRange( + (PVOID *)&Adapter->PortOffset, + Adapter->AdapterHandle, + Adapter->IoBaseAddress, + Adapter->IoRange); + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT(MP_ERROR, ("NdisMRegisterioPortRange failed\n")); + + NdisWriteErrorLogEntry( + Adapter->AdapterHandle, + NDIS_ERROR_CODE_BAD_IO_BASE_ADDRESS, + 0); + + break; + } + + // + // Read additional info from NIC such as MAC address + // + Status = NICReadAdapterInfo(Adapter); + if (Status != NDIS_STATUS_SUCCESS) + { + break; + } + +#endif + // + // set up generic attributes + // + + + GeneralAttributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES; + GeneralAttributes.Header.Revision = NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1; + GeneralAttributes.Header.Size = sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES); + + GeneralAttributes.MediaType = NdisMedium802_3; + + GeneralAttributes.MtuSize = DEFAULT_MTU; +#define LINE_SPEED_10_GBTS 10000000000 + GeneralAttributes.MaxXmitLinkSpeed = LINE_SPEED_10_GBTS; + GeneralAttributes.MaxRcvLinkSpeed = LINE_SPEED_10_GBTS; + GeneralAttributes.XmitLinkSpeed = NDIS_LINK_SPEED_UNKNOWN; + GeneralAttributes.RcvLinkSpeed = NDIS_LINK_SPEED_UNKNOWN; + GeneralAttributes.MediaConnectState = MediaConnectStateUnknown; + GeneralAttributes.MediaDuplexState = MediaDuplexStateUnknown; + GeneralAttributes.LookaheadSize = MAX_XFER_BLOCK_SIZE; +#if 0 + MPFillPoMgmtCaps (Adapter, + &PowerManagementCapabilities, + &Status, + &ulInfoLen); +#endif + NdisZeroMemory(&PowerManagementCapabilities, sizeof(NDIS_PNP_CAPABILITIES)); + Status = NDIS_STATUS_NOT_SUPPORTED; + // ulInfoLen = 0; + + if (Status == NDIS_STATUS_SUCCESS) + { + GeneralAttributes.PowerManagementCapabilities = &PowerManagementCapabilities; + } + else + { + GeneralAttributes.PowerManagementCapabilities = NULL; + } + + // + // do not fail the call because of failure to get PM caps + // + Status = NDIS_STATUS_SUCCESS; + + GeneralAttributes.MacOptions = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | + NDIS_MAC_OPTION_TRANSFERS_NOT_PEND | + NDIS_MAC_OPTION_NO_LOOPBACK; + + GeneralAttributes.SupportedPacketFilters = NDIS_PACKET_TYPE_DIRECTED | + NDIS_PACKET_TYPE_MULTICAST | + NDIS_PACKET_TYPE_ALL_MULTICAST | + NDIS_PACKET_TYPE_BROADCAST; + + GeneralAttributes.MaxMulticastListSize = MAX_MCAST; + GeneralAttributes.MacAddressLength = HW_ADDR_LEN; + NdisMoveMemory(GeneralAttributes.PermanentMacAddress, + p_adapter->mac.addr, + HW_ADDR_LEN); + + NdisMoveMemory(GeneralAttributes.CurrentMacAddress, + p_adapter->params.conf_mac.addr, + HW_ADDR_LEN); + GeneralAttributes.RecvScaleCapabilities = NULL; + GeneralAttributes.AccessType = NET_IF_ACCESS_BROADCAST; // NET_IF_ACCESS_BROADCAST for a typical ethernet adapter + GeneralAttributes.DirectionType = NET_IF_DIRECTION_SENDRECEIVE; // NET_IF_DIRECTION_SENDRECEIVE for a typical ethernet adapter + GeneralAttributes.ConnectionType = NET_IF_CONNECTION_DEDICATED; // NET_IF_CONNECTION_DEDICATED for a typical ethernet adapter + GeneralAttributes.IfType = IF_TYPE_ETHERNET_CSMACD; // IF_TYPE_ETHERNET_CSMACD for a typical ethernet adapter (regardless of speed) + GeneralAttributes.IfConnectorPresent = TRUE; // RFC 2665 TRUE if physical adapter + + GeneralAttributes.SupportedStatistics = NDIS_STATISTICS_XMIT_OK_SUPPORTED | + NDIS_STATISTICS_RCV_OK_SUPPORTED | + NDIS_STATISTICS_XMIT_ERROR_SUPPORTED | + NDIS_STATISTICS_RCV_ERROR_SUPPORTED | + NDIS_STATISTICS_RCV_CRC_ERROR_SUPPORTED | + NDIS_STATISTICS_RCV_NO_BUFFER_SUPPORTED | + NDIS_STATISTICS_TRANSMIT_QUEUE_LENGTH_SUPPORTED | + NDIS_STATISTICS_GEN_STATISTICS_SUPPORTED; + + GeneralAttributes.SupportedOidList = NICSupportedOidsTest; + GeneralAttributes.SupportedOidListLength = sizeof(NICSupportedOidsTest); + + Status = NdisMSetMiniportAttributes(MiniportAdapterHandle, + (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&GeneralAttributes); + + +#if 0 + // + // Allocate all other memory blocks including shared memory + // + Status = NICAllocAdapterMemory(Adapter); + if (Status != NDIS_STATUS_SUCCESS) + { + break; + } + // + // Init send data structures + // + NICInitSend(Adapter); + + // + // Init receive data structures + // + Status = NICInitRecv(Adapter); + if (Status != NDIS_STATUS_SUCCESS) + { + break; + } + // + // Map bus-relative registers to virtual system-space + // + Status = NdisMMapIoSpace( + (PVOID *) &(Adapter->CSRAddress), + Adapter->AdapterHandle, + Adapter->MemPhysAddress, + NIC_MAP_IOSPACE_LENGTH); + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT(MP_ERROR, ("NdisMMapIoSpace failed\n")); + + NdisWriteErrorLogEntry( + Adapter->AdapterHandle, + NDIS_ERROR_CODE_RESOURCE_CONFLICT, + 1, + ERRLOG_MAP_IO_SPACE); + + break; + } + + DBGPRINT(MP_INFO, ("CSRAddress="PTR_FORMAT"\n", Adapter->CSRAddress)); + + // + // Disable interrupts here which is as soon as possible + // + NICDisableInterrupt(Adapter); +#endif + + // + // Register the interrupt + // + // + + // + // the embeded NDIS interrupt structure is already zero'ed out + // as part of the adapter structure + // + #if 0 + NdisZeroMemory(&Interrupt, sizeof(NDIS_MINIPORT_INTERRUPT_CHARACTERISTICS)); + + Interrupt.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_INTERRUPT; + Interrupt.Header.Revision = NDIS_MINIPORT_INTERRUPT_REVISION_1; + Interrupt.Header.Size = sizeof(NDIS_MINIPORT_INTERRUPT_CHARACTERISTICS); + + Interrupt.InterruptHandler = MPIsr; + Interrupt.InterruptDpcHandler = MPHandleInterrupt; + Interrupt.DisableInterruptHandler = NULL; + Interrupt.EnableInterruptHandler = NULL; + + + + Status = NdisMRegisterInterruptEx(Adapter->AdapterHandle, + Adapter, + &Interrupt, + &Adapter->NdisInterruptHandle + ); + + + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT(MP_ERROR, ("NdisMRegisterInterrupt failed\n")); + + NdisWriteErrorLogEntry( + Adapter->AdapterHandle, + NDIS_ERROR_CODE_INTERRUPT_CONNECT, + 0); + + break; + } + + // + // If the driver support MSI + // + Adapter->InterruptType = Interrupt.InterruptType; + + if (Adapter->InterruptType == NDIS_CONNECT_MESSAGE_BASED) + { + Adapter->MessageInfoTable = Interrupt.MessageInfoTable; + } + + // + // If the driver supports MSI, here it should what kind of interrupt is granted. If MSI is granted, + // the driver can check Adapter->MessageInfoTable to get MSI information + // + + + MP_SET_FLAG(Adapter, fMP_ADAPTER_INTERRUPT_IN_USE); + + // + // Test our adapter hardware + // + Status = NICSelfTest(Adapter); + if (Status != NDIS_STATUS_SUCCESS) + { + break; + } + + // + // Init the hardware and set up everything + // + Status = NICInitializeAdapter(Adapter); + if (Status != NDIS_STATUS_SUCCESS) + { + break; + } + + // + // initial state is paused + // + Adapter->AdapterState = NicPaused; + + // + // Set the link detection flag + // + MP_SET_FLAG(Adapter, fMP_ADAPTER_LINK_DETECTION); + + // + // Increment the reference count so halt handler will wait + // + MP_INC_REF(Adapter); + + // + // Enable the interrupt + // + NICEnableInterrupt(Adapter); + + + NdisZeroMemory(&Timer, sizeof(NDIS_TIMER_CHARACTERISTICS)); + + Timer.Header.Type = NDIS_OBJECT_TYPE_TIMER_CHARACTERISTICS; + Timer.Header.Revision = NDIS_TIMER_CHARACTERISTICS_REVISION_1; + Timer.Header.Size = sizeof(NDIS_TIMER_CHARACTERISTICS); + + Timer.AllocationTag = NIC_TAG; + Timer.TimerFunction = MpLinkDetectionDpc; + Timer.FunctionContext = Adapter; + + // + // Minimize init-time + // + Status = NdisAllocateTimerObject( + Adapter->AdapterHandle, + &Timer, + &Adapter->LinkDetectionTimerHandle); + + if (Status != NDIS_STATUS_SUCCESS) + { + break; + } + + liDueTime.QuadPart = NIC_LINK_DETECTION_DELAY; + isTimerAlreadyInQueue =NdisSetTimerObject(Adapter->LinkDetectionTimerHandle, liDueTime, 0, NULL); + ASSERT(!isTimerAlreadyInQueue); +#endif + } +#if 0 + if (Adapter && (Status != NDIS_STATUS_SUCCESS)) + { + // + // Undo everything if it failed + // + MP_DEC_REF(Adapter); + MpFreeAdapter(Adapter); + } + + DBGPRINT_S(Status, ("<==== MPInitialize, Status=%x\n", Status)); +#endif + /* Create the adapter adapter */ + ib_status = ipoib_start_adapter( p_adapter ); + if( ib_status != IB_SUCCESS ) + { + ASSERT(FALSE); + + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ipoib_start_adapter returned status %d.\n", ib_status ) ); + return NDIS_STATUS_FAILURE; + } + + ipoib_ref_ibat(); + return NDIS_STATUS_SUCCESS; +} + + + +NDIS_STATUS +ipoib_initialize_ex( + IN NDIS_HANDLE h_adapter, + IN NDIS_HANDLE config_context, + IN PNDIS_MINIPORT_INIT_PARAMETERS MiniportInitParameters) + { + NDIS_STATUS status; + ib_api_status_t ib_status; + ipoib_adapter_t *p_adapter; + + IPOIB_ENTER( IPOIB_DBG_INIT ); + +#ifdef _DEBUG_ + PAGED_CODE(); +#endif + + UNUSED_PARAM( config_context ); + UNUSED_PARAM( MiniportInitParameters ); + + /* Create the adapter adapter */ + ib_status = ipoib_create_adapter( h_adapter, &p_adapter ); + if( ib_status != IB_SUCCESS ) + { + ASSERT(FALSE); + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ipoib_create_adapter returned status %d.\n", ib_status ) ); + return NDIS_STATUS_FAILURE; + } + p_adapter->ipoib_state = IPOIB_PAUSED; + status = SetAttributes(p_adapter, h_adapter); + if (status != NDIS_STATUS_SUCCESS) { + ASSERT(FALSE); + } + +#if IPOIB_USE_DMA + InitNdisScatterGatherDma(p_adapter, h_adapter); +#endif + + /* Create the adapter adapter */ + ib_status = ipoib_start_adapter( p_adapter ); + if( ib_status != IB_SUCCESS ) + { + ASSERT(FALSE); + NdisWriteErrorLogEntry( h_adapter, + NDIS_ERROR_CODE_HARDWARE_FAILURE, 0 ); +#if IPOIB_USE_DMA + NdisMDeregisterScatterGatherDma(p_adapter->NdisMiniportDmaHandle); +#endif + ipoib_destroy_adapter( p_adapter ); + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ipoib_start_adapter returned status %d.\n", ib_status ) ); + return NDIS_STATUS_FAILURE; + } + + ipoib_ref_ibat(); + + IPOIB_EXIT( IPOIB_DBG_INIT ); + return status; + } + + +//! Deallocates resources when the NIC is removed and halts the NIC.. +//TODO: Dispatch or Passive ? +/* IRQL = DISPATCH_LEVEL + +@param adapter_context The adapter context allocated at start +*/ +void +ipoib_halt_ex( + IN NDIS_HANDLE adapter_context, + IN NDIS_HALT_ACTION HaltAction ) +{ + ipoib_adapter_t *p_adapter; + + IPOIB_ENTER( IPOIB_DBG_INIT ); + + UNUSED_PARAM(HaltAction); +//return; + ipoib_deref_ibat(); + + CL_ASSERT( adapter_context ); + p_adapter = (ipoib_adapter_t*)adapter_context; + + IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, + ("Port %016I64x (CA %016I64x port %d) halting\n", + p_adapter->guids.port_guid.guid, p_adapter->guids.ca_guid, + p_adapter->guids.port_num) ); + +#if IPOIB_USE_DMA + if (p_adapter->NdisMiniportDmaHandle != NULL) + { + NdisMDeregisterScatterGatherDma(p_adapter->NdisMiniportDmaHandle); + p_adapter->NdisMiniportDmaHandle = NULL; + } +#endif + ipoib_destroy_adapter( p_adapter ); + + IPOIB_EXIT( IPOIB_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 +ipoib_check_for_hang( + IN NDIS_HANDLE adapter_context ) +{ + ipoib_adapter_t *p_adapter; + + IPOIB_ENTER( IPOIB_DBG_INIT ); +//return FALSE; + CL_ASSERT( adapter_context ); + p_adapter = (ipoib_adapter_t*)adapter_context; + + if( p_adapter->reset ) + { + IPOIB_EXIT( IPOIB_DBG_INIT ); + return FALSE; + } + if (p_adapter->hung) { + ipoib_resume_oids(p_adapter); + } + + IPOIB_EXIT( IPOIB_DBG_INIT ); + return (p_adapter->hung? TRUE:FALSE); +} + + +/*++ +Routine Description: + The routine sets an NDIS_OFFLOAD structure indicates the current offload + capabilities that are provided by the miniport adapter + +Arguments: + pPort - a pointer to port object + offload - reference to NDIS_OFFLOAD object that should be filled + +Return Value: + None. + +--*/ +//TODO +#if 0 +static +void +__ipoib_get_offload_config( + ipoib_port_t *pPort, + NDIS_OFFLOAD *p_offload + ) +{ + NDIS_STATUS Status; + ULONG TxChksumOffload = ((MP_GET_PORT_CONFIG(pPort, TxChksumOffload) == TRUE) ? NDIS_OFFLOAD_SET_ON : NDIS_OFFLOAD_SET_OFF); + ULONG RxChksumOffload = ((MP_GET_PORT_CONFIG(pPort, RxChksumOffload) == TRUE) ? NDIS_OFFLOAD_SET_ON : NDIS_OFFLOAD_SET_OFF); + BOOLEAN fLargeSendOffload = MP_GET_PORT_CONFIG(pPort, LargeSendOffload); + ULONG ulEncapsulation = NDIS_ENCAPSULATION_IEEE_802_3 | NDIS_ENCAPSULATION_IEEE_802_3_P_AND_Q; + + NdisZeroMemory(&*p_offload, sizeof(NDIS_OFFLOAD)); + *p_offload.Header.Type = NDIS_OBJECT_TYPE_OFFLOAD; + *p_offload.Header.Revision = NDIS_OFFLOAD_REVISION_1; // BUGBUG: do we need to support revision 2? UH 17-May-2008 + *p_offload.Header.Size = NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_1; + + *p_offload.Checksum.IPv4Transmit.Encapsulation = ulEncapsulation; + *p_offload.Checksum.IPv4Transmit.IpOptionsSupported = TxChksumOffload; + *p_offload.Checksum.IPv4Transmit.TcpOptionsSupported = TxChksumOffload; + *p_offload.Checksum.IPv4Transmit.TcpChecksum = TxChksumOffload; + *p_offload.Checksum.IPv4Transmit.UdpChecksum = NDIS_OFFLOAD_NOT_SUPPORTED; + *p_offload.Checksum.IPv4Transmit.IpChecksum = TxChksumOffload; + + *p_offload.Checksum.IPv4Receive.Encapsulation = ulEncapsulation; + *p_offload.Checksum.IPv4Receive.IpOptionsSupported = RxChksumOffload; + *p_offload.Checksum.IPv4Receive.TcpOptionsSupported = RxChksumOffload; + *p_offload.Checksum.IPv4Receive.TcpChecksum = RxChksumOffload; + *p_offload.Checksum.IPv4Receive.UdpChecksum = NDIS_OFFLOAD_NOT_SUPPORTED; + *p_offload.Checksum.IPv4Receive.IpChecksum = RxChksumOffload; + + *p_offload.Checksum.IPv6Transmit.Encapsulation = ulEncapsulation; + *p_offload.Checksum.IPv6Transmit.IpExtensionHeadersSupported = TxChksumOffload; + *p_offload.Checksum.IPv6Transmit.TcpOptionsSupported = TxChksumOffload; + *p_offload.Checksum.IPv6Transmit.TcpChecksum = TxChksumOffload; + *p_offload.Checksum.IPv6Transmit.UdpChecksum = NDIS_OFFLOAD_NOT_SUPPORTED; + + + *p_offload.Checksum.IPv6Receive.Encapsulation = ulEncapsulation; + *p_offload.Checksum.IPv6Receive.IpExtensionHeadersSupported = RxChksumOffload; + *p_offload.Checksum.IPv6Receive.TcpOptionsSupported = RxChksumOffload; + *p_offload.Checksum.IPv6Receive.TcpChecksum = RxChksumOffload; + *p_offload.Checksum.IPv6Receive.UdpChecksum = NDIS_OFFLOAD_NOT_SUPPORTED; + + if (fLargeSendOffload) + { + *p_offload.LsoV1.IPv4.Encapsulation = ulEncapsulation; + *p_offload.LsoV1.IPv4.MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE; + *p_offload.LsoV1.IPv4.MinSegmentCount = 1; + *p_offload.LsoV1.IPv4.TcpOptions = NDIS_OFFLOAD_SUPPORTED; + *p_offload.LsoV1.IPv4.IpOptions = NDIS_OFFLOAD_SUPPORTED; + } +} +#endif + +//! 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 +ipoib_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 ) + { + ipoib_adapter_t *p_adapter; + NDIS_STATUS status; + USHORT version; + ULONG info; + PVOID src_buf; + ULONG buf_len; + pending_oid_t oid_info; + uint8_t port_num; + + IPOIB_ENTER( IPOIB_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 = (ipoib_adapter_t*)adapter_context; + + CL_ASSERT( p_bytes_written ); + CL_ASSERT( p_bytes_needed ); + CL_ASSERT( !p_adapter->pending_query ); + + status = NDIS_STATUS_SUCCESS; + src_buf = &info; + buf_len = sizeof(info); + + port_num = p_adapter->guids.port_num; + + switch( oid ) + { + /* Required General */ + case OID_GEN_SUPPORTED_LIST: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_GEN_SUPPORTED_LIST\n", port_num) ); + src_buf = (PVOID)SUPPORTED_OIDS; + buf_len = sizeof(SUPPORTED_OIDS); + break; + + case OID_GEN_HARDWARE_STATUS: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_GEN_HARDWARE_STATUS\n", port_num) ); + cl_obj_lock( &p_adapter->obj ); + switch( p_adapter->state ) + { + case IB_PNP_PORT_ADD: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d returning NdisHardwareStatusInitializing\n", port_num) ); + info = NdisHardwareStatusInitializing; + break; + + case IB_PNP_PORT_ACTIVE: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d returning NdisHardwareStatusReady\n", port_num) ); + info = NdisHardwareStatusReady; + break; + + default: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d returning NdisHardwareStatusNotReady\n", port_num) ); + info = NdisHardwareStatusNotReady; + } + cl_obj_unlock( &p_adapter->obj ); + break; + + case OID_GEN_MEDIA_SUPPORTED: + case OID_GEN_MEDIA_IN_USE: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_GEN_MEDIA_SUPPORTED " + "or OID_GEN_MEDIA_IN_USE\n", port_num) ); + info = NdisMedium802_3; + break; + + case OID_GEN_MAXIMUM_FRAME_SIZE: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_GEN_MAXIMUM_FRAME_SIZE\n", port_num) ); + if( p_adapter->params.cm_enabled ) + { + info = p_adapter->params.cm_payload_mtu; + } + else + { + info = p_adapter->params.payload_mtu; + } + break; + + case OID_GEN_LINK_SPEED: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_GEN_LINK_SPEED\n", port_num) ); + if (info_buf_len < buf_len) + { + break; + } + + cl_obj_lock( &p_adapter->obj ); + switch( p_adapter->state ) + { + case IB_PNP_PORT_ADD: + /* Mark the adapter as pending an OID */ + p_adapter->pending_query = TRUE; + + /* Save the request parameters. */ + p_adapter->query_oid = oid_info; + + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d returning NDIS_STATUS_PENDING\n", port_num) ); + status = NDIS_STATUS_PENDING; + break; + + case IB_PNP_PORT_REMOVE: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d returning NDIS_STATUS_NOT_ACCEPTED\n", port_num) ); + status = NDIS_STATUS_NOT_ACCEPTED; + break; + + default: + CL_ASSERT( p_adapter->p_port ); + info = p_adapter->port_rate; + break; + } + cl_obj_unlock( &p_adapter->obj ); + break; + + case OID_GEN_TRANSMIT_BUFFER_SPACE: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_GEN_TRANSMIT_BUFFER_SPACE\n", port_num) ); + if( p_adapter->params.cm_enabled ) + info = p_adapter->params.sq_depth * p_adapter->params.cm_xfer_block_size; + else + info = p_adapter->params.sq_depth * p_adapter->params.xfer_block_size; + break; + + case OID_GEN_RECEIVE_BUFFER_SPACE: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_GEN_TRANSMIT_BUFFER_SPACE " + "or OID_GEN_RECEIVE_BUFFER_SPACE\n", port_num) ); + if( p_adapter->params.cm_enabled ) + info = p_adapter->params.rq_depth * p_adapter->params.cm_xfer_block_size; + else + info = p_adapter->params.rq_depth * p_adapter->params.xfer_block_size; + break; + + case OID_GEN_MAXIMUM_LOOKAHEAD: + case OID_GEN_CURRENT_LOOKAHEAD: + case OID_GEN_TRANSMIT_BLOCK_SIZE: + case OID_GEN_RECEIVE_BLOCK_SIZE: + case OID_GEN_MAXIMUM_TOTAL_SIZE: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_GEN_MAXIMUM_LOOKAHEAD " + "or OID_GEN_CURRENT_LOOKAHEAD or " + "OID_GEN_TRANSMIT_BLOCK_SIZE or " + "OID_GEN_RECEIVE_BLOCK_SIZE or " + "OID_GEN_MAXIMUM_TOTAL_SIZE\n", port_num) ); + if( p_adapter->params.cm_enabled ) + info = p_adapter->params.cm_xfer_block_size; + else + info = p_adapter->params.xfer_block_size; + break; + + case OID_GEN_VENDOR_ID: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_GEN_VENDOR_ID\n", port_num) ); + src_buf = (void*)VENDOR_ID; + buf_len = sizeof(VENDOR_ID); + break; + + case OID_GEN_VENDOR_DESCRIPTION: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_GEN_VENDOR_DESCRIPTION\n", port_num) ); + src_buf = VENDOR_DESCRIPTION; + buf_len = sizeof(VENDOR_DESCRIPTION); + break; + + case OID_GEN_VENDOR_DRIVER_VERSION: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_GEN_VENDOR_DRIVER_VERSION\n", port_num) ); + src_buf = &version; + buf_len = sizeof(version); + //TODO: Figure out what the right version is. + version = 1 << 8 | 1; + break; + + case OID_GEN_PHYSICAL_MEDIUM: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_GEN_PHYSICAL_MEDIUM\n", port_num) ); + info = NdisPhysicalMediumUnspecified; + break; + + case OID_GEN_CURRENT_PACKET_FILTER: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_GEN_CURRENT_PACKET_FILTER\n", port_num) ); + info = p_adapter->packet_filter; + break; + + case OID_GEN_DRIVER_VERSION: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_GEN_DRIVER_VERSION\n", port_num) ); + src_buf = &version; + buf_len = sizeof(version); + version = MAJOR_NDIS_VERSION << 8 | MINOR_NDIS_VERSION; + break; + + case OID_GEN_MAC_OPTIONS: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_GEN_MAC_OPTIONS\n", port_num) ); + info = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | + NDIS_MAC_OPTION_TRANSFERS_NOT_PEND | + NDIS_MAC_OPTION_NO_LOOPBACK | + NDIS_MAC_OPTION_FULL_DUPLEX; + //TODO: Figure out if we will support priority and VLANs. + // NDIS_MAC_OPTION_8021P_PRIORITY; + //#ifdef NDIS51_MINIPORT + // info |= NDIS_MAC_OPTION_8021Q_VLAN; + //#endif + break; + + case OID_GEN_MEDIA_CONNECT_STATUS: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_GEN_MEDIA_CONNECT_STATUS\n", port_num) ); + cl_obj_lock( &p_adapter->obj ); + switch( p_adapter->state ) + { + case IB_PNP_PORT_ADD: + case IB_PNP_PORT_INIT: + /* + * Delay reporting media state until we know whether the port is + * either up or down. + */ + p_adapter->pending_query = TRUE; + p_adapter->query_oid = oid_info; + + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d returning NDIS_STATUS_PENDING\n", port_num) ); + status = NDIS_STATUS_PENDING; + break; + + case IB_PNP_PORT_ACTIVE: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d returning NdisMediaStateConnected\n", port_num) ); + info = NdisMediaStateConnected; + break; + + case IB_PNP_PORT_REMOVE: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d returning NDIS_STATUS_NOT_ACCEPTED\n", port_num) ); + status = NDIS_STATUS_NOT_ACCEPTED; + break; + + default: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d returning NdisMediaStateDisconnected\n", port_num) ); + info = NdisMediaStateDisconnected; + } + cl_obj_unlock( &p_adapter->obj ); + break; + + case OID_GEN_MAXIMUM_SEND_PACKETS: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_GEN_MAXIMUM_SEND_PACKETS\n", port_num) ); + info = MINIPORT_MAX_SEND_PACKETS; + break; + + /* Required General Statistics */ + case OID_GEN_STATISTICS: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_GEN_STATISTICS\n", port_num) ); + src_buf = NULL; + buf_len = sizeof(NDIS_STATISTICS_INFO); + if (info_buf_len < buf_len) + { + break; + } + status = ipoib_get_gen_stat(p_adapter, &oid_info ); + break; + + case OID_GEN_XMIT_OK: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_GEN_XMIT_OK\n", port_num) ); + src_buf = NULL; + status = ipoib_get_send_stat( p_adapter, IP_STAT_SUCCESS, &oid_info ); + break; + + case OID_GEN_RCV_OK: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_GEN_RCV_OK\n", port_num) ); + src_buf = NULL; + status = ipoib_get_recv_stat( p_adapter, IP_STAT_SUCCESS, &oid_info ); + break; + + case OID_GEN_XMIT_ERROR: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_GEN_XMIT_ERROR\n", port_num) ); + src_buf = NULL; + status = ipoib_get_send_stat( p_adapter, IP_STAT_ERROR, &oid_info ); + break; + + case OID_GEN_RCV_ERROR: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_GEN_RCV_ERROR\n", port_num) ); + src_buf = NULL; + status = ipoib_get_recv_stat( p_adapter, IP_STAT_ERROR, &oid_info ); + break; + + case OID_GEN_RCV_NO_BUFFER: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_GEN_RCV_NO_BUFFER\n", port_num) ); + src_buf = NULL; + status = ipoib_get_recv_stat( p_adapter, IP_STAT_DROPPED, &oid_info ); + break; + + case OID_GEN_DIRECTED_BYTES_XMIT: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_GEN_DIRECTED_BYTES_XMIT\n", port_num) ); + src_buf = NULL; + status = ipoib_get_send_stat( p_adapter, IP_STAT_UCAST_BYTES, &oid_info ); + break; + + case OID_GEN_DIRECTED_FRAMES_XMIT: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_GEN_DIRECTED_FRAMES_XMIT\n", port_num) ); + src_buf = NULL; + status = ipoib_get_send_stat( p_adapter, IP_STAT_UCAST_FRAMES, &oid_info ); + break; + + case OID_GEN_MULTICAST_BYTES_XMIT: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_GEN_MULTICAST_BYTES_XMIT\n", port_num) ); + src_buf = NULL; + status = ipoib_get_send_stat( p_adapter, IP_STAT_MCAST_BYTES, &oid_info ); + break; + + case OID_GEN_MULTICAST_FRAMES_XMIT: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_GEN_MULTICAST_FRAMES_XMIT\n", port_num) ); + src_buf = NULL; + status = ipoib_get_send_stat( p_adapter, IP_STAT_MCAST_FRAMES, &oid_info ); + break; + + case OID_GEN_BROADCAST_BYTES_XMIT: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_GEN_BROADCAST_BYTES_XMIT\n", port_num) ); + src_buf = NULL; + status = ipoib_get_send_stat( p_adapter, IP_STAT_BCAST_BYTES, &oid_info ); + break; + + case OID_GEN_BROADCAST_FRAMES_XMIT: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_GEN_BROADCAST_FRAMES_XMIT\n", port_num) ); + src_buf = NULL; + status = ipoib_get_send_stat( p_adapter, IP_STAT_BCAST_FRAMES, &oid_info ); + break; + + case OID_GEN_DIRECTED_BYTES_RCV: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_GEN_DIRECTED_BYTES_RCV\n", port_num) ); + src_buf = NULL; + status = ipoib_get_recv_stat( p_adapter, IP_STAT_UCAST_BYTES, &oid_info ); + break; + + case OID_GEN_DIRECTED_FRAMES_RCV: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_GEN_DIRECTED_FRAMES_RCV\n", port_num) ); + src_buf = NULL; + status = ipoib_get_recv_stat( p_adapter, IP_STAT_UCAST_FRAMES, &oid_info ); + break; + + case OID_GEN_MULTICAST_BYTES_RCV: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_GEN_MULTICAST_BYTES_RCV\n", port_num) ); + src_buf = NULL; + status = ipoib_get_recv_stat( p_adapter, IP_STAT_MCAST_BYTES, &oid_info ); + break; + + case OID_GEN_MULTICAST_FRAMES_RCV: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_GEN_MULTICAST_FRAMES_RCV\n", port_num) ); + src_buf = NULL; + status = ipoib_get_recv_stat( p_adapter, IP_STAT_MCAST_FRAMES, &oid_info ); + break; + + case OID_GEN_BROADCAST_BYTES_RCV: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_GEN_BROADCAST_BYTES_RCV\n", port_num) ); + src_buf = NULL; + status = ipoib_get_recv_stat( p_adapter, IP_STAT_BCAST_BYTES, &oid_info ); + break; + + case OID_GEN_BROADCAST_FRAMES_RCV: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_GEN_BROADCAST_FRAMES_RCV\n", port_num) ); + src_buf = NULL; + status = ipoib_get_recv_stat( p_adapter, IP_STAT_BCAST_FRAMES, &oid_info ); + break; + + /* Required Ethernet operational characteristics */ + case OID_802_3_PERMANENT_ADDRESS: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_802_3_PERMANENT_ADDRESS\n", port_num) ); + src_buf = &p_adapter->mac; + buf_len = sizeof(p_adapter->mac); + break; + + case OID_802_3_CURRENT_ADDRESS: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_802_3_CURRENT_ADDRESS\n", port_num) ); + src_buf = &p_adapter->params.conf_mac; + buf_len = sizeof(p_adapter->params.conf_mac); + break; + + case OID_802_3_MULTICAST_LIST: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_802_3_MULTICAST_LIST\n", port_num) ); + src_buf = p_adapter->mcast_array; + buf_len = p_adapter->mcast_array_size * sizeof(mac_addr_t); + break; + + case OID_802_3_MAXIMUM_LIST_SIZE: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_802_3_MAXIMUM_LIST_SIZE\n", port_num) ); + info = MAX_MCAST; + break; + + case OID_802_3_MAC_OPTIONS: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_802_3_MAC_OPTIONS\n", port_num) ); + info = 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: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_802_3_RCV_ERROR_ALIGNMENT or " + "OID_802_3_XMIT_ONE_COLLISION or " + "OID_802_3_XMIT_MORE_COLLISIONS\n", port_num) ); + info = 0; + break; + + case OID_TCP_TASK_OFFLOAD: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_TCP_TASK_OFFLOAD\n", port_num) ); + src_buf = NULL; + status = __ipoib_get_tcp_task_offload( p_adapter, &oid_info ); + break; + + /* Optional General */ + case OID_GEN_SUPPORTED_GUIDS: +#ifdef NDIS51_MINIPORT + case OID_GEN_VLAN_ID: +#endif + + /* 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; + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received an unsupported oid of 0x%.8X!\n", port_num, oid) ); + break; + + case OID_GEN_PROTOCOL_OPTIONS: + case OID_GEN_NETWORK_LAYER_ADDRESSES: + case OID_GEN_TRANSPORT_HEADER_OFFSET: + case OID_PNP_ENABLE_WAKE_UP: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_GEN_PROTOCOL_OPTIONS or OID_GEN_NETWORK_LAYER_ADDRESSES or OID_GEN_TRANSPORT_HEADER_OFFSET OID_PNP_ENABLE_WAKE_UPn", port_num) ); + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Number of OID: 0x%.8X!\n", oid) ); + status = NDIS_STATUS_SUCCESS; + break; + + case OID_PNP_QUERY_POWER: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_TCP_TASK_OFFLOAD\n", port_num) ); + // Status is pre-set in this routine to Success + status = NDIS_STATUS_SUCCESS; + break; + + case OID_TCP_OFFLOAD_CURRENT_CONFIG: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_PNP_QUERY_POWER\n", port_num) ); + //ulBytesAvailable = ulInfoLen = sizeof(NDIS_OFFLOAD); + if (info_buf_len < sizeof(NDIS_OFFLOAD)) + { + status = NDIS_STATUS_BUFFER_TOO_SHORT; + *p_bytes_needed = sizeof(NDIS_OFFLOAD) ; + break; + } + + //ipoib_offload_config(pPort, &offload); + //pInfo = &offload; + break; + + default: + status = NDIS_STATUS_INVALID_OID; + // IPOIB_PRINT( TRACE_LEVEL_ERROR,IPOIB_DBG_OID, + // ("Port %d received an invalid oid of 0x%.8X!\n", port_num, 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 + */ + if( status != NDIS_STATUS_PENDING ) + { + ipoib_complete_query( + p_adapter, &oid_info, status, src_buf, buf_len ); + return status; + } + + IPOIB_EXIT( IPOIB_DBG_OID ); + return NDIS_STATUS_PENDING; + } + + +static void +ipoib_complete_query( + IN ipoib_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; + + IPOIB_ENTER( IPOIB_DBG_OID ); + + CL_ASSERT( status != NDIS_STATUS_PENDING ); + + if( status == NDIS_STATUS_SUCCESS ) + { + if( p_oid_info->buf_len < buf_len ) + { + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_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 + { + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Returning NDIS_NOT_ACCEPTED") ); + oid_status = NDIS_STATUS_NOT_ACCEPTED; + } + } + else + { + *p_oid_info->p_bytes_used = 0; + } + + if (p_adapter->query_oid.p_pending_oid) + { + NdisMOidRequestComplete(p_adapter->h_adapter,p_adapter->query_oid.p_pending_oid,oid_status); + p_adapter->query_oid.p_pending_oid = NULL; + } + p_adapter->pending_query = FALSE; + + IPOIB_EXIT( IPOIB_DBG_OID ); +} + + +static NDIS_STATUS +__ipoib_get_tcp_task_offload( + IN ipoib_adapter_t* p_adapter, + OUT pending_oid_t *pNdisRequest ) +{ +#ifndef NDIS60_MINIPORT + NDIS_TASK_OFFLOAD_HEADER *p_offload_hdr; + NDIS_TASK_OFFLOAD *p_offload_task; + NDIS_TASK_TCP_IP_CHECKSUM *p_offload_chksum; + + NDIS_TASK_TCP_LARGE_SEND *p_offload_lso; + ULONG buf_len; + + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received query for OID_TCP_TASK_OFFLOAD\n", + p_adapter->guids.port_num) ); + + buf_len = sizeof(NDIS_TASK_OFFLOAD_HEADER) + + offsetof( NDIS_TASK_OFFLOAD, TaskBuffer ) + + sizeof(NDIS_TASK_TCP_IP_CHECKSUM) + + (p_adapter->params.lso ? + sizeof(NDIS_TASK_OFFLOAD) + sizeof(NDIS_TASK_TCP_LARGE_SEND) + : 0); + + pNdisRequest->DATA.QUERY_INFORMATION.BytesNeeded = buf_len; + + if( pNdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength < buf_len ) + return NDIS_STATUS_INVALID_LENGTH; + + p_offload_hdr = (NDIS_TASK_OFFLOAD_HEADER*)pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer; + 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; + } + + 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 = + p_offload_chksum->V4Transmit.TcpOptionsSupported = + p_offload_chksum->V4Transmit.TcpChecksum = + p_offload_chksum->V4Transmit.UdpChecksum = + p_offload_chksum->V4Transmit.IpChecksum = + !!(p_adapter->params.send_chksum_offload); + + 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_adapter->params.recv_chksum_offload); + + p_offload_chksum->V6Transmit.IpOptionsSupported = FALSE; + p_offload_chksum->V6Transmit.TcpOptionsSupported = FALSE; + p_offload_chksum->V6Transmit.TcpChecksum = FALSE; + p_offload_chksum->V6Transmit.UdpChecksum = FALSE; + + p_offload_chksum->V6Receive.IpOptionsSupported = FALSE; + p_offload_chksum->V6Receive.TcpOptionsSupported = FALSE; + p_offload_chksum->V6Receive.TcpChecksum = FALSE; + p_offload_chksum->V6Receive.UdpChecksum = FALSE; + + + if (p_adapter->params.lso) { + // set the previous pointer to the correct place + p_offload_task->OffsetNextTask = FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer) + + p_offload_task->TaskBufferLength; + // set the LSO packet + p_offload_task = (PNDIS_TASK_OFFLOAD) + ((PUCHAR)p_offload_task + p_offload_task->OffsetNextTask); + + p_offload_task->Version = NDIS_TASK_OFFLOAD_VERSION; + p_offload_task->Size = sizeof(NDIS_TASK_OFFLOAD); + p_offload_task->Task = TcpLargeSendNdisTask; + p_offload_task->OffsetNextTask = 0; + p_offload_task->TaskBufferLength = sizeof(NDIS_TASK_TCP_LARGE_SEND); + + p_offload_lso = (PNDIS_TASK_TCP_LARGE_SEND) p_offload_task->TaskBuffer; + + p_offload_lso->Version = 0; + //TODO optimal size: 60000, 64000 or 65536 + //TODO LSO_MIN_SEG_COUNT to be 1 + p_offload_lso->MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE; +#define LSO_MIN_SEG_COUNT 2 + p_offload_lso->MinSegmentCount = LSO_MIN_SEG_COUNT; + p_offload_lso->TcpOptions = TRUE; + p_offload_lso->IpOptions = TRUE; + } + + pNdisRequest->DATA.QUERY_INFORMATION.BytesWritten = buf_len + + return NDIS_STATUS_SUCCESS; +#endif + UNUSED_PARAM(p_adapter); + UNUSED_PARAM(pNdisRequest); + return NDIS_STATUS_NOT_SUPPORTED; + +} + + +static NDIS_STATUS +__ipoib_set_tcp_task_offload( + IN ipoib_adapter_t* p_adapter, + IN void* const p_info_buf, + IN ULONG* const p_info_len ) +{ +#ifndef NDIS60_MINIPORT + NDIS_TASK_OFFLOAD_HEADER *p_offload_hdr; + NDIS_TASK_OFFLOAD *p_offload_task; + NDIS_TASK_TCP_IP_CHECKSUM *p_offload_chksum; + + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received set for OID_TCP_TASK_OFFLOAD\n", + p_adapter->guids.port_num) ); + + 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; + + if( !p_adapter->params.send_chksum_offload && + (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) ) + { + return NDIS_STATUS_NOT_SUPPORTED; + } + + if( !p_adapter->params.recv_chksum_offload && + (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) ) + { + return NDIS_STATUS_NOT_SUPPORTED; + } + + return NDIS_STATUS_SUCCESS; +#endif + UNUSED_PARAM(p_adapter); + UNUSED_PARAM(p_info_buf); + UNUSED_PARAM(p_info_len); + return NDIS_STATUS_NOT_SUPPORTED; +} + + +//! 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 +ipoib_reset( + IN NDIS_HANDLE adapter_context, + OUT PBOOLEAN p_addr_reset) +{ + ipoib_adapter_t* p_adapter; + + IPOIB_ENTER( IPOIB_DBG_INIT ); +//return NDIS_STATUS_SUCCESS; + CL_ASSERT( p_addr_reset ); + CL_ASSERT( adapter_context ); + p_adapter = (ipoib_adapter_t*)adapter_context; + + switch( ipoib_reset_adapter( p_adapter ) ) + { + case IB_NOT_DONE: + IPOIB_EXIT( IPOIB_DBG_INIT ); + return NDIS_STATUS_PENDING; + + case IB_SUCCESS: + IPOIB_EXIT( IPOIB_DBG_INIT ); + *p_addr_reset = TRUE; + return NDIS_STATUS_SUCCESS; + + case IB_INVALID_STATE: + IPOIB_EXIT( IPOIB_DBG_INIT ); + return NDIS_STATUS_RESET_IN_PROGRESS; + + default: + IPOIB_EXIT( IPOIB_DBG_INIT ); + 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 +ipoib_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 ) +{ + ipoib_adapter_t* p_adapter; + NDIS_STATUS status; + + ULONG buf_len; + uint8_t port_num; + + KLOCK_QUEUE_HANDLE hdl; + + IPOIB_ENTER( IPOIB_DBG_OID ); + + CL_ASSERT( adapter_context ); + p_adapter = (ipoib_adapter_t*)adapter_context; + + 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); + + port_num = p_adapter->guids.port_num; + + cl_obj_lock( &p_adapter->obj ); + + if( p_adapter->state == IB_PNP_PORT_REMOVE ) + { + *p_bytes_read = 0; + cl_obj_unlock( &p_adapter->obj ); + return NDIS_STATUS_NOT_ACCEPTED; + } + + cl_obj_unlock( &p_adapter->obj ); + + switch( oid ) + { + /* Required General */ + case OID_GEN_CURRENT_PACKET_FILTER: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received set for OID_GEN_CURRENT_PACKET_FILTER\n", port_num)); + if( info_buf_len < sizeof(p_adapter->packet_filter) ) + { + status = NDIS_STATUS_INVALID_LENGTH; + } + else if( !info_buf ) + { + status = NDIS_STATUS_INVALID_DATA; + } + else + { + KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl ); + cl_obj_lock( &p_adapter->obj ); + switch( p_adapter->state ) + { + case IB_PNP_PORT_ADD: + p_adapter->set_oid.oid = oid; + p_adapter->set_oid.p_buf = info_buf; + p_adapter->set_oid.buf_len = info_buf_len; + p_adapter->set_oid.p_bytes_used = p_bytes_read; + p_adapter->set_oid.p_bytes_needed = p_bytes_needed; + p_adapter->pending_set = TRUE; + status = NDIS_STATUS_PENDING; + break; + + case IB_PNP_PORT_REMOVE: + status = NDIS_STATUS_NOT_ACCEPTED; + break; + + default: + if( !p_adapter->packet_filter && (*(uint32_t*)info_buf) ) + { + cl_qlist_insert_tail( + &g_ipoib.adapter_list, &p_adapter->entry ); + + /* + * Filter was zero, now non-zero. Register IP addresses + * with SA. + */ + ipoib_reg_addrs( p_adapter ); + } + else if( p_adapter->packet_filter && !(*(uint32_t*)info_buf) ) + { + /* + * Filter was non-zero, now zero. Deregister IP addresses. + */ + ipoib_dereg_addrs( p_adapter ); + + ASSERT( cl_qlist_count( &g_ipoib.adapter_list ) ); + cl_qlist_remove_item( + &g_ipoib.adapter_list, &p_adapter->entry ); + } + + p_adapter->packet_filter = *(uint32_t*)info_buf; + } + cl_obj_unlock( &p_adapter->obj ); + KeReleaseInStackQueuedSpinLock( &hdl ); + } + break; + + case OID_GEN_CURRENT_LOOKAHEAD: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received set for OID_GEN_CURRENT_LOOKAHEAD\n", port_num)); + if( info_buf_len < buf_len ) + status = NDIS_STATUS_INVALID_LENGTH; + break; + + case OID_GEN_PROTOCOL_OPTIONS: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received set for OID_GEN_PROTOCOL_OPTIONS\n", port_num)); + if( info_buf_len < buf_len ) + status = NDIS_STATUS_INVALID_LENGTH; + break; + + case OID_GEN_NETWORK_LAYER_ADDRESSES: + status = __ipoib_set_net_addr( p_adapter, info_buf, info_buf_len, p_bytes_read, p_bytes_needed); + break; + +#ifdef NDIS51_MINIPORT + case OID_GEN_MACHINE_NAME: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID, + ("Port %d received set for OID_GEN_MACHINE_NAME\n", port_num) ); + break; +#endif + + /* Required Ethernet operational characteristics */ + case OID_802_3_MULTICAST_LIST: + IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID, + ("Port %d received set for OID_802_3_MULTICAST_LIST\n", port_num) ); + if( info_buf_len > MAX_MCAST * sizeof(mac_addr_t) ) + { + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d OID_802_3_MULTICAST_LIST - Multicast list full.\n", port_num) ); + status = NDIS_STATUS_MULTICAST_FULL; + *p_bytes_needed = MAX_MCAST * sizeof(mac_addr_t); + } + else if( info_buf_len % sizeof(mac_addr_t) ) + { + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d OID_802_3_MULTICAST_LIST - Invalid input buffer.\n", port_num) ); + status = NDIS_STATUS_INVALID_DATA; + } + else if( !info_buf && info_buf_len ) + { + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d OID_802_3_MULTICAST_LIST - Invalid input buffer.\n", port_num) ); + status = NDIS_STATUS_INVALID_DATA; + } + else + { + ipoib_refresh_mcast( p_adapter, (mac_addr_t*)info_buf, + (uint8_t)(info_buf_len / sizeof(mac_addr_t)) ); + + buf_len = info_buf_len; + /* + * Note that we don't return pending. It will likely take longer + * for our SA transactions to complete than NDIS will give us + * before reseting the adapter. If an SA failure is encountered, + * the adapter will be marked as hung and we will get reset. + */ + status = NDIS_STATUS_SUCCESS; + } + break; + + case OID_TCP_TASK_OFFLOAD: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received set for OID_TCP_TASK_OFFLOAD\n", port_num) ); + + buf_len = info_buf_len; + status = + __ipoib_set_tcp_task_offload( p_adapter, info_buf, &buf_len ); + break; + + /* Optional General */ + case OID_GEN_TRANSPORT_HEADER_OFFSET: +#ifdef NDIS51_MINIPORT + case OID_GEN_RNDIS_CONFIG_PARAMETER: + case OID_GEN_VLAN_ID: +#endif + status = NDIS_STATUS_NOT_SUPPORTED; + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received an unsupported oid of 0x%.8X!\n", port_num, oid)); + 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; + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received an invalid oid of 0x%.8X!\n", port_num, 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; + } + + IPOIB_EXIT( IPOIB_DBG_OID ); + return status; +} + +#ifdef NNN +NDIS_STATUS +ipoib_set_info( + ipoib_adapter_t* p_adapter, + IN PNDIS_OID_REQUEST pNdisRequest) +{ + NDIS_STATUS status; + NDIS_OID oid; + UINT info_buf_len; + UINT buf_len; + uint8_t port_num; + PVOID info_buf; + UINT *p_bytes_needed; + KLOCK_QUEUE_HANDLE hdl; + + IPOIB_ENTER( IPOIB_DBG_OID ); + + oid = pNdisRequest->DATA.SET_INFORMATION.Oid; + info_buf = pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer; + info_buf_len = pNdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength; + p_bytes_needed = &pNdisRequest->DATA.QUERY_INFORMATION.BytesNeeded; + status = NDIS_STATUS_SUCCESS; + + buf_len = sizeof(UINT); + port_num = p_adapter->guids.port_num; + + switch( oid ) + { + /* Required General */ + case OID_GEN_CURRENT_PACKET_FILTER: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received set for OID_GEN_CURRENT_PACKET_FILTER\n", port_num)); + if( info_buf_len < sizeof(p_adapter->packet_filter) ) + { + status = NDIS_STATUS_INVALID_LENGTH; + } + else if( !info_buf ) + { + status = NDIS_STATUS_INVALID_DATA; + } + else + { + KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl ); + cl_obj_lock( &p_adapter->obj ); + switch( p_adapter->state ) + { + case IB_PNP_PORT_ADD: + p_adapter->p_oid_request = pNdisRequest; + status = NDIS_STATUS_PENDING; + break; + + case IB_PNP_PORT_REMOVE: + status = NDIS_STATUS_NOT_ACCEPTED; + break; + + default: + if( !p_adapter->packet_filter && (*(uint32_t*)info_buf) ) + { + cl_qlist_insert_tail( + &g_ipoib.adapter_list, &p_adapter->entry ); + + /* + * Filter was zero, now non-zero. Register IP addresses + * with SA. + */ + ipoib_reg_addrs( p_adapter ); + } + else if( p_adapter->packet_filter && !(*(uint32_t*)info_buf) ) + { + /* + * Filter was non-zero, now zero. Deregister IP addresses. + */ + ipoib_dereg_addrs( p_adapter ); + + ASSERT( cl_qlist_count( &g_ipoib.adapter_list ) ); + cl_qlist_remove_item( + &g_ipoib.adapter_list, &p_adapter->entry ); + } + + p_adapter->packet_filter = *(uint32_t*)info_buf; + } + cl_obj_unlock( &p_adapter->obj ); + KeReleaseInStackQueuedSpinLock( &hdl ); + } + break; + + case OID_GEN_CURRENT_LOOKAHEAD: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received set for OID_GEN_CURRENT_LOOKAHEAD\n", port_num)); + if( info_buf_len < buf_len ) + status = NDIS_STATUS_INVALID_LENGTH; + break; + + case OID_GEN_PROTOCOL_OPTIONS: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received set for OID_GEN_PROTOCOL_OPTIONS\n", port_num)); + if( info_buf_len < buf_len ) + status = NDIS_STATUS_INVALID_LENGTH; + break; + + case OID_GEN_NETWORK_LAYER_ADDRESSES: + status = __ipoib_set_net_addr( p_adapter, pNdisRequest); + break; + + case OID_GEN_MACHINE_NAME: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID, + ("Port %d received set for OID_GEN_MACHINE_NAME\n", port_num) ); + break; + + + /* Required Ethernet operational characteristics */ + case OID_802_3_MULTICAST_LIST: + IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID, + ("Port %d received set for OID_802_3_MULTICAST_LIST\n", port_num) ); + if( info_buf_len > MAX_MCAST * sizeof(mac_addr_t) ) + { + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d OID_802_3_MULTICAST_LIST - Multicast list full.\n", port_num) ); + status = NDIS_STATUS_MULTICAST_FULL; + *p_bytes_needed = MAX_MCAST * sizeof(mac_addr_t); + } + else if( info_buf_len % sizeof(mac_addr_t) ) + { + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d OID_802_3_MULTICAST_LIST - Invalid input buffer.\n", port_num) ); + status = NDIS_STATUS_INVALID_DATA; + } + else if( !info_buf && info_buf_len ) + { + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d OID_802_3_MULTICAST_LIST - Invalid input buffer.\n", port_num) ); + status = NDIS_STATUS_INVALID_DATA; + } + else + { + ipoib_refresh_mcast( p_adapter, (mac_addr_t*)info_buf, + (uint8_t)(info_buf_len / sizeof(mac_addr_t)) ); + + buf_len = info_buf_len; + /* + * Note that we don't return pending. It will likely take longer + * for our SA transactions to complete than NDIS will give us + * before reseting the adapter. If an SA failure is encountered, + * the adapter will be marked as hung and we will get reset. + */ + status = NDIS_STATUS_SUCCESS; + } + break; + + case OID_TCP_TASK_OFFLOAD: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received set for OID_TCP_TASK_OFFLOAD\n", port_num) ); + + buf_len = info_buf_len; + status = + __ipoib_set_tcp_task_offload( p_adapter, pNdisRequest ); + break; + + /* Optional General */ + case OID_GEN_TRANSPORT_HEADER_OFFSET: +#ifdef NDIS51_MINIPORT + case OID_GEN_RNDIS_CONFIG_PARAMETER: + case OID_GEN_VLAN_ID: +#endif + status = NDIS_STATUS_NOT_SUPPORTED; + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received an unsupported oid of 0x%.8X!\n", port_num, oid)); + 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; + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received an invalid oid of 0x%.8X!\n", port_num, oid)); + break; + } + + if( status == NDIS_STATUS_SUCCESS ) + { + pNdisRequest->DATA.SET_INFORMATION.BytesRead = buf_len; + } + else + { + if( status == NDIS_STATUS_INVALID_LENGTH ) + { + if ( !*p_bytes_needed ) + { + *p_bytes_needed = buf_len; + } + } + + pNdisRequest->DATA.SET_INFORMATION.BytesRead = 0; + } + + IPOIB_EXIT( IPOIB_DBG_OID ); + return status; +} +#endif +static NDIS_STATUS +ipoib_oid_handler( + IN NDIS_HANDLE adapter_context, + IN PNDIS_OID_REQUEST pNdisRequest) +{ + NDIS_REQUEST_TYPE RequestType; + NDIS_STATUS status = NDIS_STATUS_SUCCESS; + + IPOIB_ENTER( IPOIB_DBG_OID ); + + RequestType = pNdisRequest->RequestType; + + switch(RequestType) + { + case NdisRequestSetInformation: + status = ipoib_set_info(adapter_context, + pNdisRequest->DATA.SET_INFORMATION.Oid, + pNdisRequest->DATA.SET_INFORMATION.InformationBuffer, + pNdisRequest->DATA.SET_INFORMATION.InformationBufferLength, + (PULONG)&pNdisRequest->DATA.SET_INFORMATION.BytesRead, + (PULONG)&pNdisRequest->DATA.SET_INFORMATION.BytesNeeded); + break; + + case NdisRequestQueryInformation: + case NdisRequestQueryStatistics: + status = ipoib_query_info(adapter_context, + pNdisRequest->DATA.QUERY_INFORMATION.Oid, + pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer, + pNdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength, + (PULONG)&pNdisRequest->DATA.QUERY_INFORMATION.BytesWritten, + (PULONG)&pNdisRequest->DATA.QUERY_INFORMATION.BytesNeeded); + + break; + + default: + status = NDIS_STATUS_NOT_SUPPORTED; + break; + } + IPOIB_EXIT( IPOIB_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 ipoib_adapter_t structure with per NIC state +@param packet_array Array of packets to send +@param numPackets Number of packets in the array +*/ +void +ipoib_send_net_buffer_list( + IN NDIS_HANDLE adapter_context, + IN PNET_BUFFER_LIST net_buffer_list, + IN NDIS_PORT_NUMBER port_num, + IN ULONG send_flags + ) +{ + ipoib_adapter_t *p_adapter; + ipoib_port_t *p_port; + ULONG send_complete_flags; + PNET_BUFFER_LIST curr_net_buffer_list; + PNET_BUFFER_LIST next_net_buffer_list; + NDIS_STATUS status = NDIS_STATUS_SUCCESS; + + UNREFERENCED_PARAMETER(port_num); + PERF_DECLARE( SendPackets ); + PERF_DECLARE( PortSend ); + + IPOIB_ENTER( IPOIB_DBG_SEND ); + cl_perf_start( SendPackets ); + + CL_ASSERT( adapter_context ); + p_adapter = (ipoib_adapter_t*)adapter_context; + p_port = p_adapter->p_port; + + cl_obj_lock( &p_adapter->obj ); + if( p_adapter->ipoib_state == IPOIB_PAUSING || + p_adapter->ipoib_state == IPOIB_PAUSED) + { + status = NDIS_STATUS_PAUSED; + cl_obj_unlock( &p_adapter->obj ); + goto compl_status; + } + + if( p_adapter->state != IB_PNP_PORT_ACTIVE || !p_adapter->p_port ) + { + cl_obj_unlock( &p_adapter->obj ); + status = NDIS_STATUS_FAILURE; + goto compl_status; + } + + p_port = p_adapter->p_port; + ipoib_port_ref( p_port, ref_send_packets ); + cl_obj_unlock( &p_adapter->obj ); + //IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + // ("Starting NET BUFFER LIST \n") ); + for (curr_net_buffer_list = net_buffer_list; + curr_net_buffer_list != NULL; + curr_net_buffer_list = next_net_buffer_list) + { + next_net_buffer_list = NET_BUFFER_LIST_NEXT_NBL(curr_net_buffer_list); + cl_perf_start( PortSend ); + + ipoib_port_send( p_port, curr_net_buffer_list, send_flags); + cl_perf_stop( &adapter->perf, PortSend ); + } + ipoib_port_deref( p_port, ref_send_packets ); + + cl_perf_stop( &p_adapter->perf, SendPackets ); + + cl_perf_log( &p_adapter->perf, SendBundle, num_packets ); + +compl_status: + if (status != NDIS_STATUS_SUCCESS) + { + //ASSERT(FALSE); //???? + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Got bad status \n") ); + send_complete_flags = 0; + + for (curr_net_buffer_list = net_buffer_list; + curr_net_buffer_list != NULL; + curr_net_buffer_list = next_net_buffer_list) + { + next_net_buffer_list = NET_BUFFER_LIST_NEXT_NBL(curr_net_buffer_list); + NET_BUFFER_LIST_STATUS(curr_net_buffer_list) = status; + ipoib_inc_send_stat( p_adapter, IP_STAT_DROPPED, 0 ); + } + + + if (NDIS_TEST_SEND_AT_DISPATCH_LEVEL(send_flags)) + { + NDIS_SET_SEND_COMPLETE_FLAG(send_complete_flags, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL); + } + + NdisMSendNetBufferListsComplete( + p_adapter->h_adapter, + net_buffer_list, + send_complete_flags); + } + IPOIB_EXIT( IPOIB_DBG_SEND ); +} + +void +ipoib_pnp_notify( + IN NDIS_HANDLE adapter_context, + IN PNET_DEVICE_PNP_EVENT pnp_event) +{ + ipoib_adapter_t *p_adapter; + + IPOIB_ENTER( IPOIB_DBG_PNP ); + + p_adapter = (ipoib_adapter_t*)adapter_context; + + IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_PNP, ("Event %d\n", pnp_event->DevicePnPEvent) ); + if( pnp_event->DevicePnPEvent != NdisDevicePnPEventPowerProfileChanged ) + { + cl_obj_lock( &p_adapter->obj ); + p_adapter->state = IB_PNP_PORT_REMOVE; + cl_obj_unlock( &p_adapter->obj ); + + ipoib_resume_oids( p_adapter ); + } + + IPOIB_EXIT( IPOIB_DBG_PNP ); +} + + +VOID +ipoib_shutdown_ex( + IN NDIS_HANDLE adapter_context, + IN NDIS_SHUTDOWN_ACTION shutdown_action) +{ + IPOIB_ENTER( IPOIB_DBG_INIT ); + UNUSED_PARAM( adapter_context ); + UNUSED_PARAM( shutdown_action ); + IPOIB_EXIT( IPOIB_DBG_INIT ); +} + + +void +ipoib_resume_oids( + IN ipoib_adapter_t* const p_adapter ) +{ + ULONG info; + NDIS_STATUS status; + boolean_t pending_query, pending_set; + pending_oid_t query_oid = {0}; + pending_oid_t set_oid = {0}; + KLOCK_QUEUE_HANDLE hdl; + + IPOIB_ENTER( IPOIB_DBG_INIT ); + + cl_obj_lock( &p_adapter->obj ); + /* + * Set the status depending on our state. Fail OID requests that + * are pending while we reset the adapter. + */ + switch( p_adapter->state ) + { + case IB_PNP_PORT_ADD: + status = NDIS_STATUS_FAILURE; + break; + + case IB_PNP_PORT_REMOVE: + status = NDIS_STATUS_NOT_ACCEPTED; + break; + + default: + status = NDIS_STATUS_SUCCESS; + } + + pending_query = p_adapter->pending_query; + if( pending_query ) + { + query_oid = p_adapter->query_oid; + p_adapter->pending_query = FALSE; + } + pending_set = p_adapter->pending_set; + if( pending_set ) + { + set_oid = p_adapter->set_oid; + p_adapter->pending_set = FALSE; + } + cl_obj_unlock( &p_adapter->obj ); + + /* + * 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_GEN_LINK_SPEED: + ipoib_complete_query( p_adapter, &query_oid, + status, &p_adapter->port_rate, sizeof(p_adapter->port_rate) ); + break; + + case OID_GEN_MEDIA_CONNECT_STATUS: + info = NdisMediaStateConnected; + ipoib_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 ); + break; + } + } + + if( pending_set ) + { + switch( set_oid.oid ) + { + case OID_GEN_CURRENT_PACKET_FILTER: + /* Validation already performed in the SetInformation path. */ + + KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl ); + cl_obj_lock( &p_adapter->obj ); + if( !p_adapter->packet_filter && (*(PULONG)set_oid.p_buf) ) + { + cl_qlist_insert_tail( + &g_ipoib.adapter_list, &p_adapter->entry ); + /* + * Filter was zero, now non-zero. Register IP addresses + * with SA. + */ + ipoib_reg_addrs( p_adapter ); + } + else if( p_adapter->packet_filter && !(*(PULONG)set_oid.p_buf) ) + { + /* Filter was non-zero, now zero. Deregister IP addresses. */ + ipoib_dereg_addrs( p_adapter ); + + ASSERT( cl_qlist_count( &g_ipoib.adapter_list ) ); + cl_qlist_remove_item( + &g_ipoib.adapter_list, &p_adapter->entry ); + } + p_adapter->packet_filter = *(PULONG)set_oid.p_buf; + + cl_obj_unlock( &p_adapter->obj ); + KeReleaseInStackQueuedSpinLock( &hdl ); + p_adapter->set_oid.p_pending_oid = NULL; + NdisMOidRequestComplete( p_adapter->h_adapter, set_oid.p_pending_oid, status ); + break; + + case OID_GEN_NETWORK_LAYER_ADDRESSES: + status = __ipoib_set_net_addr( p_adapter, + p_adapter->set_oid.p_buf, + p_adapter->set_oid.buf_len, + p_adapter->set_oid.p_bytes_used, + p_adapter->set_oid.p_bytes_needed ); + + if( status != NDIS_STATUS_PENDING ) + { + p_adapter->set_oid.p_pending_oid = NULL; + NdisMOidRequestComplete( p_adapter->h_adapter, set_oid.p_pending_oid, status ); + } + break; + + default: + CL_ASSERT( set_oid.oid && 0 ); + break; + } + } + + IPOIB_EXIT( IPOIB_DBG_INIT ); +} + + +static NDIS_STATUS +__ipoib_set_net_addr( + IN ipoib_adapter_t * p_adapter, + IN PVOID info_buf, + IN ULONG info_buf_len, + OUT PULONG p_bytes_read, + OUT PULONG p_bytes_needed ) +{ + NDIS_STATUS status; + PNETWORK_ADDRESS_LIST p_net_addrs; + PNETWORK_ADDRESS p_net_addr_oid; + PNETWORK_ADDRESS_IP p_ip_addr; + + net_address_item_t *p_addr_item; + + cl_status_t cl_status; + + size_t idx; + LONG i; + ULONG addr_size; + ULONG total_size; + + uint8_t port_num; + + IPOIB_ENTER( IPOIB_DBG_OID ); + + status = NDIS_STATUS_SUCCESS; + port_num = p_adapter->guids.port_num; + + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d received set for OID_GEN_NETWORK_LAYER_ADDRESSES\n", + port_num) ); + + if( !info_buf ) + { + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Port %d - OID_GEN_NETWORK_LAYER_ADDRESSES - " + "NULL buffer\n", port_num) ); + IPOIB_EXIT( IPOIB_DBG_OID ); + return NDIS_STATUS_INVALID_DATA; + } + + /* + * Must use field offset because the structures define array's of size one + * of a the incorrect type for what is really stored. + */ + if( info_buf_len < FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address) ) + { + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - " + "bad length of %d, not enough " + "for NETWORK_ADDRESS_LIST (%d)\n", port_num, info_buf_len, + FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address)) ); + *p_bytes_needed = FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address); + IPOIB_EXIT( IPOIB_DBG_OID ); + return NDIS_STATUS_INVALID_LENGTH; + } + + p_net_addrs = (PNETWORK_ADDRESS_LIST)info_buf; + if( p_net_addrs->AddressCount == 0) + { + if( p_net_addrs->AddressType == NDIS_PROTOCOL_ID_TCP_IP ) + { + IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID, + ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - " + "clear TCP/IP addresses\n", port_num) ); + } + else + { + IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID, + ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - " + "Non TCP/IP address type of 0x%.4X on clear\n", + port_num, p_net_addrs->AddressType) ); + IPOIB_EXIT( IPOIB_DBG_OID ); + return NDIS_STATUS_SUCCESS; + } + } + + addr_size = FIELD_OFFSET(NETWORK_ADDRESS, Address) + + NETWORK_ADDRESS_LENGTH_IP; + total_size = FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address) + + addr_size * p_net_addrs->AddressCount; + + if( info_buf_len < total_size ) + { + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - " + "bad length of %d, %d required for %d addresses\n", + port_num, info_buf_len, total_size, p_net_addrs->AddressCount) ); + *p_bytes_needed = total_size; + IPOIB_EXIT( IPOIB_DBG_OID ); + return NDIS_STATUS_INVALID_LENGTH; + } + + /* Lock lists for duration since SA callbacks can occur on other CPUs */ + cl_obj_lock( &p_adapter->obj ); + + /* Set the capacity of the vector to accomodate all assinged addresses. */ + cl_status = cl_vector_set_capacity( + &p_adapter->ip_vector, p_net_addrs->AddressCount ); + if( cl_status != CL_SUCCESS ) + { + cl_obj_unlock( &p_adapter->obj ); + IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Port %d - OID_GEN_NETWORK_LAYER_ADDRESSES - " + "Failed to set IP vector capacity: %#x\n", port_num, + cl_status) ); + IPOIB_EXIT( IPOIB_DBG_OID ); + return NDIS_STATUS_RESOURCES; + } + + *p_bytes_read = total_size; + + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - List contains %d addresses\n", + port_num, p_net_addrs->AddressCount)); + + /* First look for addresses we had that should be removed */ + for( idx = 0; idx != cl_vector_get_size( &p_adapter->ip_vector ); idx++ ) + { + p_addr_item = (net_address_item_t*) + cl_vector_get_ptr( &p_adapter->ip_vector, idx ); + p_net_addr_oid = (PNETWORK_ADDRESS)p_net_addrs->Address; + + for( i = 0; i < p_net_addrs->AddressCount; ++i, p_net_addr_oid = + (PNETWORK_ADDRESS)((uint8_t *)p_net_addr_oid + + FIELD_OFFSET(NETWORK_ADDRESS, Address) + + p_net_addr_oid->AddressLength) ) + { + + if( p_net_addr_oid->AddressType != NDIS_PROTOCOL_ID_TCP_IP ) + { + IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_OID, + ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Address %d is wrong type of 0x%.4X, " + "should be 0x%.4X\n", port_num, i, p_net_addr_oid->AddressType, + NDIS_PROTOCOL_ID_TCP_IP)); + continue; + } + + if( p_net_addr_oid->AddressLength != NETWORK_ADDRESS_LENGTH_IP) + { + IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_OID, + ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Address %d is wrong size of %d, " + "should be %d\n", port_num, i, p_net_addr_oid->AddressLength, + NETWORK_ADDRESS_LENGTH_IP)); + continue; + } + + p_ip_addr = (PNETWORK_ADDRESS_IP)p_net_addr_oid->Address; + if( !cl_memcmp( &p_ip_addr->in_addr, + &p_addr_item->address.as_ulong, sizeof(ULONG) ) ) + { + break; + } + } + + if( i == p_net_addrs->AddressCount ) + { + /* Didn't find a match, delete from SA */ + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Deleting Address %d.%d.%d.%d\n", + port_num, + p_addr_item->address.as_bytes[0], + p_addr_item->address.as_bytes[1], + p_addr_item->address.as_bytes[2], + p_addr_item->address.as_bytes[3])); + + if( p_addr_item->p_reg ) + { + if( p_addr_item->p_reg->h_reg_svc ) + { + p_adapter->p_ifc->dereg_svc( + p_addr_item->p_reg->h_reg_svc, __ipoib_ats_dereg_cb ); + } + else + { + cl_free( p_addr_item->p_reg ); + } + p_addr_item->p_reg = NULL; + } + p_addr_item->address.as_ulong = 0; + } + } + + /* Now look for new addresses */ + p_net_addr_oid = (NETWORK_ADDRESS *)p_net_addrs->Address; + idx = 0; + for( i = 0; i < p_net_addrs->AddressCount; i++, p_net_addr_oid = + (PNETWORK_ADDRESS)((uint8_t *)p_net_addr_oid + + FIELD_OFFSET(NETWORK_ADDRESS, Address) + p_net_addr_oid->AddressLength) ) + { + + if( p_net_addr_oid->AddressType != NDIS_PROTOCOL_ID_TCP_IP ) + { + IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID, + ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Address %d is wrong type of 0x%.4X, " + "should be 0x%.4X\n", port_num, i, p_net_addr_oid->AddressType, + NDIS_PROTOCOL_ID_TCP_IP)); + continue; + } + + if( p_net_addr_oid->AddressLength != NETWORK_ADDRESS_LENGTH_IP) + { + IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID, + ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Address %d is wrong size of %d, " + "should be %d\n", port_num, i, p_net_addr_oid->AddressLength, + NETWORK_ADDRESS_LENGTH_IP)); + continue; + } + + p_ip_addr = (PNETWORK_ADDRESS_IP)p_net_addr_oid->Address; + + /* Size the vector as needed. */ + if( cl_vector_get_size( &p_adapter->ip_vector ) <= idx ) + cl_vector_set_size( &p_adapter->ip_vector, idx + 1 ); + + p_addr_item = (net_address_item_t *) cl_vector_get_ptr( &p_adapter->ip_vector, idx ); + if( !cl_memcmp( &p_ip_addr->in_addr, &p_addr_item->address.as_ulong, + sizeof(ULONG) ) ) + { + idx++; + /* Already have this address - no change needed */ + continue; + } + + /* + * Copy the address information, but don't register yet - the port + * could be down. + */ + if( p_addr_item->p_reg ) + { + /* If in use by some other address, deregister. */ + if( p_addr_item->p_reg->h_reg_svc ) + { + p_adapter->p_ifc->dereg_svc( + p_addr_item->p_reg->h_reg_svc, __ipoib_ats_dereg_cb ); + } + else + { + cl_free( p_addr_item->p_reg ); + } + p_addr_item->p_reg = NULL; + } + memcpy ((void *)&p_addr_item->address.as_ulong, (const void *)&p_ip_addr->in_addr, sizeof(ULONG) ); + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Adding Address %d.%d.%d.%d\n", + port_num, + p_addr_item->address.as_bytes[0], + p_addr_item->address.as_bytes[1], + p_addr_item->address.as_bytes[2], + p_addr_item->address.as_bytes[3]) ); + idx++; + } + + /* Now clear any extra entries that shouldn't be there. */ + while( idx < cl_vector_get_size( &p_adapter->ip_vector ) ) + { + p_addr_item = (net_address_item_t*) + cl_vector_get_ptr( &p_adapter->ip_vector, + cl_vector_get_size( &p_adapter->ip_vector ) - 1 ); + + if( p_addr_item->p_reg ) + { + if( p_addr_item->p_reg->h_reg_svc ) + { + p_adapter->p_ifc->dereg_svc( + p_addr_item->p_reg->h_reg_svc, __ipoib_ats_dereg_cb ); + } + else + { + cl_free( p_addr_item->p_reg ); + } + p_addr_item->p_reg = NULL; + p_addr_item->address.as_ulong = 0; + } + + /* No need to check return value - shrinking always succeeds. */ + cl_vector_set_size( &p_adapter->ip_vector, + cl_vector_get_size( &p_adapter->ip_vector ) - 1 ); + } + + if( p_adapter->state == IB_PNP_PORT_ACTIVE && p_adapter->packet_filter ) + ipoib_reg_addrs( p_adapter ); + + cl_obj_unlock( &p_adapter->obj ); + + IPOIB_EXIT( IPOIB_DBG_OID ); + return NDIS_STATUS_SUCCESS; +} + + +/* Object lock is held when this function is called. */ +void +ipoib_reg_addrs( + IN ipoib_adapter_t* const p_adapter ) +{ + net_address_item_t *p_addr_item; + + size_t idx; + + uint8_t port_num; + + ib_api_status_t ib_status; + ib_reg_svc_req_t ib_service; + ib_gid_t port_gid; + + IPOIB_ENTER( IPOIB_DBG_OID ); + + if(p_adapter->guids.port_guid.pkey != IB_DEFAULT_PKEY) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR,IPOIB_DBG_ERROR, + ("ATS Service available for default pkey only\n")); + return; + } + port_num = p_adapter->guids.port_num; + + /* Setup our service call with things common to all calls */ + cl_memset( &ib_service, 0, sizeof(ib_service) ); + + /* BUGBUG Only register local subnet GID prefix for now */ + ib_gid_set_default( &port_gid, p_adapter->guids.port_guid.guid ); + ib_service.svc_rec.service_gid = port_gid; + + ib_service.svc_rec.service_pkey = IB_DEFAULT_PKEY; + ib_service.svc_rec.service_lease = IB_INFINITE_SERVICE_LEASE; + + /* Must cast here because the service name is an array of unsigned chars but + * strcpy want a pointer to a signed char */ + if ( StringCchCopy( (char *)ib_service.svc_rec.service_name, + sizeof(ib_service.svc_rec.service_name) / sizeof(char), ATS_NAME ) != S_OK) { + ASSERT(FALSE); + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR,IPOIB_DBG_ERROR, + ("Problem copying ATS name: exiting\n")); + return; + } + + /* IP Address in question will be put in below */ + ib_service.port_guid = p_adapter->guids.port_guid.guid; + ib_service.timeout_ms = p_adapter->params.sa_timeout; + ib_service.retry_cnt = p_adapter->params.sa_retry_cnt; + + /* Can't set IB_FLAGS_SYNC here because I can't wait at dispatch */ + ib_service.flags = 0; + + /* Service context will be put in below */ + + ib_service.svc_data_mask = IB_SR_COMPMASK_SID | + IB_SR_COMPMASK_SGID | + IB_SR_COMPMASK_SPKEY | + IB_SR_COMPMASK_SLEASE | + IB_SR_COMPMASK_SNAME | + IB_SR_COMPMASK_SDATA8_12 | + IB_SR_COMPMASK_SDATA8_13 | + IB_SR_COMPMASK_SDATA8_14 | + IB_SR_COMPMASK_SDATA8_15; + ib_service.pfn_reg_svc_cb = __ipoib_ats_reg_cb; + + for( idx = 0; idx < cl_vector_get_size( &p_adapter->ip_vector); idx++ ) + { + p_addr_item = (net_address_item_t*) + cl_vector_get_ptr( &p_adapter->ip_vector, idx ); + + if( p_addr_item->p_reg ) + continue; + + p_addr_item->p_reg = (ats_reg_t *) cl_zalloc( sizeof(ats_reg_t) ); + if( !p_addr_item->p_reg ) + break; + + p_addr_item->p_reg->p_adapter = p_adapter; + + ib_service.svc_context = p_addr_item->p_reg; + + ib_service.svc_rec.service_id = + ATS_SERVICE_ID & CL_HTON64(0xFFFFFFFFFFFFFF00); + /* ATS service IDs start at 0x10000CE100415453 */ + ib_service.svc_rec.service_id |= ((uint64_t)(idx + 0x53)) << 56; + + cl_memcpy( &ib_service.svc_rec.service_data8[ATS_IPV4_OFFSET], + p_addr_item->address.as_bytes, IPV4_ADDR_SIZE ); + + /* Take a reference for each service request. */ + cl_obj_ref(&p_adapter->obj); + ib_status = p_adapter->p_ifc->reg_svc( + p_adapter->h_al, &ib_service, &p_addr_item->p_reg->h_reg_svc ); + if( ib_status != IB_SUCCESS ) + { + if( ib_status == IB_INVALID_GUID ) + { + /* If this occurs, we log the error but do not fail the OID yet */ + IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_OID, + ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - " + "Failed to register IP Address " + "of %d.%d.%d.%d with error IB_INVALID_GUID\n", + port_num, + p_addr_item->address.as_bytes[0], + p_addr_item->address.as_bytes[1], + p_addr_item->address.as_bytes[2], + p_addr_item->address.as_bytes[3]) ); + } + else + { + /* Fatal error. */ + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Failed to register IP Address " + "of %d.%d.%d.%d with error %s\n", + port_num, + p_addr_item->address.as_bytes[0], + p_addr_item->address.as_bytes[1], + p_addr_item->address.as_bytes[2], + p_addr_item->address.as_bytes[3], + p_adapter->p_ifc->get_err_str( ib_status )) ); + p_adapter->hung = TRUE; + } + cl_obj_deref(&p_adapter->obj); + cl_free( p_addr_item->p_reg ); + p_addr_item->p_reg = NULL; + } + } + + IPOIB_EXIT( IPOIB_DBG_OID ); +} + + +/* Object lock is held when this function is called. */ +void +ipoib_dereg_addrs( + IN ipoib_adapter_t* const p_adapter ) +{ + net_address_item_t *p_addr_item; + + size_t idx; + + IPOIB_ENTER( IPOIB_DBG_OID ); + + for( idx = 0; idx < cl_vector_get_size( &p_adapter->ip_vector); idx++ ) + { + p_addr_item = (net_address_item_t*) + cl_vector_get_ptr( &p_adapter->ip_vector, idx ); + + if( !p_addr_item->p_reg ) + continue; + + if( p_addr_item->p_reg->h_reg_svc ) + { + p_adapter->p_ifc->dereg_svc( + p_addr_item->p_reg->h_reg_svc, __ipoib_ats_dereg_cb ); + } + else + { + cl_free( p_addr_item->p_reg ); + } + p_addr_item->p_reg = NULL; + } + + IPOIB_EXIT( IPOIB_DBG_OID ); +} + + +void +ipoib_cancel_xmit( + IN NDIS_HANDLE adapter_context, + IN PVOID cancel_id ) +{ +/* ipoib_adapter_t* const p_adapter = + (ipoib_adapter_t* const )adapter_context; + + +if 0 + if( p_adapter && p_adapter->p_port ) + { + ipoib_port_cancel_xmit( p_adapter->p_port, cancel_id ); + } +endif +*/ + + UNUSED_PARAM(adapter_context); + UNUSED_PARAM(cancel_id); + + return; //TODO return this functionality + +} + + +static void +__ipoib_ats_reg_cb( + IN ib_reg_svc_rec_t *p_reg_svc_rec ) +{ + ats_reg_t *p_reg; + uint8_t port_num; + + IPOIB_ENTER( IPOIB_DBG_OID ); + + CL_ASSERT( p_reg_svc_rec ); + CL_ASSERT( p_reg_svc_rec->svc_context ); + + p_reg = (ats_reg_t*)p_reg_svc_rec->svc_context; + port_num = p_reg->p_adapter->guids.port_num; + + cl_obj_lock( &p_reg->p_adapter->obj ); + + if( p_reg_svc_rec->req_status == IB_SUCCESS && + !p_reg_svc_rec->resp_status ) + { + IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, + ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Registered IP Address " + "of %d.%d.%d.%d\n", + port_num, + p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET], + p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+1], + p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+2], + p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+3]) ); + } + else if( p_reg_svc_rec->req_status != IB_CANCELED ) + { + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_OID, + ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Failed to register IP Address " + "of %d.%d.%d.%d with error %s\n", + port_num, + p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET], + p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+1], + p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+2], + p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+3], + p_reg->p_adapter->p_ifc->get_err_str((ib_api_status_t) p_reg_svc_rec->resp_status )) ); + p_reg->p_adapter->hung = TRUE; + p_reg->h_reg_svc = NULL; + } + + cl_obj_unlock( &p_reg->p_adapter->obj ); + cl_obj_deref(&p_reg->p_adapter->obj); + + IPOIB_EXIT( IPOIB_DBG_OID ); +} + + +static void +__ipoib_ats_dereg_cb( + IN void *context ) +{ + cl_free( context ); +} + +static NDIS_STATUS +ipoib_pause( + IN NDIS_HANDLE adapter_context, + IN PNDIS_MINIPORT_PAUSE_PARAMETERS pause_parameters) +{ + ipoib_adapter_t *p_adapter; + KLOCK_QUEUE_HANDLE hdl; + + UNREFERENCED_PARAMETER(pause_parameters); + IPOIB_ENTER( IPOIB_DBG_INIT ); +//return NDIS_STATUS_SUCCESS; + CL_ASSERT(adapter_context); + p_adapter = (ipoib_adapter_t*)adapter_context; + CL_ASSERT(p_adapter->ipoib_state == IPOIB_RUNNING); + + KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl ); + p_adapter->ipoib_state = IPOIB_PAUSING; + KeReleaseInStackQueuedSpinLock( &hdl ); + + //TODO: + ipoib_port_resume(p_adapter->p_port,FALSE); +// ASSERT(FALSE); + + KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl ); + p_adapter->ipoib_state = IPOIB_PAUSED; + KeReleaseInStackQueuedSpinLock( &hdl ); + + IPOIB_EXIT( IPOIB_DBG_INIT ); + return NDIS_STATUS_SUCCESS; +} + +static NDIS_STATUS +ipoib_restart( + IN NDIS_HANDLE adapter_context, + IN PNDIS_MINIPORT_RESTART_PARAMETERS restart_parameters) +{ + ipoib_adapter_t *p_adapter; + KLOCK_QUEUE_HANDLE hdl; + PNDIS_RESTART_ATTRIBUTES NdisRestartAttributes; + PNDIS_RESTART_GENERAL_ATTRIBUTES NdisGeneralAttributes; + + IPOIB_ENTER( IPOIB_DBG_INIT ); + p_adapter = (ipoib_adapter_t*)adapter_context; + + NdisRestartAttributes = restart_parameters->RestartAttributes; + + if (NdisRestartAttributes != NULL) + { + CL_ASSERT(NdisRestartAttributes->Oid == OID_GEN_MINIPORT_RESTART_ATTRIBUTES); + NdisGeneralAttributes = (PNDIS_RESTART_GENERAL_ATTRIBUTES)NdisRestartAttributes->Data; + // + // Check to see if we need to change any attributes + } + + KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl ); + p_adapter->ipoib_state = IPOIB_RUNNING; + KeReleaseInStackQueuedSpinLock( &hdl ); + + + IPOIB_EXIT( IPOIB_DBG_INIT ); + return NDIS_STATUS_SUCCESS; +} + +/*++ +Routine Description: + + This function aborts the request pending in the miniport. + +Arguments: + + MiniportAdapterContext Pointer to the adapter structure + RequestId Specify the request to be cancelled. + +Return Value: + +--*/ +static void +ipoib_cancel_oid_request( + IN NDIS_HANDLE adapter_context, + IN PVOID requestId + ) +{ + PNDIS_OID_REQUEST pending_request; + ipoib_adapter_t *p_adapter; + + IPOIB_ENTER( IPOIB_DBG_OID ); + p_adapter = (ipoib_adapter_t*)adapter_context; + + cl_obj_lock( &p_adapter->obj ); + + if ( p_adapter->query_oid.p_pending_oid && + p_adapter->query_oid.p_pending_oid->RequestId == requestId) + { + pending_request = p_adapter->query_oid.p_pending_oid; + p_adapter->query_oid.p_pending_oid = NULL; + p_adapter->pending_query = FALSE; + } + else if(p_adapter->set_oid.p_pending_oid && + p_adapter->set_oid.p_pending_oid->RequestId == requestId) + { + pending_request = p_adapter->set_oid.p_pending_oid; + p_adapter->set_oid.p_pending_oid = NULL; + p_adapter->pending_set = FALSE; + } + else + { + cl_obj_unlock( &p_adapter->obj ); + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("No Pending OID found\n") ); + return; + } + cl_obj_unlock( &p_adapter->obj ); + + NdisMOidRequestComplete(p_adapter->h_adapter, + pending_request, + NDIS_STATUS_REQUEST_ABORTED); + + IPOIB_EXIT( IPOIB_DBG_OID ); +} diff --git a/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_endpoint.c b/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_endpoint.c deleted file mode 100644 index 1e82e5a5..00000000 --- a/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_endpoint.c +++ /dev/null @@ -1,1170 +0,0 @@ -/* - * Copyright (c) 2005 SilverStorm Technologies. All rights reserved. - * Copyright (c) 2006 Mellanox Technologies. All rights reserved. - * Portions Copyright (c) 2008 Microsoft 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: ipoib_endpoint.c 4226 2009-04-06 06:01:03Z xalex $ - */ - - - -#include "ipoib_endpoint.h" -#include "ipoib_port.h" -#include "ipoib_debug.h" -#if defined(EVENT_TRACING) -#ifdef offsetof -#undef offsetof -#endif -#include "ipoib_endpoint.tmh" -#endif -#include -#include - - -static void -__endpt_destroying( - IN cl_obj_t* p_obj ); - -static void -__endpt_cleanup( - IN cl_obj_t* p_obj ); - -static void -__endpt_free( - IN cl_obj_t* p_obj ); - -static ib_api_status_t -__create_mcast_av( - IN ib_pd_handle_t h_pd, - IN uint8_t port_num, - IN ib_member_rec_t* const p_member_rec, - OUT ib_av_handle_t* const ph_av ); - -static inline ipoib_port_t* -__endpt_parent( - IN ipoib_endpt_t* const p_endpt ); - -static void -__path_query_cb( - IN ib_query_rec_t *p_query_rec ); - -static void -__endpt_resolve( - IN ipoib_endpt_t* const p_endpt ); - -static void -__endpt_cm_send_cb( - IN const ib_cq_handle_t h_cq, - IN void *cq_context ); -static void -__endpt_cm_recv_cb( - IN const ib_cq_handle_t h_cq, - IN void *cq_context ); - -static void -__endpt_cm_buf_mgr_construct( - IN endpt_buf_mgr_t * const p_buf_mgr ); -static void -__conn_reply_cb( - IN ib_cm_rep_rec_t *p_cm_rep ); - -static void -__conn_mra_cb( - IN ib_cm_mra_rec_t *p_mra_rec ); - -static void -__conn_rej_cb( - IN ib_cm_rej_rec_t *p_rej_rec ); - -static void -__conn_dreq_cb( - IN ib_cm_dreq_rec_t *p_dreq_rec ); - -#if 0 //CM -static cl_status_t -__cm_recv_desc_ctor( - IN void* const p_object, - IN void* context, - OUT cl_pool_item_t** const pp_pool_item ); - -static void -__cm_recv_desc_dtor( - IN const cl_pool_item_t* const p_pool_item, - IN void *context ); - -static NDIS_PACKET* -__endpt_cm_get_ndis_pkt( - IN ipoib_port_t* const p_port, - IN ipoib_cm_desc_t* const p_desc ); - -static inline ipoib_cm_desc_t* -__endpt_cm_buf_mgr_get_recv( - IN endpt_buf_mgr_t * const p_buf_mgr ); - -static boolean_t -__cm_recv_is_dhcp( - IN const ipoib_pkt_t* const p_ipoib ); - -static ib_api_status_t -__endpt_cm_recv_arp( - IN ipoib_port_t* const p_port, - IN const ipoib_pkt_t* const p_ipoib, - OUT eth_pkt_t* const p_eth, - IN ipoib_endpt_t* const p_src_endpt ); - -static ib_api_status_t -__endpt_cm_recv_udp( - IN ipoib_port_t* const p_port, - IN ib_wc_t* const p_wc, - IN const ipoib_pkt_t* const p_ipoib, - OUT eth_pkt_t* const p_eth, - IN ipoib_endpt_t* const p_src_endpt ); -#endif - -ipoib_endpt_t* -ipoib_endpt_create( - IN const ib_gid_t* const p_dgid, - IN const net16_t dlid, - IN const net32_t qpn ) -{ - ipoib_endpt_t *p_endpt; - cl_status_t status; - - IPOIB_ENTER( IPOIB_DBG_ENDPT ); - - p_endpt = cl_zalloc( sizeof(ipoib_endpt_t) ); - if( !p_endpt ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed to allocate endpoint (%d bytes)\n", - sizeof(ipoib_endpt_t)) ); - return NULL; - } - - cl_obj_construct( &p_endpt->obj, IPOIB_OBJ_ENDPOINT ); - - status = cl_obj_init( &p_endpt->obj, CL_DESTROY_ASYNC, - __endpt_destroying, __endpt_cleanup, __endpt_free ); - - IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT, - ("Created endpoint: [ %p ] DLID: %#x QPN: %#x \n", - p_endpt, cl_ntoh16(dlid), cl_ntoh32(qpn) ) ); - - p_endpt->dgid = *p_dgid; - p_endpt->dlid = dlid; - p_endpt->qpn = qpn; - - IPOIB_EXIT( IPOIB_DBG_ENDPT ); - return p_endpt; -} - - -static ib_api_status_t -__create_mcast_av( - IN ib_pd_handle_t h_pd, - IN uint8_t port_num, - IN ib_member_rec_t* const p_member_rec, - OUT ib_av_handle_t* const ph_av ) -{ - ib_av_attr_t av_attr; - uint32_t flow_lbl; - uint8_t hop_lmt; - ib_api_status_t status; - ipoib_endpt_t *p_endpt; - - IPOIB_ENTER( IPOIB_DBG_MCAST ); - - p_endpt = PARENT_STRUCT(ph_av, ipoib_endpt_t, h_av ); - - cl_memclr( &av_attr, sizeof(ib_av_attr_t) ); - av_attr.port_num = port_num; - ib_member_get_sl_flow_hop( p_member_rec->sl_flow_hop, - &av_attr.sl, &flow_lbl, &hop_lmt ); - av_attr.dlid = p_member_rec->mlid; - av_attr.grh_valid = TRUE; - av_attr.grh.hop_limit = hop_lmt; - av_attr.grh.dest_gid = p_member_rec->mgid; - av_attr.grh.src_gid = p_member_rec->port_gid; - av_attr.grh.ver_class_flow = - ib_grh_set_ver_class_flow( 6, p_member_rec->tclass, flow_lbl ); - av_attr.static_rate = p_member_rec->rate & IB_PATH_REC_BASE_MASK; - av_attr.path_bits = 0; - /* port is not attached to endpoint at this point, so use endpt ifc reference */ - status = p_endpt->p_ifc->create_av( h_pd, &av_attr, ph_av ); - - if( status != IB_SUCCESS ) - { - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ib_create_av returned %s\n", - p_endpt->p_ifc->get_err_str( status )) ); - } - - IPOIB_EXIT( IPOIB_DBG_MCAST ); - return status; -} - - -ib_api_status_t -ipoib_endpt_set_mcast( - IN ipoib_endpt_t* const p_endpt, - IN ib_pd_handle_t h_pd, - IN uint8_t port_num, - IN ib_mcast_rec_t* const p_mcast_rec ) -{ - ib_api_status_t status; - - IPOIB_ENTER( IPOIB_DBG_ENDPT ); - - IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT, - ("Create av for MAC: %02X-%02X-%02X-%02X-%02X-%02X\n", - p_endpt->mac.addr[0], p_endpt->mac.addr[1], - p_endpt->mac.addr[2], p_endpt->mac.addr[3], - p_endpt->mac.addr[4], p_endpt->mac.addr[5]) ); - - status = __create_mcast_av( h_pd, port_num, p_mcast_rec->p_member_rec, - &p_endpt->h_av ); - if( status != IB_SUCCESS ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("__create_mcast_av returned %s\n", - p_endpt->p_ifc->get_err_str( status )) ); - return status; - } - p_endpt->h_mcast = p_mcast_rec->h_mcast; - CL_ASSERT(p_endpt->dlid == 0); - - IPOIB_EXIT( IPOIB_DBG_ENDPT ); - return IB_SUCCESS; -} - - -static void -__endpt_destroying( - IN cl_obj_t* p_obj ) -{ - ipoib_endpt_t *p_endpt; - ipoib_port_t *p_port; - - IPOIB_ENTER( IPOIB_DBG_ENDPT ); - - p_endpt = PARENT_STRUCT( p_obj, ipoib_endpt_t, obj ); - p_port = __endpt_parent( p_endpt ); - - cl_obj_lock( p_obj ); - if( p_endpt->h_query ) - { - p_port->p_adapter->p_ifc->cancel_query( - p_port->p_adapter->h_al, p_endpt->h_query ); - p_endpt->h_query = NULL; - } - - /* Leave the multicast group if it exists. */ - if( p_endpt->h_mcast ) - { - IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT, - ("Leaving MCast group\n") ); - ipoib_port_ref(p_port, ref_leave_mcast); - p_port->p_adapter->p_ifc->leave_mcast( p_endpt->h_mcast, ipoib_leave_mcast_cb ); - } -#if 0 - else if( p_port->p_adapter->params.cm_enabled ) - { - p_endpt->cm_flag = 0; - CL_ASSERT( endpt_cm_get_state( p_endpt ) == IPOIB_CM_DISCONNECTED ); - } -#endif - - cl_obj_unlock( p_obj ); - - IPOIB_EXIT( IPOIB_DBG_ENDPT ); -} - - -static void -__endpt_cleanup( - IN cl_obj_t* p_obj ) -{ - ipoib_endpt_t *p_endpt; - ipoib_port_t *p_port; - - IPOIB_ENTER( IPOIB_DBG_ENDPT ); - - p_endpt = PARENT_STRUCT( p_obj, ipoib_endpt_t, obj ); - p_port = __endpt_parent( p_endpt ); - - /* Destroy the AV if it exists. */ - if( p_endpt->h_av ) - p_port->p_adapter->p_ifc->destroy_av( p_endpt->h_av ); - - IPOIB_EXIT( IPOIB_DBG_ENDPT ); -} - - -static void -__endpt_free( - IN cl_obj_t* p_obj ) -{ - ipoib_endpt_t *p_endpt; - - IPOIB_ENTER( IPOIB_DBG_ENDPT ); - - p_endpt = PARENT_STRUCT( p_obj, ipoib_endpt_t, obj ); - - cl_obj_deinit( p_obj ); - cl_free( p_endpt ); - - IPOIB_EXIT( IPOIB_DBG_ENDPT ); -} - - -static inline ipoib_port_t* -__endpt_parent( - IN ipoib_endpt_t* const p_endpt ) -{ - return PARENT_STRUCT( p_endpt->rel.p_parent_obj, ipoib_port_t, obj ); -} - -ipoib_port_t* -ipoib_endpt_parent( - IN ipoib_endpt_t* const p_endpt ) -{ - return __endpt_parent( p_endpt ); -} - -/* - * This function is called with the port object's send lock held and - * a reference held on the endpoint. If we fail, we release the reference. - */ -NDIS_STATUS -ipoib_endpt_queue( - IN ipoib_endpt_t* const p_endpt ) -{ - ib_api_status_t status; - ipoib_port_t *p_port; - ib_av_attr_t av_attr; - net32_t flow_lbl; - - IPOIB_ENTER( IPOIB_DBG_ENDPT ); - - if( p_endpt->h_av ) - { - IPOIB_EXIT( IPOIB_DBG_ENDPT ); - return NDIS_STATUS_SUCCESS; - } - - if( p_endpt->qpn == CL_HTON32(0x00FFFFFF) ) - { - /* - * Handle a race between the mcast callback and a receive/send. The QP - * is joined to the MC group before the MC callback is received, so it - * can receive packets, and NDIS can try to respond. We need to delay - * a response until the MC callback runs and sets the AV. - */ - ipoib_endpt_deref( p_endpt ); - IPOIB_EXIT( IPOIB_DBG_ENDPT ); - return NDIS_STATUS_PENDING; - } - - /* This is the first packet for this endpoint. Create the AV. */ - p_port = __endpt_parent( p_endpt ); - - cl_memclr( &av_attr, sizeof(ib_av_attr_t) ); - - av_attr.port_num = p_port->port_num; - - ib_member_get_sl_flow_hop( - p_port->ib_mgr.bcast_rec.sl_flow_hop, - &av_attr.sl, - &flow_lbl, - &av_attr.grh.hop_limit - ); - - av_attr.dlid = p_endpt->dlid; - - /* - * We always send the GRH so that we preferably lookup endpoints - * by GID rather than by LID. This allows certain WHQL tests - * such as the 2c_MediaCheck test to succeed since they don't use - * IP. This allows endpoints to be created on the fly for requests - * for which there is no match, something that doesn't work when - * using LIDs only. - */ - av_attr.grh_valid = TRUE; - av_attr.grh.ver_class_flow = ib_grh_set_ver_class_flow( - 6, p_port->ib_mgr.bcast_rec.tclass, flow_lbl ); - av_attr.grh.resv1 = 0; - av_attr.grh.resv2 = 0; - ib_gid_set_default( &av_attr.grh.src_gid, p_port->p_adapter->guids.port_guid.guid ); - av_attr.grh.dest_gid = p_endpt->dgid; - - av_attr.static_rate = p_port->ib_mgr.bcast_rec.rate; - av_attr.path_bits = 0; - - /* Create the AV. */ - status = p_port->p_adapter->p_ifc->create_av( - p_port->ib_mgr.h_pd, &av_attr, &p_endpt->h_av ); - if( status != IB_SUCCESS ) - { - p_port->p_adapter->hung = TRUE; - ipoib_endpt_deref( p_endpt ); - cl_obj_unlock( &p_endpt->obj ); - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ib_create_av failed with %s\n", - p_port->p_adapter->p_ifc->get_err_str( status )) ); - return NDIS_STATUS_FAILURE; - } - - IPOIB_EXIT( IPOIB_DBG_ENDPT ); - return NDIS_STATUS_SUCCESS; -} - -#if 0 - -static void -__endpt_cm_buf_mgr_construct( - IN endpt_buf_mgr_t * const p_buf_mgr ) -{ - IPOIB_ENTER( IPOIB_DBG_INIT ); - - cl_qpool_construct( &p_buf_mgr->recv_pool ); - - p_buf_mgr->h_packet_pool = NULL; - p_buf_mgr->h_buffer_pool = NULL; - - IPOIB_EXIT( IPOIB_DBG_INIT ); -} - -ib_api_status_t -endpt_cm_buf_mgr_init( - IN ipoib_port_t* const p_port ) -{ - cl_status_t cl_status; - NDIS_STATUS ndis_status; - ib_api_status_t ib_status = IB_SUCCESS; - - IPOIB_ENTER( IPOIB_DBG_INIT ); - - if( p_port->cm_buf_mgr.pool_init ) - return ib_status; - - cl_qlist_init( &p_port->cm_buf_mgr.posted_list ); - - __endpt_cm_buf_mgr_construct( &p_port->cm_buf_mgr ); - p_port->cm_recv_mgr.rq_depth = - min( (uint32_t)p_port->p_adapter->params.rq_depth * 8, - p_port->p_ca_attrs->max_srq_wrs/2 ); - p_port->cm_recv_mgr.depth = 0; - /* Allocate the receive descriptors pool */ - cl_status = cl_qpool_init( &p_port->cm_buf_mgr.recv_pool, - p_port->cm_recv_mgr.rq_depth , - 0, - 0, - sizeof( ipoib_cm_desc_t ), - __cm_recv_desc_ctor, - __cm_recv_desc_dtor, - p_port ); - - if( cl_status != CL_SUCCESS ) - { - NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, - EVENT_IPOIB_RECV_POOL, 1, cl_status ); - - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("cl_qpool_init for cm recvs returned %#x\n", cl_status) ); - - return IB_INSUFFICIENT_MEMORY; - } - - /* Allocate the NDIS buffer and packet pools for receive indication. */ - NdisAllocatePacketPool( &ndis_status, - &p_port->cm_buf_mgr.h_packet_pool, - p_port->cm_recv_mgr.rq_depth, - PROTOCOL_RESERVED_SIZE_IN_PACKET ); - if( ndis_status != NDIS_STATUS_SUCCESS ) - { - NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, - EVENT_IPOIB_RECV_PKT_POOL, 1, ndis_status ); - - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("NdisAllocatePacketPool returned %08X\n", ndis_status) ); - - ib_status = IB_INSUFFICIENT_RESOURCES; - goto pkt_pool_failed; - } - - NdisAllocateBufferPool( &ndis_status, - &p_port->cm_buf_mgr.h_buffer_pool, - p_port->cm_recv_mgr.rq_depth ); - if( ndis_status != NDIS_STATUS_SUCCESS ) - { - NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, - EVENT_IPOIB_RECV_BUF_POOL, 1, ndis_status ); - - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("NdisAllocateBufferPool returned %08X\n", ndis_status) ); - - ib_status = IB_INSUFFICIENT_RESOURCES; - goto buf_pool_failed; - } - //NDIS60 - //p_port->cm_recv_mgr.recv_pkt_array = - //cl_zalloc( sizeof(NDIS_PACKET*) * p_port->cm_recv_mgr.rq_depth ); - p_port->cm_recv_mgr.recv_lst_array = - cl_zalloc( sizeof(NET_BUFFER_LIST*) * p_port->cm_recv_mgr.rq_depth ); - - - - if( !p_port->cm_recv_mgr.recv_pkt_array ) - { - //NDIS60 - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("cl_zalloc for NET_BUFFER_LIST array failed.\n") ); - - ib_status = IB_INSUFFICIENT_MEMORY; - goto pkt_array_failed; - } - - p_port->cm_buf_mgr.pool_init = TRUE; - return IB_SUCCESS; - -pkt_array_failed: - if( p_port->cm_buf_mgr.h_buffer_pool ) - NdisFreeBufferPool( p_port->cm_buf_mgr.h_buffer_pool ); -buf_pool_failed: - if( p_port->cm_buf_mgr.h_packet_pool ) - NdisFreePacketPool( p_port->cm_buf_mgr.h_packet_pool ); -pkt_pool_failed: - cl_qpool_destroy( &p_port->cm_buf_mgr.recv_pool ); - - IPOIB_EXIT( IPOIB_DBG_INIT ); - return ib_status; -} - -void -endpt_cm_buf_mgr_reset( - IN ipoib_port_t* const p_port ) -{ - cl_list_item_t *p_item; - - if( !p_port->cm_buf_mgr.pool_init ) - return; - - if( cl_qlist_count( &p_port->cm_buf_mgr.posted_list ) ) - { - for( p_item = cl_qlist_remove_head( &p_port->cm_buf_mgr.posted_list ); - p_item != cl_qlist_end( &p_port->cm_buf_mgr.posted_list ); - p_item = cl_qlist_remove_head( &p_port->cm_buf_mgr.posted_list ) ) - { - cl_qpool_put( &p_port->cm_buf_mgr.recv_pool, - &( PARENT_STRUCT( p_item, ipoib_cm_desc_t, list_item ))->item ); - } - } -} - -void -endpt_cm_buf_mgr_destroy( - IN ipoib_port_t* const p_port ) -{ - - IPOIB_ENTER(IPOIB_DBG_INIT ); - - CL_ASSERT( p_port ); - - /* Free the receive descriptors. */ - if( !p_port->cm_buf_mgr.pool_init ) - return; - - endpt_cm_buf_mgr_reset( p_port ); - - p_port->cm_buf_mgr.pool_init = FALSE; - - if( p_port->cm_recv_mgr.recv_pkt_array ) - { - cl_free( p_port->cm_recv_mgr.recv_pkt_array ); - } - - /* Destroy the receive packet and buffer pools. */ - if( p_port->cm_buf_mgr.h_buffer_pool ) - NdisFreeBufferPool( p_port->cm_buf_mgr.h_buffer_pool ); - if( p_port->cm_buf_mgr.h_packet_pool ) - NdisFreePacketPool( p_port->cm_buf_mgr.h_packet_pool ); - - cl_qpool_destroy( &p_port->cm_buf_mgr.recv_pool ); - - IPOIB_EXIT( IPOIB_DBG_INIT ); -} - -static cl_status_t -__cm_recv_desc_ctor( - IN void* const p_object, - IN void* context, - OUT cl_pool_item_t** const pp_pool_item ) -{ - ipoib_cm_desc_t* p_desc; - ipoib_port_t* p_port; - ib_mr_create_t create_mr; - net32_t rkey; - - CL_ASSERT( p_object ); - CL_ASSERT( context ); - - p_desc = (ipoib_cm_desc_t*)p_object; - p_port = (ipoib_port_t*)context; - -#define BUF_ALIGN (16) - - p_desc->alloc_buf_size = - ROUNDUP( p_port->p_adapter->params.cm_xfer_block_size, BUF_ALIGN ); - - p_desc->p_alloc_buf = (uint8_t *)ExAllocatePoolWithTag( - NonPagedPool, p_desc->alloc_buf_size, 'DOMC' ); - - if( p_desc->p_alloc_buf == NULL ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed to allocate receive buffer size %d bytes.\n", p_desc->alloc_buf_size ) ); - return CL_INSUFFICIENT_MEMORY; - } - - create_mr.vaddr = p_desc->p_alloc_buf; - create_mr.length = p_desc->alloc_buf_size; - create_mr.access_ctrl = IB_AC_LOCAL_WRITE; - - - if( p_port->p_adapter->p_ifc->reg_mem( - p_port->ib_mgr.h_pd, - &create_mr, - &p_desc->lkey, - &rkey, - &p_desc->h_mr ) != IB_SUCCESS ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed to create Memory Region size %d bytes.\n", p_desc->alloc_buf_size ) ); - goto ctor_failed; - } - p_desc->p_buf = p_desc->p_alloc_buf + (BUF_ALIGN - sizeof( ipoib_hdr_t)); - p_desc->buf_size = p_desc->alloc_buf_size - (BUF_ALIGN - sizeof( ipoib_hdr_t)); - - /* Setup the local data segment. */ - p_desc->local_ds[0].vaddr = (uint64_t)(uintn_t)p_desc->p_buf; - p_desc->local_ds[0].length = p_desc->buf_size; - p_desc->local_ds[0].lkey = p_desc->lkey; - - /* Setup the work request. */ - p_desc->wr.wr_id = (uintn_t)p_desc; - p_desc->wr.ds_array = p_desc->local_ds; - p_desc->wr.num_ds = 1; - p_desc->type = PKT_TYPE_CM_UCAST; - - *pp_pool_item = &p_desc->item; - return CL_SUCCESS; - -ctor_failed: - ExFreePoolWithTag( p_desc->p_alloc_buf, 'DOMC' ); - return CL_INSUFFICIENT_MEMORY; -} - -static void -__cm_recv_desc_dtor( - IN const cl_pool_item_t* const p_pool_item, - IN void *context ) -{ - ipoib_cm_desc_t *p_desc; - ipoib_port_t* p_port; - - if( p_pool_item == NULL || context == NULL ) - return; - - p_port = (ipoib_port_t*)context; - p_desc = PARENT_STRUCT( p_pool_item, ipoib_cm_desc_t, item ); - - if( p_desc->h_mr ) - p_port->p_adapter->p_ifc->dereg_mr( p_desc->h_mr ); - - if( p_desc->p_alloc_buf ) - ExFreePoolWithTag( p_desc->p_alloc_buf, 'DOMC' ); -} - - -static NDIS_PACKET* -__endpt_cm_get_ndis_pkt( - IN ipoib_port_t* const p_port, - IN ipoib_cm_desc_t* const p_desc ) -{ - NDIS_STATUS status; - NDIS_PACKET *p_packet; - NDIS_BUFFER *p_buffer; - - IPOIB_ENTER( IPOIB_DBG_RECV ); - - NdisDprAllocatePacketNonInterlocked( &status, &p_packet, - p_port->cm_buf_mgr.h_packet_pool ); - if( status != NDIS_STATUS_SUCCESS ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed to allocate NDIS_PACKET: %08x\n", status) ); - return NULL; - } - - IPOIB_PORT_FROM_PACKET( p_packet ) = p_port; - IPOIB_RECV_FROM_PACKET( p_packet ) = p_desc; - - NdisAllocateBuffer( - &status, - &p_buffer, - p_port->cm_buf_mgr.h_buffer_pool, - (void *)(p_desc->p_buf - DATA_OFFSET), - p_desc->len + DATA_OFFSET ); - - if( status != NDIS_STATUS_SUCCESS ) - { - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed to allocate NDIS_BUFFER: %08x\n", status) ); - NdisDprFreePacketNonInterlocked( p_packet ); - return NULL; - } - - NdisChainBufferAtFront( p_packet, p_buffer ); - NDIS_SET_PACKET_HEADER_SIZE( p_packet, sizeof(eth_hdr_t) ); - - IPOIB_EXIT( IPOIB_DBG_RECV ); - return p_packet; -} - -static inline ipoib_cm_desc_t* -__endpt_cm_buf_mgr_get_recv( - IN endpt_buf_mgr_t * const p_buf_mgr ) -{ - ipoib_cm_desc_t *p_desc; - - p_desc = (ipoib_cm_desc_t*)cl_qpool_get( &p_buf_mgr->recv_pool ); - if( p_desc ) - cl_qlist_insert_tail( &p_buf_mgr->posted_list, &p_desc->list_item ); - - return p_desc; -} - -void -endpt_cm_buf_mgr_put_recv( - IN endpt_buf_mgr_t * const p_buf_mgr, - IN ipoib_cm_desc_t* const p_desc ) -{ - - IPOIB_ENTER(IPOIB_DBG_RECV ); - - /* Return the descriptor to it's pool. */ - cl_qlist_remove_item( &p_buf_mgr->posted_list, &p_desc->list_item ); - cl_qpool_put( &p_buf_mgr->recv_pool, &p_desc->item ); - - IPOIB_EXIT( IPOIB_DBG_RECV ); -} - -void -endpt_cm_buf_mgr_put_recv_list( - IN endpt_buf_mgr_t * const p_buf_mgr, - IN cl_qlist_t* const p_list ) -{ - cl_qpool_put_list( &p_buf_mgr->recv_pool, p_list ); -} - -uint32_t -endpt_cm_recv_mgr_build_pkt_array( - IN ipoib_port_t* const p_port, - IN ipoib_endpt_t* const p_endpt, - IN cl_qlist_t* const p_done_list, - IN OUT uint32_t* p_bytes_recv ) -{ - cl_list_item_t *p_item; - ipoib_cm_desc_t *p_desc; - uint32_t i = 0; - NDIS_PACKET *p_packet; - NDIS_TCP_IP_CHECKSUM_PACKET_INFO chksum; - - IPOIB_ENTER( IPOIB_DBG_RECV ); - UNUSED_PARAM( p_endpt ); - - p_item = cl_qlist_remove_head( p_done_list ); - - *p_bytes_recv = 0; - - for( p_item; p_item != cl_qlist_end( p_done_list ); - p_item = cl_qlist_remove_head( p_done_list ) ) - { - p_desc = (ipoib_cm_desc_t*)p_item; - - p_packet = __endpt_cm_get_ndis_pkt( p_port, p_desc ); - if( !p_packet ) - { - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed to get Packet from descriptor\n" ) ); - endpt_cm_buf_mgr_put_recv( &p_port->cm_buf_mgr, p_desc ); - p_port->cm_recv_mgr.depth--; - continue; - } - chksum.Value = 0; - switch( p_port->p_adapter->params.recv_chksum_offload ) - { - default: - CL_ASSERT( FALSE ); - case CSUM_DISABLED: - case CSUM_ENABLED: - NDIS_PER_PACKET_INFO_FROM_PACKET( p_packet, TcpIpChecksumPacketInfo ) = - (void*)(uintn_t)chksum.Value; - break; - case CSUM_BYPASS: - /* Flag the checksums as having been calculated. */ - chksum.Receive.NdisPacketTcpChecksumSucceeded = TRUE; - chksum.Receive.NdisPacketUdpChecksumSucceeded = TRUE; - chksum.Receive.NdisPacketIpChecksumSucceeded = TRUE; - NDIS_PER_PACKET_INFO_FROM_PACKET( p_packet, TcpIpChecksumPacketInfo ) = - (void*)(uintn_t)chksum.Value; - break; - } - - NDIS_SET_PACKET_STATUS( p_packet, NDIS_STATUS_SUCCESS ); - p_port->cm_recv_mgr.recv_pkt_array[i] = p_packet; - i++; - *p_bytes_recv += p_desc->len; - } - - IPOIB_EXIT( IPOIB_DBG_RECV ); - return i; -} -void -endpt_cm_flush_recv( - IN ipoib_port_t* const p_port, - IN ipoib_endpt_t* const p_endpt ) -{ - ib_api_status_t ib_status = IB_SUCCESS; - ib_qp_mod_t mod_attr; - ib_wc_t wc[MAX_RECV_WC]; - ib_wc_t *p_free_wc; - ib_wc_t *p_done_wc; - ib_wc_t *p_wc; - ipoib_cm_desc_t *p_desc; - size_t i; - - IPOIB_ENTER( IPOIB_DBG_RECV ); - - CL_ASSERT( p_endpt ); - - if( p_endpt->conn.h_recv_qp ) - { - cl_memclr( &mod_attr, sizeof( mod_attr ) ); - mod_attr.req_state = IB_QPS_ERROR; - p_port->p_adapter->p_ifc->modify_qp( p_endpt->conn.h_send_qp, &mod_attr ); - p_port->p_adapter->p_ifc->modify_qp( p_endpt->conn.h_recv_qp, &mod_attr ); - - for( i = 0; i < MAX_RECV_WC; i++ ) - wc[i].p_next = &wc[i + 1]; - wc[MAX_RECV_WC - 1].p_next = NULL; - - do - { - p_free_wc = wc; - ib_status = - p_port->p_adapter->p_ifc->poll_cq( p_endpt->conn.h_recv_cq, - &p_free_wc, &p_done_wc ); - if( ib_status != IB_SUCCESS && - ib_status != IB_NOT_FOUND ) - { - /* connection CQ failed */ - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Poll Recv CQ failed status %#x\n", ib_status ) ); - break; - } - cl_spinlock_acquire( &p_port->recv_lock ); - for( p_wc = p_done_wc; p_wc; p_wc = p_wc->p_next ) - { - p_desc = (ipoib_cm_desc_t *)(uintn_t)p_wc->wr_id; - endpt_cm_buf_mgr_put_recv( &p_port->cm_buf_mgr, p_desc ); - p_port->cm_recv_mgr.depth--; - } - cl_spinlock_release( &p_port->recv_lock ); - } while( !p_free_wc ); - - ib_status = p_port->p_adapter->p_ifc->destroy_qp( p_endpt->conn.h_recv_qp, NULL ); - if( ib_status != IB_SUCCESS ) - { - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Destroy Recv QP failed status %#x\n", ib_status ) ); - } - p_endpt->conn.h_recv_qp = NULL; - } - - if( p_endpt->conn.h_send_qp ) - { - ib_status = p_port->p_adapter->p_ifc->destroy_qp( p_endpt->conn.h_send_qp, NULL ); - if( ib_status != IB_SUCCESS ) - { - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Destroy Send QP failed status %#x\n", ib_status ) ); - } - p_endpt->conn.h_send_qp = NULL; - } - - IPOIB_EXIT( IPOIB_DBG_RECV ); -} - -int32_t -endpt_cm_recv_mgr_filter( - IN ipoib_endpt_t* const p_endpt, - IN ib_wc_t* const p_done_wc_list, - OUT cl_qlist_t* const p_done_list, - OUT cl_qlist_t* const p_bad_list ) -{ - ib_api_status_t ib_status; - ipoib_cm_desc_t *p_desc; - ib_wc_t *p_wc; - ipoib_pkt_t *p_ipoib; - eth_pkt_t *p_eth; - ipoib_port_t* p_port; - int32_t recv_cnt; - - IPOIB_ENTER( IPOIB_DBG_RECV ); - - p_port = ipoib_endpt_parent( p_endpt ); - - for( p_wc = p_done_wc_list, recv_cnt = 0; p_wc; p_wc = p_wc->p_next ) - { - p_desc = (ipoib_cm_desc_t *)(uintn_t)p_wc->wr_id; - recv_cnt++; - if( p_wc->status != IB_WCS_SUCCESS ) - { - if( p_wc->status != IB_WCS_WR_FLUSHED_ERR ) - { - - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed completion %s (vendor specific %#x)\n", - p_port->p_adapter->p_ifc->get_wc_status_str( p_wc->status ), - (int)p_wc->vendor_specific) ); - } - else - { - IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_RECV, - ("Flushed completion %s\n", - p_port->p_adapter->p_ifc->get_wc_status_str( p_wc->status )) ); - } - - ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_ERROR, 0, 0 ); - - cl_qlist_remove_item( &p_port->cm_buf_mgr.posted_list,&p_desc->list_item ); - cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item ); - continue; - } - - /* Successful completion - Setup the ethernet/ip/arp header and queue descriptor for report. */ - ib_status = IB_SUCCESS; - p_ipoib = (ipoib_pkt_t *)((uint8_t*)p_desc->p_buf ); - p_eth = (eth_pkt_t *)((uint8_t*)p_desc->p_buf - DATA_OFFSET ); - - switch( p_ipoib->hdr.type ) - { - case ETH_PROT_TYPE_ARP: - if( p_wc->length < (sizeof(ipoib_hdr_t) + sizeof(ipoib_arp_pkt_t)) ) - { - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Received ARP packet too short\n") ); - ib_status = IB_ERROR; - break; - } - ib_status = - __endpt_cm_recv_arp( p_port, p_ipoib, p_eth, p_endpt ); - break; - case ETH_PROT_TYPE_IP: - if( p_wc->length < (sizeof(ipoib_hdr_t) + sizeof(ip_hdr_t)) ) - { - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Received IP packet too short\n") ); - ib_status = IB_ERROR; - break; - } - if( p_ipoib->type.ip.hdr.prot == IP_PROT_UDP ) - { - ib_status = - __endpt_cm_recv_udp( p_port, p_wc, p_ipoib, p_eth, p_endpt ); - } - - break; - } - - if( ib_status != IB_SUCCESS ) - { - ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_ERROR, 0, 0 ); - cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item ); - continue; - } - - p_eth->hdr.type = p_ipoib->hdr.type; - p_eth->hdr.src = p_endpt->mac; - p_eth->hdr.dst = p_port->p_adapter->mac; - - /* save payload length */ - p_desc->len = p_wc->length; - - cl_qlist_insert_tail( p_done_list, &p_desc->item.list_item ); - } - - IPOIB_EXIT( IPOIB_DBG_RECV ); - return recv_cnt; -} - -ib_api_status_t -endpt_cm_post_recv( - IN ipoib_port_t* const p_port ) -{ - ib_api_status_t ib_status = IB_SUCCESS; - ipoib_cm_desc_t *p_head_desc = NULL; - ipoib_cm_desc_t *p_tail_desc = NULL; - ipoib_cm_desc_t *p_next_desc; - ib_recv_wr_t *p_failed_wc = NULL; - - IPOIB_ENTER( IPOIB_DBG_RECV ); - - while( cl_qpool_count( &p_port->cm_buf_mgr.recv_pool ) > 1 ) - { - /* Pull receives out of the pool and chain them up. */ - p_next_desc = __endpt_cm_buf_mgr_get_recv( - &p_port->cm_buf_mgr ); - if( !p_next_desc ) - { - IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_RECV, - ("Out of receive descriptors! Endpt recv queue depth 0x%x\n", - p_port->cm_recv_mgr.depth ) ); - break; - } - - if( !p_tail_desc ) - { - p_tail_desc = p_next_desc; - p_next_desc->wr.p_next = NULL; - } - else - { - p_next_desc->wr.p_next = &p_head_desc->wr; - } - - p_head_desc = p_next_desc; - - p_port->cm_recv_mgr.depth++; - } - - if( p_head_desc ) - { - ib_status = p_port->p_adapter->p_ifc->post_srq_recv( - p_port->ib_mgr.h_srq, &p_head_desc->wr, &p_failed_wc ); - - if( ib_status != IB_SUCCESS ) - { - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ip_post_recv returned %s\n", - p_port->p_adapter->p_ifc->get_err_str( ib_status )) ); - - /* put descriptors back to the pool */ - while( p_failed_wc ) - { - p_head_desc = PARENT_STRUCT( p_failed_wc, ipoib_cm_desc_t, wr ); - p_failed_wc = p_failed_wc->p_next; - endpt_cm_buf_mgr_put_recv( &p_port->cm_buf_mgr, p_head_desc ); - p_port->cm_recv_mgr.depth--; - } - } - } - - - IPOIB_EXIT( IPOIB_DBG_RECV ); - return( ib_status ); -} - -static ib_api_status_t -__endpt_cm_recv_arp( - IN ipoib_port_t* const p_port, - IN const ipoib_pkt_t* const p_ipoib, - OUT eth_pkt_t* const p_eth, - IN ipoib_endpt_t* const p_src_endpt ) -{ - const ipoib_arp_pkt_t *p_ib_arp; - arp_pkt_t *p_arp; - - p_ib_arp = &p_ipoib->type.arp; - p_arp = &p_eth->type.arp; - - if( p_ib_arp->hw_type != ARP_HW_TYPE_IB || - p_ib_arp->hw_size != sizeof(ipoib_hw_addr_t) || - p_ib_arp->prot_type != ETH_PROT_TYPE_IP ) - { - return IB_ERROR; - } - - p_arp->hw_type = ARP_HW_TYPE_ETH; - p_arp->hw_size = sizeof(mac_addr_t); - p_arp->src_hw = p_src_endpt->mac; - p_arp->src_ip = p_ib_arp->src_ip; - p_arp->dst_hw = p_port->p_local_endpt->mac; - p_arp->dst_ip = p_ib_arp->dst_ip; - - return IB_SUCCESS; -} - -static ib_api_status_t -__endpt_cm_recv_udp( - IN ipoib_port_t* const p_port, - IN ib_wc_t* const p_wc, - IN const ipoib_pkt_t* const p_ipoib, - OUT eth_pkt_t* const p_eth, - IN ipoib_endpt_t* const p_src_endpt ) -{ - ib_api_status_t ib_status = IB_SUCCESS; - - if( p_wc->length < - (sizeof(ipoib_hdr_t) + sizeof(ip_hdr_t) + sizeof(udp_hdr_t)) ) - { - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Received UDP packet too short\n") ); - return IB_ERROR; - } - if( __cm_recv_is_dhcp( p_ipoib ) ) - { - ib_status = ipoib_recv_dhcp( - p_port, p_ipoib, p_eth, p_src_endpt, p_port->p_local_endpt ); - } - - return ib_status; -} - -static boolean_t -__cm_recv_is_dhcp( - IN const ipoib_pkt_t* const p_ipoib ) -{ - return( (p_ipoib->type.ip.prot.udp.hdr.dst_port == DHCP_PORT_SERVER && - p_ipoib->type.ip.prot.udp.hdr.src_port == DHCP_PORT_CLIENT) || - (p_ipoib->type.ip.prot.udp.hdr.dst_port == DHCP_PORT_CLIENT && - p_ipoib->type.ip.prot.udp.hdr.src_port == DHCP_PORT_SERVER) ); -} -#endif diff --git a/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_endpoint.cpp b/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_endpoint.cpp new file mode 100644 index 00000000..58a2b5c2 --- /dev/null +++ b/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_endpoint.cpp @@ -0,0 +1,1170 @@ +/* + * Copyright (c) 2005 SilverStorm Technologies. All rights reserved. + * Copyright (c) 2006 Mellanox Technologies. All rights reserved. + * Portions Copyright (c) 2008 Microsoft 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: ipoib_endpoint.c 4226 2009-04-06 06:01:03Z xalex $ + */ + + + +#include "ipoib_endpoint.h" +#include "ipoib_port.h" +#include "ipoib_debug.h" +#if defined(EVENT_TRACING) +#ifdef offsetof +#undef offsetof +#endif +#include "ipoib_endpoint.tmh" +#endif +#include +#include + + +static void +__endpt_destroying( + IN cl_obj_t* p_obj ); + +static void +__endpt_cleanup( + IN cl_obj_t* p_obj ); + +static void +__endpt_free( + IN cl_obj_t* p_obj ); + +static ib_api_status_t +__create_mcast_av( + IN ib_pd_handle_t h_pd, + IN uint8_t port_num, + IN ib_member_rec_t* const p_member_rec, + OUT ib_av_handle_t* const ph_av ); + +static inline ipoib_port_t* +__endpt_parent( + IN ipoib_endpt_t* const p_endpt ); + +static void +__path_query_cb( + IN ib_query_rec_t *p_query_rec ); + +static void +__endpt_resolve( + IN ipoib_endpt_t* const p_endpt ); + +static void +__endpt_cm_send_cb( + IN const ib_cq_handle_t h_cq, + IN void *cq_context ); +static void +__endpt_cm_recv_cb( + IN const ib_cq_handle_t h_cq, + IN void *cq_context ); + +static void +__endpt_cm_buf_mgr_construct( + IN endpt_buf_mgr_t * const p_buf_mgr ); +static void +__conn_reply_cb( + IN ib_cm_rep_rec_t *p_cm_rep ); + +static void +__conn_mra_cb( + IN ib_cm_mra_rec_t *p_mra_rec ); + +static void +__conn_rej_cb( + IN ib_cm_rej_rec_t *p_rej_rec ); + +static void +__conn_dreq_cb( + IN ib_cm_dreq_rec_t *p_dreq_rec ); + +#if 0 //CM +static cl_status_t +__cm_recv_desc_ctor( + IN void* const p_object, + IN void* context, + OUT cl_pool_item_t** const pp_pool_item ); + +static void +__cm_recv_desc_dtor( + IN const cl_pool_item_t* const p_pool_item, + IN void *context ); + +static NDIS_PACKET* +__endpt_cm_get_ndis_pkt( + IN ipoib_port_t* const p_port, + IN ipoib_cm_desc_t* const p_desc ); + +static inline ipoib_cm_desc_t* +__endpt_cm_buf_mgr_get_recv( + IN endpt_buf_mgr_t * const p_buf_mgr ); + +static boolean_t +__cm_recv_is_dhcp( + IN const ipoib_pkt_t* const p_ipoib ); + +static ib_api_status_t +__endpt_cm_recv_arp( + IN ipoib_port_t* const p_port, + IN const ipoib_pkt_t* const p_ipoib, + OUT eth_pkt_t* const p_eth, + IN ipoib_endpt_t* const p_src_endpt ); + +static ib_api_status_t +__endpt_cm_recv_udp( + IN ipoib_port_t* const p_port, + IN ib_wc_t* const p_wc, + IN const ipoib_pkt_t* const p_ipoib, + OUT eth_pkt_t* const p_eth, + IN ipoib_endpt_t* const p_src_endpt ); +#endif + +ipoib_endpt_t* +ipoib_endpt_create( + IN const ib_gid_t* const p_dgid, + IN const net16_t dlid, + IN const net32_t qpn ) +{ + ipoib_endpt_t *p_endpt; + cl_status_t status; + + IPOIB_ENTER( IPOIB_DBG_ENDPT ); + + p_endpt = (ipoib_endpt_t *) cl_zalloc( sizeof(ipoib_endpt_t) ); + if( !p_endpt ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed to allocate endpoint (%d bytes)\n", + sizeof(ipoib_endpt_t)) ); + return NULL; + } + + cl_obj_construct( &p_endpt->obj, IPOIB_OBJ_ENDPOINT ); + + status = cl_obj_init( &p_endpt->obj, CL_DESTROY_ASYNC, + __endpt_destroying, __endpt_cleanup, __endpt_free ); + + IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT, + ("Created endpoint: [ %p ] DLID: %#x QPN: %#x \n", + p_endpt, cl_ntoh16(dlid), cl_ntoh32(qpn) ) ); + + p_endpt->dgid = *p_dgid; + p_endpt->dlid = dlid; + p_endpt->qpn = qpn; + + IPOIB_EXIT( IPOIB_DBG_ENDPT ); + return p_endpt; +} + + +static ib_api_status_t +__create_mcast_av( + IN ib_pd_handle_t h_pd, + IN uint8_t port_num, + IN ib_member_rec_t* const p_member_rec, + OUT ib_av_handle_t* const ph_av ) +{ + ib_av_attr_t av_attr; + uint32_t flow_lbl; + uint8_t hop_lmt; + ib_api_status_t status; + ipoib_endpt_t *p_endpt; + + IPOIB_ENTER( IPOIB_DBG_MCAST ); + + p_endpt = PARENT_STRUCT(ph_av, ipoib_endpt_t, h_av ); + + cl_memclr( &av_attr, sizeof(ib_av_attr_t) ); + av_attr.port_num = port_num; + ib_member_get_sl_flow_hop( p_member_rec->sl_flow_hop, + &av_attr.sl, &flow_lbl, &hop_lmt ); + av_attr.dlid = p_member_rec->mlid; + av_attr.grh_valid = TRUE; + av_attr.grh.hop_limit = hop_lmt; + av_attr.grh.dest_gid = p_member_rec->mgid; + av_attr.grh.src_gid = p_member_rec->port_gid; + av_attr.grh.ver_class_flow = + ib_grh_set_ver_class_flow( 6, p_member_rec->tclass, flow_lbl ); + av_attr.static_rate = p_member_rec->rate & IB_PATH_REC_BASE_MASK; + av_attr.path_bits = 0; + /* port is not attached to endpoint at this point, so use endpt ifc reference */ + status = p_endpt->p_ifc->create_av( h_pd, &av_attr, ph_av ); + + if( status != IB_SUCCESS ) + { + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ib_create_av returned %s\n", + p_endpt->p_ifc->get_err_str( status )) ); + } + + IPOIB_EXIT( IPOIB_DBG_MCAST ); + return status; +} + + +ib_api_status_t +ipoib_endpt_set_mcast( + IN ipoib_endpt_t* const p_endpt, + IN ib_pd_handle_t h_pd, + IN uint8_t port_num, + IN ib_mcast_rec_t* const p_mcast_rec ) +{ + ib_api_status_t status; + + IPOIB_ENTER( IPOIB_DBG_ENDPT ); + + IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT, + ("Create av for MAC: %02X-%02X-%02X-%02X-%02X-%02X\n", + p_endpt->mac.addr[0], p_endpt->mac.addr[1], + p_endpt->mac.addr[2], p_endpt->mac.addr[3], + p_endpt->mac.addr[4], p_endpt->mac.addr[5]) ); + + status = __create_mcast_av( h_pd, port_num, p_mcast_rec->p_member_rec, + &p_endpt->h_av ); + if( status != IB_SUCCESS ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("__create_mcast_av returned %s\n", + p_endpt->p_ifc->get_err_str( status )) ); + return status; + } + p_endpt->h_mcast = p_mcast_rec->h_mcast; + CL_ASSERT(p_endpt->dlid == 0); + + IPOIB_EXIT( IPOIB_DBG_ENDPT ); + return IB_SUCCESS; +} + + +static void +__endpt_destroying( + IN cl_obj_t* p_obj ) +{ + ipoib_endpt_t *p_endpt; + ipoib_port_t *p_port; + + IPOIB_ENTER( IPOIB_DBG_ENDPT ); + + p_endpt = PARENT_STRUCT( p_obj, ipoib_endpt_t, obj ); + p_port = __endpt_parent( p_endpt ); + + cl_obj_lock( p_obj ); + if( p_endpt->h_query ) + { + p_port->p_adapter->p_ifc->cancel_query( + p_port->p_adapter->h_al, p_endpt->h_query ); + p_endpt->h_query = NULL; + } + + /* Leave the multicast group if it exists. */ + if( p_endpt->h_mcast ) + { + IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT, + ("Leaving MCast group\n") ); + ipoib_port_ref(p_port, ref_leave_mcast); + p_port->p_adapter->p_ifc->leave_mcast( p_endpt->h_mcast, ipoib_leave_mcast_cb ); + } +#if 0 + else if( p_port->p_adapter->params.cm_enabled ) + { + p_endpt->cm_flag = 0; + CL_ASSERT( endpt_cm_get_state( p_endpt ) == IPOIB_CM_DISCONNECTED ); + } +#endif + + cl_obj_unlock( p_obj ); + + IPOIB_EXIT( IPOIB_DBG_ENDPT ); +} + + +static void +__endpt_cleanup( + IN cl_obj_t* p_obj ) +{ + ipoib_endpt_t *p_endpt; + ipoib_port_t *p_port; + + IPOIB_ENTER( IPOIB_DBG_ENDPT ); + + p_endpt = PARENT_STRUCT( p_obj, ipoib_endpt_t, obj ); + p_port = __endpt_parent( p_endpt ); + + /* Destroy the AV if it exists. */ + if( p_endpt->h_av ) + p_port->p_adapter->p_ifc->destroy_av( p_endpt->h_av ); + + IPOIB_EXIT( IPOIB_DBG_ENDPT ); +} + + +static void +__endpt_free( + IN cl_obj_t* p_obj ) +{ + ipoib_endpt_t *p_endpt; + + IPOIB_ENTER( IPOIB_DBG_ENDPT ); + + p_endpt = PARENT_STRUCT( p_obj, ipoib_endpt_t, obj ); + + cl_obj_deinit( p_obj ); + cl_free( p_endpt ); + + IPOIB_EXIT( IPOIB_DBG_ENDPT ); +} + + +static inline ipoib_port_t* +__endpt_parent( + IN ipoib_endpt_t* const p_endpt ) +{ + return PARENT_STRUCT( p_endpt->rel.p_parent_obj, ipoib_port_t, obj ); +} + +ipoib_port_t* +ipoib_endpt_parent( + IN ipoib_endpt_t* const p_endpt ) +{ + return __endpt_parent( p_endpt ); +} + +/* + * This function is called with the port object's send lock held and + * a reference held on the endpoint. If we fail, we release the reference. + */ +NDIS_STATUS +ipoib_endpt_queue( + IN ipoib_endpt_t* const p_endpt ) +{ + ib_api_status_t status; + ipoib_port_t *p_port; + ib_av_attr_t av_attr; + net32_t flow_lbl; + + IPOIB_ENTER( IPOIB_DBG_ENDPT ); + + if( p_endpt->h_av ) + { + IPOIB_EXIT( IPOIB_DBG_ENDPT ); + return NDIS_STATUS_SUCCESS; + } + + if( p_endpt->qpn == CL_HTON32(0x00FFFFFF) ) + { + /* + * Handle a race between the mcast callback and a receive/send. The QP + * is joined to the MC group before the MC callback is received, so it + * can receive packets, and NDIS can try to respond. We need to delay + * a response until the MC callback runs and sets the AV. + */ + ipoib_endpt_deref( p_endpt ); + IPOIB_EXIT( IPOIB_DBG_ENDPT ); + return NDIS_STATUS_PENDING; + } + + /* This is the first packet for this endpoint. Create the AV. */ + p_port = __endpt_parent( p_endpt ); + + cl_memclr( &av_attr, sizeof(ib_av_attr_t) ); + + av_attr.port_num = p_port->port_num; + + ib_member_get_sl_flow_hop( + p_port->ib_mgr.bcast_rec.sl_flow_hop, + &av_attr.sl, + &flow_lbl, + &av_attr.grh.hop_limit + ); + + av_attr.dlid = p_endpt->dlid; + + /* + * We always send the GRH so that we preferably lookup endpoints + * by GID rather than by LID. This allows certain WHQL tests + * such as the 2c_MediaCheck test to succeed since they don't use + * IP. This allows endpoints to be created on the fly for requests + * for which there is no match, something that doesn't work when + * using LIDs only. + */ + av_attr.grh_valid = TRUE; + av_attr.grh.ver_class_flow = ib_grh_set_ver_class_flow( + 6, p_port->ib_mgr.bcast_rec.tclass, flow_lbl ); + av_attr.grh.resv1 = 0; + av_attr.grh.resv2 = 0; + ib_gid_set_default( &av_attr.grh.src_gid, p_port->p_adapter->guids.port_guid.guid ); + av_attr.grh.dest_gid = p_endpt->dgid; + + av_attr.static_rate = p_port->ib_mgr.bcast_rec.rate; + av_attr.path_bits = 0; + + /* Create the AV. */ + status = p_port->p_adapter->p_ifc->create_av( + p_port->ib_mgr.h_pd, &av_attr, &p_endpt->h_av ); + if( status != IB_SUCCESS ) + { + p_port->p_adapter->hung = TRUE; + ipoib_endpt_deref( p_endpt ); + cl_obj_unlock( &p_endpt->obj ); + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ib_create_av failed with %s\n", + p_port->p_adapter->p_ifc->get_err_str( status )) ); + return NDIS_STATUS_FAILURE; + } + + IPOIB_EXIT( IPOIB_DBG_ENDPT ); + return NDIS_STATUS_SUCCESS; +} + +#if 0 + +static void +__endpt_cm_buf_mgr_construct( + IN endpt_buf_mgr_t * const p_buf_mgr ) +{ + IPOIB_ENTER( IPOIB_DBG_INIT ); + + cl_qpool_construct( &p_buf_mgr->recv_pool ); + + p_buf_mgr->h_packet_pool = NULL; + p_buf_mgr->h_buffer_pool = NULL; + + IPOIB_EXIT( IPOIB_DBG_INIT ); +} + +ib_api_status_t +endpt_cm_buf_mgr_init( + IN ipoib_port_t* const p_port ) +{ + cl_status_t cl_status; + NDIS_STATUS ndis_status; + ib_api_status_t ib_status = IB_SUCCESS; + + IPOIB_ENTER( IPOIB_DBG_INIT ); + + if( p_port->cm_buf_mgr.pool_init ) + return ib_status; + + cl_qlist_init( &p_port->cm_buf_mgr.posted_list ); + + __endpt_cm_buf_mgr_construct( &p_port->cm_buf_mgr ); + p_port->cm_recv_mgr.rq_depth = + min( (uint32_t)p_port->p_adapter->params.rq_depth * 8, + p_port->p_ca_attrs->max_srq_wrs/2 ); + p_port->cm_recv_mgr.depth = 0; + /* Allocate the receive descriptors pool */ + cl_status = cl_qpool_init( &p_port->cm_buf_mgr.recv_pool, + p_port->cm_recv_mgr.rq_depth , + 0, + 0, + sizeof( ipoib_cm_desc_t ), + __cm_recv_desc_ctor, + __cm_recv_desc_dtor, + p_port ); + + if( cl_status != CL_SUCCESS ) + { + NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, + EVENT_IPOIB_RECV_POOL, 1, cl_status ); + + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("cl_qpool_init for cm recvs returned %#x\n", cl_status) ); + + return IB_INSUFFICIENT_MEMORY; + } + + /* Allocate the NDIS buffer and packet pools for receive indication. */ + NdisAllocatePacketPool( &ndis_status, + &p_port->cm_buf_mgr.h_packet_pool, + p_port->cm_recv_mgr.rq_depth, + PROTOCOL_RESERVED_SIZE_IN_PACKET ); + if( ndis_status != NDIS_STATUS_SUCCESS ) + { + NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, + EVENT_IPOIB_RECV_PKT_POOL, 1, ndis_status ); + + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("NdisAllocatePacketPool returned %08X\n", ndis_status) ); + + ib_status = IB_INSUFFICIENT_RESOURCES; + goto pkt_pool_failed; + } + + NdisAllocateBufferPool( &ndis_status, + &p_port->cm_buf_mgr.h_buffer_pool, + p_port->cm_recv_mgr.rq_depth ); + if( ndis_status != NDIS_STATUS_SUCCESS ) + { + NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, + EVENT_IPOIB_RECV_BUF_POOL, 1, ndis_status ); + + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("NdisAllocateBufferPool returned %08X\n", ndis_status) ); + + ib_status = IB_INSUFFICIENT_RESOURCES; + goto buf_pool_failed; + } + //NDIS60 + //p_port->cm_recv_mgr.recv_pkt_array = + //cl_zalloc( sizeof(NDIS_PACKET*) * p_port->cm_recv_mgr.rq_depth ); + p_port->cm_recv_mgr.recv_lst_array = + cl_zalloc( sizeof(NET_BUFFER_LIST*) * p_port->cm_recv_mgr.rq_depth ); + + + + if( !p_port->cm_recv_mgr.recv_pkt_array ) + { + //NDIS60 + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("cl_zalloc for NET_BUFFER_LIST array failed.\n") ); + + ib_status = IB_INSUFFICIENT_MEMORY; + goto pkt_array_failed; + } + + p_port->cm_buf_mgr.pool_init = TRUE; + return IB_SUCCESS; + +pkt_array_failed: + if( p_port->cm_buf_mgr.h_buffer_pool ) + NdisFreeBufferPool( p_port->cm_buf_mgr.h_buffer_pool ); +buf_pool_failed: + if( p_port->cm_buf_mgr.h_packet_pool ) + NdisFreePacketPool( p_port->cm_buf_mgr.h_packet_pool ); +pkt_pool_failed: + cl_qpool_destroy( &p_port->cm_buf_mgr.recv_pool ); + + IPOIB_EXIT( IPOIB_DBG_INIT ); + return ib_status; +} + +void +endpt_cm_buf_mgr_reset( + IN ipoib_port_t* const p_port ) +{ + cl_list_item_t *p_item; + + if( !p_port->cm_buf_mgr.pool_init ) + return; + + if( cl_qlist_count( &p_port->cm_buf_mgr.posted_list ) ) + { + for( p_item = cl_qlist_remove_head( &p_port->cm_buf_mgr.posted_list ); + p_item != cl_qlist_end( &p_port->cm_buf_mgr.posted_list ); + p_item = cl_qlist_remove_head( &p_port->cm_buf_mgr.posted_list ) ) + { + cl_qpool_put( &p_port->cm_buf_mgr.recv_pool, + &( PARENT_STRUCT( p_item, ipoib_cm_desc_t, list_item ))->item ); + } + } +} + +void +endpt_cm_buf_mgr_destroy( + IN ipoib_port_t* const p_port ) +{ + + IPOIB_ENTER(IPOIB_DBG_INIT ); + + CL_ASSERT( p_port ); + + /* Free the receive descriptors. */ + if( !p_port->cm_buf_mgr.pool_init ) + return; + + endpt_cm_buf_mgr_reset( p_port ); + + p_port->cm_buf_mgr.pool_init = FALSE; + + if( p_port->cm_recv_mgr.recv_pkt_array ) + { + cl_free( p_port->cm_recv_mgr.recv_pkt_array ); + } + + /* Destroy the receive packet and buffer pools. */ + if( p_port->cm_buf_mgr.h_buffer_pool ) + NdisFreeBufferPool( p_port->cm_buf_mgr.h_buffer_pool ); + if( p_port->cm_buf_mgr.h_packet_pool ) + NdisFreePacketPool( p_port->cm_buf_mgr.h_packet_pool ); + + cl_qpool_destroy( &p_port->cm_buf_mgr.recv_pool ); + + IPOIB_EXIT( IPOIB_DBG_INIT ); +} + +static cl_status_t +__cm_recv_desc_ctor( + IN void* const p_object, + IN void* context, + OUT cl_pool_item_t** const pp_pool_item ) +{ + ipoib_cm_desc_t* p_desc; + ipoib_port_t* p_port; + ib_mr_create_t create_mr; + net32_t rkey; + + CL_ASSERT( p_object ); + CL_ASSERT( context ); + + p_desc = (ipoib_cm_desc_t*)p_object; + p_port = (ipoib_port_t*)context; + +#define BUF_ALIGN (16) + + p_desc->alloc_buf_size = + ROUNDUP( p_port->p_adapter->params.cm_xfer_block_size, BUF_ALIGN ); + + p_desc->p_alloc_buf = (uint8_t *)ExAllocatePoolWithTag( + NonPagedPool, p_desc->alloc_buf_size, 'DOMC' ); + + if( p_desc->p_alloc_buf == NULL ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed to allocate receive buffer size %d bytes.\n", p_desc->alloc_buf_size ) ); + return CL_INSUFFICIENT_MEMORY; + } + + create_mr.vaddr = p_desc->p_alloc_buf; + create_mr.length = p_desc->alloc_buf_size; + create_mr.access_ctrl = IB_AC_LOCAL_WRITE; + + + if( p_port->p_adapter->p_ifc->reg_mem( + p_port->ib_mgr.h_pd, + &create_mr, + &p_desc->lkey, + &rkey, + &p_desc->h_mr ) != IB_SUCCESS ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed to create Memory Region size %d bytes.\n", p_desc->alloc_buf_size ) ); + goto ctor_failed; + } + p_desc->p_buf = p_desc->p_alloc_buf + (BUF_ALIGN - sizeof( ipoib_hdr_t)); + p_desc->buf_size = p_desc->alloc_buf_size - (BUF_ALIGN - sizeof( ipoib_hdr_t)); + + /* Setup the local data segment. */ + p_desc->local_ds[0].vaddr = (uint64_t)(uintn_t)p_desc->p_buf; + p_desc->local_ds[0].length = p_desc->buf_size; + p_desc->local_ds[0].lkey = p_desc->lkey; + + /* Setup the work request. */ + p_desc->wr.wr_id = (uintn_t)p_desc; + p_desc->wr.ds_array = p_desc->local_ds; + p_desc->wr.num_ds = 1; + p_desc->type = PKT_TYPE_CM_UCAST; + + *pp_pool_item = &p_desc->item; + return CL_SUCCESS; + +ctor_failed: + ExFreePoolWithTag( p_desc->p_alloc_buf, 'DOMC' ); + return CL_INSUFFICIENT_MEMORY; +} + +static void +__cm_recv_desc_dtor( + IN const cl_pool_item_t* const p_pool_item, + IN void *context ) +{ + ipoib_cm_desc_t *p_desc; + ipoib_port_t* p_port; + + if( p_pool_item == NULL || context == NULL ) + return; + + p_port = (ipoib_port_t*)context; + p_desc = PARENT_STRUCT( p_pool_item, ipoib_cm_desc_t, item ); + + if( p_desc->h_mr ) + p_port->p_adapter->p_ifc->dereg_mr( p_desc->h_mr ); + + if( p_desc->p_alloc_buf ) + ExFreePoolWithTag( p_desc->p_alloc_buf, 'DOMC' ); +} + + +static NDIS_PACKET* +__endpt_cm_get_ndis_pkt( + IN ipoib_port_t* const p_port, + IN ipoib_cm_desc_t* const p_desc ) +{ + NDIS_STATUS status; + NDIS_PACKET *p_packet; + NDIS_BUFFER *p_buffer; + + IPOIB_ENTER( IPOIB_DBG_RECV ); + + NdisDprAllocatePacketNonInterlocked( &status, &p_packet, + p_port->cm_buf_mgr.h_packet_pool ); + if( status != NDIS_STATUS_SUCCESS ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed to allocate NDIS_PACKET: %08x\n", status) ); + return NULL; + } + + IPOIB_PORT_FROM_PACKET( p_packet ) = p_port; + IPOIB_RECV_FROM_PACKET( p_packet ) = p_desc; + + NdisAllocateBuffer( + &status, + &p_buffer, + p_port->cm_buf_mgr.h_buffer_pool, + (void *)(p_desc->p_buf - DATA_OFFSET), + p_desc->len + DATA_OFFSET ); + + if( status != NDIS_STATUS_SUCCESS ) + { + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed to allocate NDIS_BUFFER: %08x\n", status) ); + NdisDprFreePacketNonInterlocked( p_packet ); + return NULL; + } + + NdisChainBufferAtFront( p_packet, p_buffer ); + NDIS_SET_PACKET_HEADER_SIZE( p_packet, sizeof(eth_hdr_t) ); + + IPOIB_EXIT( IPOIB_DBG_RECV ); + return p_packet; +} + +static inline ipoib_cm_desc_t* +__endpt_cm_buf_mgr_get_recv( + IN endpt_buf_mgr_t * const p_buf_mgr ) +{ + ipoib_cm_desc_t *p_desc; + + p_desc = (ipoib_cm_desc_t*)cl_qpool_get( &p_buf_mgr->recv_pool ); + if( p_desc ) + cl_qlist_insert_tail( &p_buf_mgr->posted_list, &p_desc->list_item ); + + return p_desc; +} + +void +endpt_cm_buf_mgr_put_recv( + IN endpt_buf_mgr_t * const p_buf_mgr, + IN ipoib_cm_desc_t* const p_desc ) +{ + + IPOIB_ENTER(IPOIB_DBG_RECV ); + + /* Return the descriptor to it's pool. */ + cl_qlist_remove_item( &p_buf_mgr->posted_list, &p_desc->list_item ); + cl_qpool_put( &p_buf_mgr->recv_pool, &p_desc->item ); + + IPOIB_EXIT( IPOIB_DBG_RECV ); +} + +void +endpt_cm_buf_mgr_put_recv_list( + IN endpt_buf_mgr_t * const p_buf_mgr, + IN cl_qlist_t* const p_list ) +{ + cl_qpool_put_list( &p_buf_mgr->recv_pool, p_list ); +} + +uint32_t +endpt_cm_recv_mgr_build_pkt_array( + IN ipoib_port_t* const p_port, + IN ipoib_endpt_t* const p_endpt, + IN cl_qlist_t* const p_done_list, + IN OUT uint32_t* p_bytes_recv ) +{ + cl_list_item_t *p_item; + ipoib_cm_desc_t *p_desc; + uint32_t i = 0; + NDIS_PACKET *p_packet; + NDIS_TCP_IP_CHECKSUM_PACKET_INFO chksum; + + IPOIB_ENTER( IPOIB_DBG_RECV ); + UNUSED_PARAM( p_endpt ); + + p_item = cl_qlist_remove_head( p_done_list ); + + *p_bytes_recv = 0; + + for( p_item; p_item != cl_qlist_end( p_done_list ); + p_item = cl_qlist_remove_head( p_done_list ) ) + { + p_desc = (ipoib_cm_desc_t*)p_item; + + p_packet = __endpt_cm_get_ndis_pkt( p_port, p_desc ); + if( !p_packet ) + { + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed to get Packet from descriptor\n" ) ); + endpt_cm_buf_mgr_put_recv( &p_port->cm_buf_mgr, p_desc ); + p_port->cm_recv_mgr.depth--; + continue; + } + chksum.Value = 0; + switch( p_port->p_adapter->params.recv_chksum_offload ) + { + default: + CL_ASSERT( FALSE ); + case CSUM_DISABLED: + case CSUM_ENABLED: + NDIS_PER_PACKET_INFO_FROM_PACKET( p_packet, TcpIpChecksumPacketInfo ) = + (void*)(uintn_t)chksum.Value; + break; + case CSUM_BYPASS: + /* Flag the checksums as having been calculated. */ + chksum.Receive.NdisPacketTcpChecksumSucceeded = TRUE; + chksum.Receive.NdisPacketUdpChecksumSucceeded = TRUE; + chksum.Receive.NdisPacketIpChecksumSucceeded = TRUE; + NDIS_PER_PACKET_INFO_FROM_PACKET( p_packet, TcpIpChecksumPacketInfo ) = + (void*)(uintn_t)chksum.Value; + break; + } + + NDIS_SET_PACKET_STATUS( p_packet, NDIS_STATUS_SUCCESS ); + p_port->cm_recv_mgr.recv_pkt_array[i] = p_packet; + i++; + *p_bytes_recv += p_desc->len; + } + + IPOIB_EXIT( IPOIB_DBG_RECV ); + return i; +} +void +endpt_cm_flush_recv( + IN ipoib_port_t* const p_port, + IN ipoib_endpt_t* const p_endpt ) +{ + ib_api_status_t ib_status = IB_SUCCESS; + ib_qp_mod_t mod_attr; + ib_wc_t wc[MAX_RECV_WC]; + ib_wc_t *p_free_wc; + ib_wc_t *p_done_wc; + ib_wc_t *p_wc; + ipoib_cm_desc_t *p_desc; + size_t i; + + IPOIB_ENTER( IPOIB_DBG_RECV ); + + CL_ASSERT( p_endpt ); + + if( p_endpt->conn.h_recv_qp ) + { + cl_memclr( &mod_attr, sizeof( mod_attr ) ); + mod_attr.req_state = IB_QPS_ERROR; + p_port->p_adapter->p_ifc->modify_qp( p_endpt->conn.h_send_qp, &mod_attr ); + p_port->p_adapter->p_ifc->modify_qp( p_endpt->conn.h_recv_qp, &mod_attr ); + + for( i = 0; i < MAX_RECV_WC; i++ ) + wc[i].p_next = &wc[i + 1]; + wc[MAX_RECV_WC - 1].p_next = NULL; + + do + { + p_free_wc = wc; + ib_status = + p_port->p_adapter->p_ifc->poll_cq( p_endpt->conn.h_recv_cq, + &p_free_wc, &p_done_wc ); + if( ib_status != IB_SUCCESS && + ib_status != IB_NOT_FOUND ) + { + /* connection CQ failed */ + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Poll Recv CQ failed status %#x\n", ib_status ) ); + break; + } + cl_spinlock_acquire( &p_port->recv_lock ); + for( p_wc = p_done_wc; p_wc; p_wc = p_wc->p_next ) + { + p_desc = (ipoib_cm_desc_t *)(uintn_t)p_wc->wr_id; + endpt_cm_buf_mgr_put_recv( &p_port->cm_buf_mgr, p_desc ); + p_port->cm_recv_mgr.depth--; + } + cl_spinlock_release( &p_port->recv_lock ); + } while( !p_free_wc ); + + ib_status = p_port->p_adapter->p_ifc->destroy_qp( p_endpt->conn.h_recv_qp, NULL ); + if( ib_status != IB_SUCCESS ) + { + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Destroy Recv QP failed status %#x\n", ib_status ) ); + } + p_endpt->conn.h_recv_qp = NULL; + } + + if( p_endpt->conn.h_send_qp ) + { + ib_status = p_port->p_adapter->p_ifc->destroy_qp( p_endpt->conn.h_send_qp, NULL ); + if( ib_status != IB_SUCCESS ) + { + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Destroy Send QP failed status %#x\n", ib_status ) ); + } + p_endpt->conn.h_send_qp = NULL; + } + + IPOIB_EXIT( IPOIB_DBG_RECV ); +} + +int32_t +endpt_cm_recv_mgr_filter( + IN ipoib_endpt_t* const p_endpt, + IN ib_wc_t* const p_done_wc_list, + OUT cl_qlist_t* const p_done_list, + OUT cl_qlist_t* const p_bad_list ) +{ + ib_api_status_t ib_status; + ipoib_cm_desc_t *p_desc; + ib_wc_t *p_wc; + ipoib_pkt_t *p_ipoib; + eth_pkt_t *p_eth; + ipoib_port_t* p_port; + int32_t recv_cnt; + + IPOIB_ENTER( IPOIB_DBG_RECV ); + + p_port = ipoib_endpt_parent( p_endpt ); + + for( p_wc = p_done_wc_list, recv_cnt = 0; p_wc; p_wc = p_wc->p_next ) + { + p_desc = (ipoib_cm_desc_t *)(uintn_t)p_wc->wr_id; + recv_cnt++; + if( p_wc->status != IB_WCS_SUCCESS ) + { + if( p_wc->status != IB_WCS_WR_FLUSHED_ERR ) + { + + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed completion %s (vendor specific %#x)\n", + p_port->p_adapter->p_ifc->get_wc_status_str( p_wc->status ), + (int)p_wc->vendor_specific) ); + } + else + { + IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_RECV, + ("Flushed completion %s\n", + p_port->p_adapter->p_ifc->get_wc_status_str( p_wc->status )) ); + } + + ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_ERROR, 0, 0 ); + + cl_qlist_remove_item( &p_port->cm_buf_mgr.posted_list,&p_desc->list_item ); + cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item ); + continue; + } + + /* Successful completion + Setup the ethernet/ip/arp header and queue descriptor for report. */ + ib_status = IB_SUCCESS; + p_ipoib = (ipoib_pkt_t *)((uint8_t*)p_desc->p_buf ); + p_eth = (eth_pkt_t *)((uint8_t*)p_desc->p_buf - DATA_OFFSET ); + + switch( p_ipoib->hdr.type ) + { + case ETH_PROT_TYPE_ARP: + if( p_wc->length < (sizeof(ipoib_hdr_t) + sizeof(ipoib_arp_pkt_t)) ) + { + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Received ARP packet too short\n") ); + ib_status = IB_ERROR; + break; + } + ib_status = + __endpt_cm_recv_arp( p_port, p_ipoib, p_eth, p_endpt ); + break; + case ETH_PROT_TYPE_IP: + if( p_wc->length < (sizeof(ipoib_hdr_t) + sizeof(ip_hdr_t)) ) + { + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Received IP packet too short\n") ); + ib_status = IB_ERROR; + break; + } + if( p_ipoib->type.ip.hdr.prot == IP_PROT_UDP ) + { + ib_status = + __endpt_cm_recv_udp( p_port, p_wc, p_ipoib, p_eth, p_endpt ); + } + + break; + } + + if( ib_status != IB_SUCCESS ) + { + ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_ERROR, 0, 0 ); + cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item ); + continue; + } + + p_eth->hdr.type = p_ipoib->hdr.type; + p_eth->hdr.src = p_endpt->mac; + p_eth->hdr.dst = p_port->p_adapter->mac; + + /* save payload length */ + p_desc->len = p_wc->length; + + cl_qlist_insert_tail( p_done_list, &p_desc->item.list_item ); + } + + IPOIB_EXIT( IPOIB_DBG_RECV ); + return recv_cnt; +} + +ib_api_status_t +endpt_cm_post_recv( + IN ipoib_port_t* const p_port ) +{ + ib_api_status_t ib_status = IB_SUCCESS; + ipoib_cm_desc_t *p_head_desc = NULL; + ipoib_cm_desc_t *p_tail_desc = NULL; + ipoib_cm_desc_t *p_next_desc; + ib_recv_wr_t *p_failed_wc = NULL; + + IPOIB_ENTER( IPOIB_DBG_RECV ); + + while( cl_qpool_count( &p_port->cm_buf_mgr.recv_pool ) > 1 ) + { + /* Pull receives out of the pool and chain them up. */ + p_next_desc = __endpt_cm_buf_mgr_get_recv( + &p_port->cm_buf_mgr ); + if( !p_next_desc ) + { + IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_RECV, + ("Out of receive descriptors! Endpt recv queue depth 0x%x\n", + p_port->cm_recv_mgr.depth ) ); + break; + } + + if( !p_tail_desc ) + { + p_tail_desc = p_next_desc; + p_next_desc->wr.p_next = NULL; + } + else + { + p_next_desc->wr.p_next = &p_head_desc->wr; + } + + p_head_desc = p_next_desc; + + p_port->cm_recv_mgr.depth++; + } + + if( p_head_desc ) + { + ib_status = p_port->p_adapter->p_ifc->post_srq_recv( + p_port->ib_mgr.h_srq, &p_head_desc->wr, &p_failed_wc ); + + if( ib_status != IB_SUCCESS ) + { + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ip_post_recv returned %s\n", + p_port->p_adapter->p_ifc->get_err_str( ib_status )) ); + + /* put descriptors back to the pool */ + while( p_failed_wc ) + { + p_head_desc = PARENT_STRUCT( p_failed_wc, ipoib_cm_desc_t, wr ); + p_failed_wc = p_failed_wc->p_next; + endpt_cm_buf_mgr_put_recv( &p_port->cm_buf_mgr, p_head_desc ); + p_port->cm_recv_mgr.depth--; + } + } + } + + + IPOIB_EXIT( IPOIB_DBG_RECV ); + return( ib_status ); +} + +static ib_api_status_t +__endpt_cm_recv_arp( + IN ipoib_port_t* const p_port, + IN const ipoib_pkt_t* const p_ipoib, + OUT eth_pkt_t* const p_eth, + IN ipoib_endpt_t* const p_src_endpt ) +{ + const ipoib_arp_pkt_t *p_ib_arp; + arp_pkt_t *p_arp; + + p_ib_arp = &p_ipoib->type.arp; + p_arp = &p_eth->type.arp; + + if( p_ib_arp->hw_type != ARP_HW_TYPE_IB || + p_ib_arp->hw_size != sizeof(ipoib_hw_addr_t) || + p_ib_arp->prot_type != ETH_PROT_TYPE_IP ) + { + return IB_ERROR; + } + + p_arp->hw_type = ARP_HW_TYPE_ETH; + p_arp->hw_size = sizeof(mac_addr_t); + p_arp->src_hw = p_src_endpt->mac; + p_arp->src_ip = p_ib_arp->src_ip; + p_arp->dst_hw = p_port->p_local_endpt->mac; + p_arp->dst_ip = p_ib_arp->dst_ip; + + return IB_SUCCESS; +} + +static ib_api_status_t +__endpt_cm_recv_udp( + IN ipoib_port_t* const p_port, + IN ib_wc_t* const p_wc, + IN const ipoib_pkt_t* const p_ipoib, + OUT eth_pkt_t* const p_eth, + IN ipoib_endpt_t* const p_src_endpt ) +{ + ib_api_status_t ib_status = IB_SUCCESS; + + if( p_wc->length < + (sizeof(ipoib_hdr_t) + sizeof(ip_hdr_t) + sizeof(udp_hdr_t)) ) + { + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Received UDP packet too short\n") ); + return IB_ERROR; + } + if( __cm_recv_is_dhcp( p_ipoib ) ) + { + ib_status = ipoib_recv_dhcp( + p_port, p_ipoib, p_eth, p_src_endpt, p_port->p_local_endpt ); + } + + return ib_status; +} + +static boolean_t +__cm_recv_is_dhcp( + IN const ipoib_pkt_t* const p_ipoib ) +{ + return( (p_ipoib->type.ip.prot.udp.hdr.dst_port == DHCP_PORT_SERVER && + p_ipoib->type.ip.prot.udp.hdr.src_port == DHCP_PORT_CLIENT) || + (p_ipoib->type.ip.prot.udp.hdr.dst_port == DHCP_PORT_CLIENT && + p_ipoib->type.ip.prot.udp.hdr.src_port == DHCP_PORT_SERVER) ); +} +#endif diff --git a/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_ibat.c b/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_ibat.c deleted file mode 100644 index a7703665..00000000 --- a/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_ibat.c +++ /dev/null @@ -1,693 +0,0 @@ -/* - * Copyright (c) 2005 Mellanox Technologies. All rights reserved. - * Copyright (c) 2005 SilverStorm Technologies. All rights reserved. - * Portions Copyright (c) 2008 Microsoft 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: ipoib_ibat.c 4494 2009-06-22 14:31:08Z xalex $ - */ - - -#include "ipoib_driver.h" -#include "ipoib_adapter.h" -#include "ipoib_port.h" -#include "ipoib_debug.h" -#if defined(EVENT_TRACING) -#ifdef offsetof -#undef offsetof -#endif -#include "ipoib_ibat.tmh" -#endif -#include - -extern PDRIVER_OBJECT g_p_drv_obj; - -static NTSTATUS -__ipoib_create( - IN DEVICE_OBJECT* const pDevObj, - IN IRP* const pIrp ); - -static NTSTATUS -__ipoib_cleanup( - IN DEVICE_OBJECT* const pDevObj, - IN IRP* const pIrp ); - -static NTSTATUS -__ipoib_close( - IN DEVICE_OBJECT* const pDevObj, - IN IRP* const pIrp ); - -static NTSTATUS -__ipoib_dispatch( - IN DEVICE_OBJECT* const pDevObj, - IN IRP* const pIrp ); - - -static NTSTATUS -__ibat_get_ports( - IN IRP *pIrp, - IN IO_STACK_LOCATION *pIoStack ) -{ - IOCTL_IBAT_PORTS_IN *pIn; - IOCTL_IBAT_PORTS_OUT *pOut; - KLOCK_QUEUE_HANDLE hdl; - cl_list_item_t *pItem; - ipoib_adapter_t *pAdapter; - LONG nPorts; - - IPOIB_ENTER(IPOIB_DBG_IOCTL); - - if( pIoStack->Parameters.DeviceIoControl.InputBufferLength != - sizeof(IOCTL_IBAT_PORTS_IN) ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Invalid input buffer size.\n") ); - return STATUS_INVALID_PARAMETER; - } - - if( pIoStack->Parameters.DeviceIoControl.OutputBufferLength < - sizeof(IOCTL_IBAT_PORTS_OUT) ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Invalid output buffer size.\n") ); - return STATUS_INVALID_PARAMETER; - } - - pIn = pIrp->AssociatedIrp.SystemBuffer; - pOut = pIrp->AssociatedIrp.SystemBuffer; - - if( pIn->Version != IBAT_IOCTL_VERSION ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Invalid version.\n") ); - return STATUS_INVALID_PARAMETER; - } - - KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl ); - nPorts = (LONG)cl_qlist_count( &g_ipoib.adapter_list ); - switch( nPorts ) - { - case 0: - cl_memclr( pOut->Ports, sizeof(pOut->Ports) ); - /* Fall through */ - case 1: - pOut->Size = sizeof(IOCTL_IBAT_PORTS_OUT); - break; - - default: - pOut->Size = sizeof(IOCTL_IBAT_PORTS_OUT) + - (sizeof(IBAT_PORT_RECORD) * (nPorts - 1)); - break; - } - - pIrp->IoStatus.Information = pOut->Size; - - if( pOut->Size > pIoStack->Parameters.DeviceIoControl.OutputBufferLength ) - { - nPorts = 1 + - (pIoStack->Parameters.DeviceIoControl.OutputBufferLength - - sizeof(IOCTL_IBAT_PORTS_OUT)) / sizeof(IBAT_PORT_RECORD); - - pIrp->IoStatus.Information = sizeof(IOCTL_IBAT_PORTS_OUT) + - ((nPorts - 1) * sizeof(IBAT_PORT_RECORD)); - } - - pOut->NumPorts = 0; - pItem = cl_qlist_head( &g_ipoib.adapter_list ); - while( pOut->NumPorts != nPorts ) - { - pAdapter = CONTAINING_RECORD( pItem, ipoib_adapter_t, entry ); - pOut->Ports[pOut->NumPorts].CaGuid = pAdapter->guids.ca_guid; - pOut->Ports[pOut->NumPorts].PortGuid = pAdapter->guids.port_guid.guid; - pOut->Ports[pOut->NumPorts].PKey = IB_DEFAULT_PKEY; - pOut->Ports[pOut->NumPorts].PortNum = pAdapter->guids.port_num; - pOut->NumPorts++; - - pItem = cl_qlist_next( pItem ); - } - - KeReleaseInStackQueuedSpinLock( &hdl ); - IPOIB_EXIT( IPOIB_DBG_IOCTL ); - return STATUS_SUCCESS; -} - - -static NTSTATUS -__ibat_get_ips( - IN IRP *pIrp, - IN IO_STACK_LOCATION *pIoStack ) -{ - IOCTL_IBAT_IP_ADDRESSES_IN *pIn; - IOCTL_IBAT_IP_ADDRESSES_OUT *pOut; - KLOCK_QUEUE_HANDLE hdl; - cl_list_item_t *pItem; - ipoib_adapter_t *pAdapter; - LONG nIps, maxIps; - size_t idx; - net_address_item_t *pAddr; - UINT64 PortGuid; - - IPOIB_ENTER(IPOIB_DBG_IOCTL); - - if( pIoStack->Parameters.DeviceIoControl.InputBufferLength != - sizeof(IOCTL_IBAT_IP_ADDRESSES_IN) ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Invalid input buffer size.\n") ); - return STATUS_INVALID_PARAMETER; - } - - if( pIoStack->Parameters.DeviceIoControl.OutputBufferLength < - sizeof(IOCTL_IBAT_IP_ADDRESSES_OUT) ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Invalid output buffer size.\n") ); - return STATUS_INVALID_PARAMETER; - } - - pIn = pIrp->AssociatedIrp.SystemBuffer; - pOut = pIrp->AssociatedIrp.SystemBuffer; - - if( pIn->Version != IBAT_IOCTL_VERSION ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Invalid version.\n") ); - return STATUS_INVALID_PARAMETER; - } - - PortGuid = pIn->PortGuid; - - nIps = 0; - pOut->AddressCount = 0; - maxIps = 1 + - ((pIoStack->Parameters.DeviceIoControl.OutputBufferLength - - sizeof(IOCTL_IBAT_IP_ADDRESSES_OUT)) / sizeof(IP_ADDRESS)); - - KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl ); - for( pItem = cl_qlist_head( &g_ipoib.adapter_list ); - pItem != cl_qlist_end( &g_ipoib.adapter_list ); - pItem = cl_qlist_next( pItem ) ) - { - pAdapter = CONTAINING_RECORD( pItem, ipoib_adapter_t, entry ); - if( PortGuid && pAdapter->guids.port_guid.guid != PortGuid ) - continue; - - cl_obj_lock( &pAdapter->obj ); - nIps += (LONG)cl_vector_get_size( &pAdapter->ip_vector ); - - for( idx = 0; - idx < cl_vector_get_size( &pAdapter->ip_vector ); - idx++ ) - { - if( pOut->AddressCount == maxIps ) - break; - - pAddr = (net_address_item_t*) - cl_vector_get_ptr( &pAdapter->ip_vector, idx ); - - pOut->Address[pOut->AddressCount].IpVersion = 4; - cl_memclr( &pOut->Address[pOut->AddressCount].Address, - sizeof(IP_ADDRESS) ); - cl_memcpy( &pOut->Address[pOut->AddressCount].Address[12], - pAddr->address.as_bytes, IPV4_ADDR_SIZE ); - - pOut->AddressCount++; - } - cl_obj_unlock( &pAdapter->obj ); - } - - pOut->Size = sizeof(IOCTL_IBAT_IP_ADDRESSES_OUT); - if( --nIps ) - pOut->Size += sizeof(IP_ADDRESS) * nIps; - - pIrp->IoStatus.Information = sizeof(IOCTL_IBAT_IP_ADDRESSES_OUT); - if( --maxIps < nIps ) - pIrp->IoStatus.Information += (sizeof(IP_ADDRESS) * maxIps); - else - pIrp->IoStatus.Information += (sizeof(IP_ADDRESS) * nIps); - - KeReleaseInStackQueuedSpinLock( &hdl ); - IPOIB_EXIT( IPOIB_DBG_IOCTL ); - return STATUS_SUCCESS; -} - - -static NTSTATUS -__ibat_mac_to_gid( - IN IRP *pIrp, - IN IO_STACK_LOCATION *pIoStack ) -{ - NTSTATUS status = STATUS_INVALID_PARAMETER; - IOCTL_IBAT_MAC_TO_GID_IN *pIn; - IOCTL_IBAT_MAC_TO_GID_OUT *pOut; - KLOCK_QUEUE_HANDLE hdl; - cl_list_item_t *pItem; - ipoib_adapter_t *pAdapter; - - IPOIB_ENTER(IPOIB_DBG_IOCTL); - - if( pIoStack->Parameters.DeviceIoControl.InputBufferLength != - sizeof(IOCTL_IBAT_MAC_TO_GID_IN) ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Invalid input buffer size.\n") ); - return STATUS_INVALID_PARAMETER; - } - - if( pIoStack->Parameters.DeviceIoControl.OutputBufferLength != - sizeof(IOCTL_IBAT_MAC_TO_GID_OUT) ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Invalid output buffer size.\n") ); - return STATUS_INVALID_PARAMETER; - } - - pIn = pIrp->AssociatedIrp.SystemBuffer; - pOut = pIrp->AssociatedIrp.SystemBuffer; - - if( pIn->Version != IBAT_IOCTL_VERSION ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Invalid version.\n") ); - return STATUS_INVALID_PARAMETER; - } - - KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl ); - - for( pItem = cl_qlist_head( &g_ipoib.adapter_list ); - pItem != cl_qlist_end( &g_ipoib.adapter_list ); - pItem = cl_qlist_next( pItem ) ) - { - pAdapter = CONTAINING_RECORD( pItem, ipoib_adapter_t, entry ); - if( pIn->PortGuid != pAdapter->guids.port_guid.guid ) - continue; - - /* Found the port - lookup the MAC. */ - cl_obj_lock( &pAdapter->obj ); - if( pAdapter->p_port ) - { - status = ipoib_mac_to_gid( - pAdapter->p_port, *(mac_addr_t*)pIn->DestMac, &pOut->DestGid ); - if( NT_SUCCESS( status ) ) - { - pIrp->IoStatus.Information = - sizeof(IOCTL_IBAT_MAC_TO_GID_OUT); - } - } - cl_obj_unlock( &pAdapter->obj ); - break; - } - - KeReleaseInStackQueuedSpinLock( &hdl ); - - IPOIB_EXIT( IPOIB_DBG_IOCTL ); - return status; -} - - -static NTSTATUS -__ibat_mac_to_path( - IN IRP *pIrp, - IN IO_STACK_LOCATION *pIoStack ) -{ - NTSTATUS status = STATUS_INVALID_PARAMETER; - IOCTL_IBAT_MAC_TO_PATH_IN *pIn; - IOCTL_IBAT_MAC_TO_PATH_OUT *pOut; - KLOCK_QUEUE_HANDLE hdl; - cl_list_item_t *pItem; - ipoib_adapter_t *pAdapter; - - IPOIB_ENTER(IPOIB_DBG_IOCTL); - - if( pIoStack->Parameters.DeviceIoControl.InputBufferLength != - sizeof(IOCTL_IBAT_MAC_TO_PATH_IN) ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Invalid input buffer size.\n") ); - return STATUS_INVALID_PARAMETER; - } - - if( pIoStack->Parameters.DeviceIoControl.OutputBufferLength != - sizeof(IOCTL_IBAT_MAC_TO_PATH_OUT) ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Invalid output buffer size.\n") ); - return STATUS_INVALID_PARAMETER; - } - - pIn = pIrp->AssociatedIrp.SystemBuffer; - pOut = pIrp->AssociatedIrp.SystemBuffer; - - if( pIn->Version != IBAT_IOCTL_VERSION ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Invalid version.\n") ); - return STATUS_INVALID_PARAMETER; - } - - KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl ); - - for( pItem = cl_qlist_head( &g_ipoib.adapter_list ); - pItem != cl_qlist_end( &g_ipoib.adapter_list ); - pItem = cl_qlist_next( pItem ) ) - { - pAdapter = CONTAINING_RECORD( pItem, ipoib_adapter_t, entry ); - if( pIn->PortGuid != pAdapter->guids.port_guid.guid ) - continue; - - /* Found the port - lookup the MAC. */ - cl_obj_lock( &pAdapter->obj ); - if( pAdapter->p_port ) - { - status = ipoib_mac_to_path( - pAdapter->p_port, *(mac_addr_t*)pIn->DestMac, &pOut->Path ); - - if( NT_SUCCESS( status ) ) - { - pIrp->IoStatus.Information = - sizeof(IOCTL_IBAT_MAC_TO_PATH_OUT); - } - } - cl_obj_unlock( &pAdapter->obj ); - break; - } - - KeReleaseInStackQueuedSpinLock( &hdl ); - - IPOIB_EXIT( IPOIB_DBG_IOCTL ); - return status; -} - - -static NTSTATUS -__ibat_ip_to_port( - IN IRP *pIrp, - IN IO_STACK_LOCATION *pIoStack ) -{ - IOCTL_IBAT_IP_TO_PORT_IN *pIn; - IOCTL_IBAT_IP_TO_PORT_OUT *pOut; - KLOCK_QUEUE_HANDLE hdl; - cl_list_item_t *pItem; - ipoib_adapter_t *pAdapter; - size_t idx; - net_address_item_t *pAddr; - NTSTATUS status = STATUS_NOT_FOUND; - - IPOIB_ENTER(IPOIB_DBG_IOCTL); - - if( pIoStack->Parameters.DeviceIoControl.InputBufferLength != - sizeof(IOCTL_IBAT_IP_TO_PORT_IN) ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Invalid input buffer size.\n") ); - return STATUS_INVALID_PARAMETER; - } - - if( pIoStack->Parameters.DeviceIoControl.OutputBufferLength != - sizeof(IOCTL_IBAT_IP_TO_PORT_OUT) ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Invalid output buffer size.\n") ); - return STATUS_INVALID_PARAMETER; - } - - pIn = pIrp->AssociatedIrp.SystemBuffer; - pOut = pIrp->AssociatedIrp.SystemBuffer; - - if( pIn->Version != IBAT_IOCTL_VERSION ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Invalid version.\n") ); - return STATUS_INVALID_PARAMETER; - } - - if (pIn->Address.IpVersion != 4) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Invalid IP version (%d). Supported only 4\n", pIn->Address.IpVersion) ); - return STATUS_INVALID_PARAMETER; - } - - KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl ); - for( pItem = cl_qlist_head( &g_ipoib.adapter_list ); - pItem != cl_qlist_end( &g_ipoib.adapter_list ); - pItem = cl_qlist_next( pItem ) ) - { - pAdapter = CONTAINING_RECORD( pItem, ipoib_adapter_t, entry ); - - cl_obj_lock( &pAdapter->obj ); - - for( idx = 0; - idx < cl_vector_get_size( &pAdapter->ip_vector ); - idx++ ) - { - pAddr = (net_address_item_t*) - cl_vector_get_ptr( &pAdapter->ip_vector, idx ); - - if (!memcmp( &pIn->Address.Address[12], pAddr->address.as_bytes, IPV4_ADDR_SIZE)) - { - pOut->Port.CaGuid = pAdapter->guids.ca_guid; - pOut->Port.PortGuid = pAdapter->guids.port_guid.guid; - pOut->Port.PKey = IB_DEFAULT_PKEY; - pOut->Port.PortNum = pAdapter->guids.port_num; - pIrp->IoStatus.Information = sizeof(IOCTL_IBAT_IP_TO_PORT_OUT); - status = STATUS_SUCCESS; - break; - } - } - cl_obj_unlock( &pAdapter->obj ); - if (status == STATUS_SUCCESS) - break; - } - - KeReleaseInStackQueuedSpinLock( &hdl ); - IPOIB_EXIT( IPOIB_DBG_IOCTL ); - return status; -} - -void -ipoib_ref_ibat() -{ - UNICODE_STRING DeviceName; - UNICODE_STRING DeviceLinkUnicodeString; - NDIS_DEVICE_OBJECT_ATTRIBUTES DeviceObjectAttributes; - PDRIVER_DISPATCH DispatchTable[IRP_MJ_MAXIMUM_FUNCTION+1]; - - NDIS_STATUS Status = NDIS_STATUS_SUCCESS; - - IPOIB_ENTER( IPOIB_DBG_IOCTL ); - - if( InterlockedIncrement( &g_ipoib.ibat_ref ) == 1 ) - { - - NdisZeroMemory(DispatchTable, (IRP_MJ_MAXIMUM_FUNCTION+1) * sizeof(PDRIVER_DISPATCH)); - - DispatchTable[IRP_MJ_CREATE] = __ipoib_create; - DispatchTable[IRP_MJ_CLEANUP] = __ipoib_cleanup; - DispatchTable[IRP_MJ_CLOSE] = __ipoib_close; - DispatchTable[IRP_MJ_DEVICE_CONTROL] = __ipoib_dispatch; - DispatchTable[IRP_MJ_INTERNAL_DEVICE_CONTROL] = __ipoib_dispatch; - - - NdisInitUnicodeString( &DeviceName, IBAT_DEV_NAME ); - NdisInitUnicodeString( &DeviceLinkUnicodeString, IBAT_DOS_DEV_NAME ); - - - NdisZeroMemory(&DeviceObjectAttributes, sizeof(NDIS_DEVICE_OBJECT_ATTRIBUTES)); - - DeviceObjectAttributes.Header.Type = NDIS_OBJECT_TYPE_DEFAULT; // type implicit from the context - DeviceObjectAttributes.Header.Revision = NDIS_DEVICE_OBJECT_ATTRIBUTES_REVISION_1; - DeviceObjectAttributes.Header.Size = sizeof(NDIS_DEVICE_OBJECT_ATTRIBUTES); - DeviceObjectAttributes.DeviceName = &DeviceName; - DeviceObjectAttributes.SymbolicName = &DeviceLinkUnicodeString; - DeviceObjectAttributes.MajorFunctions = &DispatchTable[0]; - DeviceObjectAttributes.ExtensionSize = 0; - DeviceObjectAttributes.DefaultSDDLString = NULL; - DeviceObjectAttributes.DeviceClassGuid = 0; - - Status = NdisRegisterDeviceEx( - g_IpoibMiniportDriverHandle, - &DeviceObjectAttributes, - &g_ipoib.h_ibat_dev, - &g_ipoib.h_ibat_dev_handle); - - - - if( Status != NDIS_STATUS_SUCCESS ) - { - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("NdisRegisterDeviceEx failed with status of %d\n", Status) ); - } - } - - IPOIB_EXIT( IPOIB_DBG_IOCTL ); -} - - -void -ipoib_deref_ibat() -{ - IPOIB_ENTER( IPOIB_DBG_IOCTL ); - - if( InterlockedDecrement( &g_ipoib.ibat_ref ) ) - { - IPOIB_EXIT( IPOIB_DBG_IOCTL ); - return; - } - - if( g_ipoib.h_ibat_dev ) - { - NdisDeregisterDeviceEx( g_ipoib.h_ibat_dev_handle ); - g_ipoib.h_ibat_dev = NULL; - g_ipoib.h_ibat_dev_handle = NULL; //TODO set here INVALID_HANDLE_VALUE - } - - IPOIB_EXIT( IPOIB_DBG_IOCTL ); -} - - -static NTSTATUS -__ipoib_create( - IN DEVICE_OBJECT* const pDevObj, - IN IRP* const pIrp ) -{ - IPOIB_ENTER( IPOIB_DBG_IOCTL ); - - UNREFERENCED_PARAMETER( pDevObj ); - - ipoib_ref_ibat(); - - pIrp->IoStatus.Status = STATUS_SUCCESS; - pIrp->IoStatus.Information = 0; - IoCompleteRequest( pIrp, IO_NO_INCREMENT ); - - IPOIB_EXIT( IPOIB_DBG_IOCTL ); - return STATUS_SUCCESS; -} - - -static NTSTATUS -__ipoib_cleanup( - IN DEVICE_OBJECT* const pDevObj, - IN IRP* const pIrp ) -{ - IPOIB_ENTER( IPOIB_DBG_IOCTL ); - - UNREFERENCED_PARAMETER( pDevObj ); - - ipoib_deref_ibat(); - - pIrp->IoStatus.Status = STATUS_SUCCESS; - pIrp->IoStatus.Information = 0; - IoCompleteRequest( pIrp, IO_NO_INCREMENT ); - - IPOIB_EXIT( IPOIB_DBG_IOCTL ); - return STATUS_SUCCESS; -} - - -static NTSTATUS -__ipoib_close( - IN DEVICE_OBJECT* const pDevObj, - IN IRP* const pIrp ) -{ - IPOIB_ENTER( IPOIB_DBG_IOCTL ); - - UNREFERENCED_PARAMETER( pDevObj ); - - pIrp->IoStatus.Status = STATUS_SUCCESS; - pIrp->IoStatus.Information = 0; - IoCompleteRequest( pIrp, IO_NO_INCREMENT ); - - IPOIB_EXIT( IPOIB_DBG_IOCTL ); - return STATUS_SUCCESS; -} - - -static NTSTATUS -__ipoib_dispatch( - IN DEVICE_OBJECT* const pDevObj, - IN IRP* const pIrp ) -{ - IO_STACK_LOCATION *pIoStack; - NTSTATUS status = STATUS_SUCCESS; - - IPOIB_ENTER( IPOIB_DBG_IOCTL ); - - UNREFERENCED_PARAMETER( pDevObj ); - - pIoStack = IoGetCurrentIrpStackLocation( pIrp ); - - pIrp->IoStatus.Information = 0; - - switch( pIoStack->Parameters.DeviceIoControl.IoControlCode ) - { - case IOCTL_IBAT_PORTS: - IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_IOCTL, - ("IOCTL_IBAT_PORTS received\n") ); - status = __ibat_get_ports( pIrp, pIoStack ); - break; - - case IOCTL_IBAT_IP_ADDRESSES: - IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_IOCTL, - ("IOCTL_IBAT_IP_ADDRESSES received\n" )); - status = __ibat_get_ips( pIrp, pIoStack ); - break; - - case IOCTL_IBAT_MAC_TO_GID: - IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_IOCTL, - ("IOCTL_IBAT_MAC_TO_GID received\n" )); - status = __ibat_mac_to_gid( pIrp, pIoStack ); - break; - - case IOCTL_IBAT_IP_TO_PORT: - IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_IOCTL, - ("IOCTL_IBAT_IP_TO_PORT received\n" )); - status = __ibat_ip_to_port( pIrp, pIoStack ); - break; - - case IOCTL_IBAT_MAC_TO_PATH: - IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_IOCTL, - ("IOCTL_IBAT_MAC_TO_PATH received\n" )); - status = __ibat_mac_to_path( pIrp, pIoStack ); - break; - - default: - IPOIB_PRINT( TRACE_LEVEL_VERBOSE, IPOIB_DBG_IOCTL, - ("unknow IOCTL code = 0x%x\n", - pIoStack->Parameters.DeviceIoControl.IoControlCode) ); - status = STATUS_INVALID_PARAMETER; - } - - pIrp->IoStatus.Status = status; - IoCompleteRequest( pIrp, IO_NO_INCREMENT ); - - IPOIB_EXIT( IPOIB_DBG_IOCTL ); - return status; -} - - diff --git a/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_ibat.cpp b/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_ibat.cpp new file mode 100644 index 00000000..1e207bca --- /dev/null +++ b/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_ibat.cpp @@ -0,0 +1,693 @@ +/* + * Copyright (c) 2005 Mellanox Technologies. All rights reserved. + * Copyright (c) 2005 SilverStorm Technologies. All rights reserved. + * Portions Copyright (c) 2008 Microsoft 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: ipoib_ibat.c 4494 2009-06-22 14:31:08Z xalex $ + */ + + +#include "ipoib_driver.h" +#include "ipoib_adapter.h" +#include "ipoib_port.h" +#include "ipoib_debug.h" +#if defined(EVENT_TRACING) +#ifdef offsetof +#undef offsetof +#endif +#include "ipoib_ibat.tmh" +#endif +#include + +extern PDRIVER_OBJECT g_p_drv_obj; + +static NTSTATUS +__ipoib_create( + IN DEVICE_OBJECT* const pDevObj, + IN IRP* const pIrp ); + +static NTSTATUS +__ipoib_cleanup( + IN DEVICE_OBJECT* const pDevObj, + IN IRP* const pIrp ); + +static NTSTATUS +__ipoib_close( + IN DEVICE_OBJECT* const pDevObj, + IN IRP* const pIrp ); + +static NTSTATUS +__ipoib_dispatch( + IN DEVICE_OBJECT* const pDevObj, + IN IRP* const pIrp ); + + +static NTSTATUS +__ibat_get_ports( + IN IRP *pIrp, + IN IO_STACK_LOCATION *pIoStack ) +{ + IOCTL_IBAT_PORTS_IN *pIn; + IOCTL_IBAT_PORTS_OUT *pOut; + KLOCK_QUEUE_HANDLE hdl; + cl_list_item_t *pItem; + ipoib_adapter_t *pAdapter; + LONG nPorts; + + IPOIB_ENTER(IPOIB_DBG_IOCTL); + + if( pIoStack->Parameters.DeviceIoControl.InputBufferLength != + sizeof(IOCTL_IBAT_PORTS_IN) ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Invalid input buffer size.\n") ); + return STATUS_INVALID_PARAMETER; + } + + if( pIoStack->Parameters.DeviceIoControl.OutputBufferLength < + sizeof(IOCTL_IBAT_PORTS_OUT) ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Invalid output buffer size.\n") ); + return STATUS_INVALID_PARAMETER; + } + + pIn = (IOCTL_IBAT_PORTS_IN *) pIrp->AssociatedIrp.SystemBuffer; + pOut = (IOCTL_IBAT_PORTS_OUT *) pIrp->AssociatedIrp.SystemBuffer; + + if( pIn->Version != IBAT_IOCTL_VERSION ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Invalid version.\n") ); + return STATUS_INVALID_PARAMETER; + } + + KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl ); + nPorts = (LONG)cl_qlist_count( &g_ipoib.adapter_list ); + switch( nPorts ) + { + case 0: + cl_memclr( pOut->Ports, sizeof(pOut->Ports) ); + /* Fall through */ + case 1: + pOut->Size = sizeof(IOCTL_IBAT_PORTS_OUT); + break; + + default: + pOut->Size = sizeof(IOCTL_IBAT_PORTS_OUT) + + (sizeof(IBAT_PORT_RECORD) * (nPorts - 1)); + break; + } + + pIrp->IoStatus.Information = pOut->Size; + + if( pOut->Size > pIoStack->Parameters.DeviceIoControl.OutputBufferLength ) + { + nPorts = 1 + + (pIoStack->Parameters.DeviceIoControl.OutputBufferLength - + sizeof(IOCTL_IBAT_PORTS_OUT)) / sizeof(IBAT_PORT_RECORD); + + pIrp->IoStatus.Information = sizeof(IOCTL_IBAT_PORTS_OUT) + + ((nPorts - 1) * sizeof(IBAT_PORT_RECORD)); + } + + pOut->NumPorts = 0; + pItem = cl_qlist_head( &g_ipoib.adapter_list ); + while( pOut->NumPorts != nPorts ) + { + pAdapter = CONTAINING_RECORD( pItem, ipoib_adapter_t, entry ); + pOut->Ports[pOut->NumPorts].CaGuid = pAdapter->guids.ca_guid; + pOut->Ports[pOut->NumPorts].PortGuid = pAdapter->guids.port_guid.guid; + pOut->Ports[pOut->NumPorts].PKey = IB_DEFAULT_PKEY; + pOut->Ports[pOut->NumPorts].PortNum = pAdapter->guids.port_num; + pOut->NumPorts++; + + pItem = cl_qlist_next( pItem ); + } + + KeReleaseInStackQueuedSpinLock( &hdl ); + IPOIB_EXIT( IPOIB_DBG_IOCTL ); + return STATUS_SUCCESS; +} + + +static NTSTATUS +__ibat_get_ips( + IN IRP *pIrp, + IN IO_STACK_LOCATION *pIoStack ) +{ + IOCTL_IBAT_IP_ADDRESSES_IN *pIn; + IOCTL_IBAT_IP_ADDRESSES_OUT *pOut; + KLOCK_QUEUE_HANDLE hdl; + cl_list_item_t *pItem; + ipoib_adapter_t *pAdapter; + LONG nIps, maxIps; + size_t idx; + net_address_item_t *pAddr; + UINT64 PortGuid; + + IPOIB_ENTER(IPOIB_DBG_IOCTL); + + if( pIoStack->Parameters.DeviceIoControl.InputBufferLength != + sizeof(IOCTL_IBAT_IP_ADDRESSES_IN) ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Invalid input buffer size.\n") ); + return STATUS_INVALID_PARAMETER; + } + + if( pIoStack->Parameters.DeviceIoControl.OutputBufferLength < + sizeof(IOCTL_IBAT_IP_ADDRESSES_OUT) ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Invalid output buffer size.\n") ); + return STATUS_INVALID_PARAMETER; + } + + pIn = (IOCTL_IBAT_IP_ADDRESSES_IN *) pIrp->AssociatedIrp.SystemBuffer; + pOut = (IOCTL_IBAT_IP_ADDRESSES_OUT *) pIrp->AssociatedIrp.SystemBuffer; + + if( pIn->Version != IBAT_IOCTL_VERSION ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Invalid version.\n") ); + return STATUS_INVALID_PARAMETER; + } + + PortGuid = pIn->PortGuid; + + nIps = 0; + pOut->AddressCount = 0; + maxIps = 1 + + ((pIoStack->Parameters.DeviceIoControl.OutputBufferLength - + sizeof(IOCTL_IBAT_IP_ADDRESSES_OUT)) / sizeof(IP_ADDRESS)); + + KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl ); + for( pItem = cl_qlist_head( &g_ipoib.adapter_list ); + pItem != cl_qlist_end( &g_ipoib.adapter_list ); + pItem = cl_qlist_next( pItem ) ) + { + pAdapter = CONTAINING_RECORD( pItem, ipoib_adapter_t, entry ); + if( PortGuid && pAdapter->guids.port_guid.guid != PortGuid ) + continue; + + cl_obj_lock( &pAdapter->obj ); + nIps += (LONG)cl_vector_get_size( &pAdapter->ip_vector ); + + for( idx = 0; + idx < cl_vector_get_size( &pAdapter->ip_vector ); + idx++ ) + { + if( pOut->AddressCount == maxIps ) + break; + + pAddr = (net_address_item_t*) + cl_vector_get_ptr( &pAdapter->ip_vector, idx ); + + pOut->Address[pOut->AddressCount].IpVersion = 4; + cl_memclr( &pOut->Address[pOut->AddressCount].Address, + sizeof(IP_ADDRESS) ); + cl_memcpy( &pOut->Address[pOut->AddressCount].Address[12], + pAddr->address.as_bytes, IPV4_ADDR_SIZE ); + + pOut->AddressCount++; + } + cl_obj_unlock( &pAdapter->obj ); + } + + pOut->Size = sizeof(IOCTL_IBAT_IP_ADDRESSES_OUT); + if( --nIps ) + pOut->Size += sizeof(IP_ADDRESS) * nIps; + + pIrp->IoStatus.Information = sizeof(IOCTL_IBAT_IP_ADDRESSES_OUT); + if( --maxIps < nIps ) + pIrp->IoStatus.Information += (sizeof(IP_ADDRESS) * maxIps); + else + pIrp->IoStatus.Information += (sizeof(IP_ADDRESS) * nIps); + + KeReleaseInStackQueuedSpinLock( &hdl ); + IPOIB_EXIT( IPOIB_DBG_IOCTL ); + return STATUS_SUCCESS; +} + + +static NTSTATUS +__ibat_mac_to_gid( + IN IRP *pIrp, + IN IO_STACK_LOCATION *pIoStack ) +{ + NTSTATUS status = STATUS_INVALID_PARAMETER; + IOCTL_IBAT_MAC_TO_GID_IN *pIn; + IOCTL_IBAT_MAC_TO_GID_OUT *pOut; + KLOCK_QUEUE_HANDLE hdl; + cl_list_item_t *pItem; + ipoib_adapter_t *pAdapter; + + IPOIB_ENTER(IPOIB_DBG_IOCTL); + + if( pIoStack->Parameters.DeviceIoControl.InputBufferLength != + sizeof(IOCTL_IBAT_MAC_TO_GID_IN) ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Invalid input buffer size.\n") ); + return STATUS_INVALID_PARAMETER; + } + + if( pIoStack->Parameters.DeviceIoControl.OutputBufferLength != + sizeof(IOCTL_IBAT_MAC_TO_GID_OUT) ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Invalid output buffer size.\n") ); + return STATUS_INVALID_PARAMETER; + } + + pIn = (IOCTL_IBAT_MAC_TO_GID_IN *) pIrp->AssociatedIrp.SystemBuffer; + pOut = (IOCTL_IBAT_MAC_TO_GID_OUT *) pIrp->AssociatedIrp.SystemBuffer; + + if( pIn->Version != IBAT_IOCTL_VERSION ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Invalid version.\n") ); + return STATUS_INVALID_PARAMETER; + } + + KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl ); + + for( pItem = cl_qlist_head( &g_ipoib.adapter_list ); + pItem != cl_qlist_end( &g_ipoib.adapter_list ); + pItem = cl_qlist_next( pItem ) ) + { + pAdapter = CONTAINING_RECORD( pItem, ipoib_adapter_t, entry ); + if( pIn->PortGuid != pAdapter->guids.port_guid.guid ) + continue; + + /* Found the port - lookup the MAC. */ + cl_obj_lock( &pAdapter->obj ); + if( pAdapter->p_port ) + { + status = ipoib_mac_to_gid( + pAdapter->p_port, *(mac_addr_t*)pIn->DestMac, &pOut->DestGid ); + if( NT_SUCCESS( status ) ) + { + pIrp->IoStatus.Information = + sizeof(IOCTL_IBAT_MAC_TO_GID_OUT); + } + } + cl_obj_unlock( &pAdapter->obj ); + break; + } + + KeReleaseInStackQueuedSpinLock( &hdl ); + + IPOIB_EXIT( IPOIB_DBG_IOCTL ); + return status; +} + + +static NTSTATUS +__ibat_mac_to_path( + IN IRP *pIrp, + IN IO_STACK_LOCATION *pIoStack ) +{ + NTSTATUS status = STATUS_INVALID_PARAMETER; + IOCTL_IBAT_MAC_TO_PATH_IN *pIn; + IOCTL_IBAT_MAC_TO_PATH_OUT *pOut; + KLOCK_QUEUE_HANDLE hdl; + cl_list_item_t *pItem; + ipoib_adapter_t *pAdapter; + + IPOIB_ENTER(IPOIB_DBG_IOCTL); + + if( pIoStack->Parameters.DeviceIoControl.InputBufferLength != + sizeof(IOCTL_IBAT_MAC_TO_PATH_IN) ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Invalid input buffer size.\n") ); + return STATUS_INVALID_PARAMETER; + } + + if( pIoStack->Parameters.DeviceIoControl.OutputBufferLength != + sizeof(IOCTL_IBAT_MAC_TO_PATH_OUT) ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Invalid output buffer size.\n") ); + return STATUS_INVALID_PARAMETER; + } + + pIn = (IOCTL_IBAT_MAC_TO_PATH_IN *) pIrp->AssociatedIrp.SystemBuffer; + pOut = (IOCTL_IBAT_MAC_TO_PATH_OUT *) pIrp->AssociatedIrp.SystemBuffer; + + if( pIn->Version != IBAT_IOCTL_VERSION ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Invalid version.\n") ); + return STATUS_INVALID_PARAMETER; + } + + KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl ); + + for( pItem = cl_qlist_head( &g_ipoib.adapter_list ); + pItem != cl_qlist_end( &g_ipoib.adapter_list ); + pItem = cl_qlist_next( pItem ) ) + { + pAdapter = CONTAINING_RECORD( pItem, ipoib_adapter_t, entry ); + if( pIn->PortGuid != pAdapter->guids.port_guid.guid ) + continue; + + /* Found the port - lookup the MAC. */ + cl_obj_lock( &pAdapter->obj ); + if( pAdapter->p_port ) + { + status = ipoib_mac_to_path( + pAdapter->p_port, *(mac_addr_t*)pIn->DestMac, &pOut->Path ); + + if( NT_SUCCESS( status ) ) + { + pIrp->IoStatus.Information = + sizeof(IOCTL_IBAT_MAC_TO_PATH_OUT); + } + } + cl_obj_unlock( &pAdapter->obj ); + break; + } + + KeReleaseInStackQueuedSpinLock( &hdl ); + + IPOIB_EXIT( IPOIB_DBG_IOCTL ); + return status; +} + + +static NTSTATUS +__ibat_ip_to_port( + IN IRP *pIrp, + IN IO_STACK_LOCATION *pIoStack ) +{ + IOCTL_IBAT_IP_TO_PORT_IN *pIn; + IOCTL_IBAT_IP_TO_PORT_OUT *pOut; + KLOCK_QUEUE_HANDLE hdl; + cl_list_item_t *pItem; + ipoib_adapter_t *pAdapter; + size_t idx; + net_address_item_t *pAddr; + NTSTATUS status = STATUS_NOT_FOUND; + + IPOIB_ENTER(IPOIB_DBG_IOCTL); + + if( pIoStack->Parameters.DeviceIoControl.InputBufferLength != + sizeof(IOCTL_IBAT_IP_TO_PORT_IN) ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Invalid input buffer size.\n") ); + return STATUS_INVALID_PARAMETER; + } + + if( pIoStack->Parameters.DeviceIoControl.OutputBufferLength != + sizeof(IOCTL_IBAT_IP_TO_PORT_OUT) ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Invalid output buffer size.\n") ); + return STATUS_INVALID_PARAMETER; + } + + pIn = (IOCTL_IBAT_IP_TO_PORT_IN *) pIrp->AssociatedIrp.SystemBuffer; + pOut = (IOCTL_IBAT_IP_TO_PORT_OUT *) pIrp->AssociatedIrp.SystemBuffer; + + if( pIn->Version != IBAT_IOCTL_VERSION ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Invalid version.\n") ); + return STATUS_INVALID_PARAMETER; + } + + if (pIn->Address.IpVersion != 4) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Invalid IP version (%d). Supported only 4\n", pIn->Address.IpVersion) ); + return STATUS_INVALID_PARAMETER; + } + + KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl ); + for( pItem = cl_qlist_head( &g_ipoib.adapter_list ); + pItem != cl_qlist_end( &g_ipoib.adapter_list ); + pItem = cl_qlist_next( pItem ) ) + { + pAdapter = CONTAINING_RECORD( pItem, ipoib_adapter_t, entry ); + + cl_obj_lock( &pAdapter->obj ); + + for( idx = 0; + idx < cl_vector_get_size( &pAdapter->ip_vector ); + idx++ ) + { + pAddr = (net_address_item_t*) + cl_vector_get_ptr( &pAdapter->ip_vector, idx ); + + if (!memcmp( &pIn->Address.Address[12], pAddr->address.as_bytes, IPV4_ADDR_SIZE)) + { + pOut->Port.CaGuid = pAdapter->guids.ca_guid; + pOut->Port.PortGuid = pAdapter->guids.port_guid.guid; + pOut->Port.PKey = IB_DEFAULT_PKEY; + pOut->Port.PortNum = pAdapter->guids.port_num; + pIrp->IoStatus.Information = sizeof(IOCTL_IBAT_IP_TO_PORT_OUT); + status = STATUS_SUCCESS; + break; + } + } + cl_obj_unlock( &pAdapter->obj ); + if (status == STATUS_SUCCESS) + break; + } + + KeReleaseInStackQueuedSpinLock( &hdl ); + IPOIB_EXIT( IPOIB_DBG_IOCTL ); + return status; +} + +void +ipoib_ref_ibat() +{ + UNICODE_STRING DeviceName; + UNICODE_STRING DeviceLinkUnicodeString; + NDIS_DEVICE_OBJECT_ATTRIBUTES DeviceObjectAttributes; + PDRIVER_DISPATCH DispatchTable[IRP_MJ_MAXIMUM_FUNCTION+1]; + + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + + IPOIB_ENTER( IPOIB_DBG_IOCTL ); + + if( InterlockedIncrement( &g_ipoib.ibat_ref ) == 1 ) + { + + NdisZeroMemory(DispatchTable, (IRP_MJ_MAXIMUM_FUNCTION+1) * sizeof(PDRIVER_DISPATCH)); + + DispatchTable[IRP_MJ_CREATE] = __ipoib_create; + DispatchTable[IRP_MJ_CLEANUP] = __ipoib_cleanup; + DispatchTable[IRP_MJ_CLOSE] = __ipoib_close; + DispatchTable[IRP_MJ_DEVICE_CONTROL] = __ipoib_dispatch; + DispatchTable[IRP_MJ_INTERNAL_DEVICE_CONTROL] = __ipoib_dispatch; + + + NdisInitUnicodeString( &DeviceName, IBAT_DEV_NAME ); + NdisInitUnicodeString( &DeviceLinkUnicodeString, IBAT_DOS_DEV_NAME ); + + + NdisZeroMemory(&DeviceObjectAttributes, sizeof(NDIS_DEVICE_OBJECT_ATTRIBUTES)); + + DeviceObjectAttributes.Header.Type = NDIS_OBJECT_TYPE_DEFAULT; // type implicit from the context + DeviceObjectAttributes.Header.Revision = NDIS_DEVICE_OBJECT_ATTRIBUTES_REVISION_1; + DeviceObjectAttributes.Header.Size = sizeof(NDIS_DEVICE_OBJECT_ATTRIBUTES); + DeviceObjectAttributes.DeviceName = &DeviceName; + DeviceObjectAttributes.SymbolicName = &DeviceLinkUnicodeString; + DeviceObjectAttributes.MajorFunctions = &DispatchTable[0]; + DeviceObjectAttributes.ExtensionSize = 0; + DeviceObjectAttributes.DefaultSDDLString = NULL; + DeviceObjectAttributes.DeviceClassGuid = 0; + + Status = NdisRegisterDeviceEx( + g_IpoibMiniportDriverHandle, + &DeviceObjectAttributes, + &g_ipoib.h_ibat_dev, + &g_ipoib.h_ibat_dev_handle); + + + + if( Status != NDIS_STATUS_SUCCESS ) + { + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("NdisRegisterDeviceEx failed with status of %d\n", Status) ); + } + } + + IPOIB_EXIT( IPOIB_DBG_IOCTL ); +} + + +void +ipoib_deref_ibat() +{ + IPOIB_ENTER( IPOIB_DBG_IOCTL ); + + if( InterlockedDecrement( &g_ipoib.ibat_ref ) ) + { + IPOIB_EXIT( IPOIB_DBG_IOCTL ); + return; + } + + if( g_ipoib.h_ibat_dev ) + { + NdisDeregisterDeviceEx( g_ipoib.h_ibat_dev_handle ); + g_ipoib.h_ibat_dev = NULL; + g_ipoib.h_ibat_dev_handle = NULL; //TODO set here INVALID_HANDLE_VALUE + } + + IPOIB_EXIT( IPOIB_DBG_IOCTL ); +} + + +static NTSTATUS +__ipoib_create( + IN DEVICE_OBJECT* const pDevObj, + IN IRP* const pIrp ) +{ + IPOIB_ENTER( IPOIB_DBG_IOCTL ); + + UNREFERENCED_PARAMETER( pDevObj ); + + ipoib_ref_ibat(); + + pIrp->IoStatus.Status = STATUS_SUCCESS; + pIrp->IoStatus.Information = 0; + IoCompleteRequest( pIrp, IO_NO_INCREMENT ); + + IPOIB_EXIT( IPOIB_DBG_IOCTL ); + return STATUS_SUCCESS; +} + + +static NTSTATUS +__ipoib_cleanup( + IN DEVICE_OBJECT* const pDevObj, + IN IRP* const pIrp ) +{ + IPOIB_ENTER( IPOIB_DBG_IOCTL ); + + UNREFERENCED_PARAMETER( pDevObj ); + + ipoib_deref_ibat(); + + pIrp->IoStatus.Status = STATUS_SUCCESS; + pIrp->IoStatus.Information = 0; + IoCompleteRequest( pIrp, IO_NO_INCREMENT ); + + IPOIB_EXIT( IPOIB_DBG_IOCTL ); + return STATUS_SUCCESS; +} + + +static NTSTATUS +__ipoib_close( + IN DEVICE_OBJECT* const pDevObj, + IN IRP* const pIrp ) +{ + IPOIB_ENTER( IPOIB_DBG_IOCTL ); + + UNREFERENCED_PARAMETER( pDevObj ); + + pIrp->IoStatus.Status = STATUS_SUCCESS; + pIrp->IoStatus.Information = 0; + IoCompleteRequest( pIrp, IO_NO_INCREMENT ); + + IPOIB_EXIT( IPOIB_DBG_IOCTL ); + return STATUS_SUCCESS; +} + + +static NTSTATUS +__ipoib_dispatch( + IN DEVICE_OBJECT* const pDevObj, + IN IRP* const pIrp ) +{ + IO_STACK_LOCATION *pIoStack; + NTSTATUS status = STATUS_SUCCESS; + + IPOIB_ENTER( IPOIB_DBG_IOCTL ); + + UNREFERENCED_PARAMETER( pDevObj ); + + pIoStack = IoGetCurrentIrpStackLocation( pIrp ); + + pIrp->IoStatus.Information = 0; + + switch( pIoStack->Parameters.DeviceIoControl.IoControlCode ) + { + case IOCTL_IBAT_PORTS: + IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_IOCTL, + ("IOCTL_IBAT_PORTS received\n") ); + status = __ibat_get_ports( pIrp, pIoStack ); + break; + + case IOCTL_IBAT_IP_ADDRESSES: + IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_IOCTL, + ("IOCTL_IBAT_IP_ADDRESSES received\n" )); + status = __ibat_get_ips( pIrp, pIoStack ); + break; + + case IOCTL_IBAT_MAC_TO_GID: + IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_IOCTL, + ("IOCTL_IBAT_MAC_TO_GID received\n" )); + status = __ibat_mac_to_gid( pIrp, pIoStack ); + break; + + case IOCTL_IBAT_IP_TO_PORT: + IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_IOCTL, + ("IOCTL_IBAT_IP_TO_PORT received\n" )); + status = __ibat_ip_to_port( pIrp, pIoStack ); + break; + + case IOCTL_IBAT_MAC_TO_PATH: + IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_IOCTL, + ("IOCTL_IBAT_MAC_TO_PATH received\n" )); + status = __ibat_mac_to_path( pIrp, pIoStack ); + break; + + default: + IPOIB_PRINT( TRACE_LEVEL_VERBOSE, IPOIB_DBG_IOCTL, + ("unknow IOCTL code = 0x%x\n", + pIoStack->Parameters.DeviceIoControl.IoControlCode) ); + status = STATUS_INVALID_PARAMETER; + } + + pIrp->IoStatus.Status = status; + IoCompleteRequest( pIrp, IO_NO_INCREMENT ); + + IPOIB_EXIT( IPOIB_DBG_IOCTL ); + return status; +} + + diff --git a/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_port.c b/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_port.c deleted file mode 100644 index 89e1a0c0..00000000 --- a/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_port.c +++ /dev/null @@ -1,8123 +0,0 @@ -/* - * Copyright (c) 2005 SilverStorm Technologies. All rights reserved. - * Copyright (c) 2006 Mellanox Technologies. All rights reserved. - * Portions Copyright (c) 2008 Microsoft 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: ipoib_port.c 4506 2009-06-23 14:40:54Z xalex $ - */ - - - -#include "ipoib_endpoint.h" -#include "ipoib_port.h" -#include "ipoib_adapter.h" -#include "ipoib_debug.h" -#if defined(EVENT_TRACING) -#ifdef offsetof -#undef offsetof -#endif -#include "ipoib_port.tmh" -#endif -#include - -#include "wdm.h" -#include - - - -ib_gid_t bcast_mgid_template = { - 0xff, /* multicast field */ - 0x12, /* scope (to be filled in) */ - 0x40, 0x1b, /* IPv4 signature */ - 0xff, 0xff, /* 16 bits of P_Key (to be filled in) */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 48 bits of zeros */ - 0xff, 0xff, 0xff, 0xff, /* 32 bit IPv4 broadcast address */ -}; - - -#ifdef _DEBUG_ -/* Handy pointer for debug use. */ -ipoib_port_t *gp_ipoib_port; -#endif - -static void __port_mcast_garbage_dpc(KDPC *p_gc_dpc,void *context,void *s_arg1, void *s_arg2); -static void __port_do_mcast_garbage(ipoib_port_t* const p_port ); - - -static void __recv_cb_dpc(KDPC *p_gc_dpc,void *context,void *s_arg1, void *s_arg2); - - -/****************************************************************************** -* -* Declarations -* -******************************************************************************/ -static void -__port_construct( - IN ipoib_port_t* const p_port ); - -static ib_api_status_t -__port_init( - IN ipoib_port_t* const p_port, - IN ipoib_adapter_t* const p_adapter, - IN ib_pnp_port_rec_t* const p_pnp_rec ); - -static void -__port_destroying( - IN cl_obj_t* const p_obj ); - -static void -__port_cleanup( - IN cl_obj_t* const p_obj ); - -static void -__port_free( - IN cl_obj_t* const p_obj ); - -static ib_api_status_t -__port_query_ca_attrs( - IN ipoib_port_t* const p_port, - IN ib_ca_attr_t** pp_ca_attrs ); - -static void -__srq_async_event_cb( -IN ib_async_event_rec_t *p_event_rec ); - -/****************************************************************************** -* -* IB resource manager operations -* -******************************************************************************/ -static void -__ib_mgr_construct( - IN ipoib_port_t* const p_port ); - -static ib_api_status_t -__ib_mgr_init( - IN ipoib_port_t* const p_port ); - -static void -__ib_mgr_destroy( - IN ipoib_port_t* const p_port ); - -static void -__qp_event( - IN ib_async_event_rec_t *p_event_rec ); - -static void -__cq_event( - IN ib_async_event_rec_t *p_event_rec ); - -static ib_api_status_t -__ib_mgr_activate( - IN ipoib_port_t* const p_port ); - -/****************************************************************************** -* -* Buffer manager operations. -* -******************************************************************************/ -static void -__buf_mgr_construct( - IN ipoib_port_t* const p_port ); - -static ib_api_status_t -__buf_mgr_init( - IN ipoib_port_t* const p_port ); - -static void -__buf_mgr_destroy( - IN ipoib_port_t* const p_port ); - -static cl_status_t -__recv_ctor( - IN void* const p_object, - IN void* context, - OUT cl_pool_item_t** const pp_pool_item ); - -#if !IPOIB_INLINE_RECV -static void -__recv_dtor( - IN const cl_pool_item_t* const p_pool_item, - IN void *context ); -#endif /* IPOIB_INLINE_RECV */ - -static inline ipoib_send_desc_t* -__buf_mgr_get_send( - IN ipoib_port_t* const p_port ); - -static inline void -__buf_mgr_put_send( - IN ipoib_port_t* const p_port, - IN ipoib_send_desc_t* const p_desc ); - -static inline ipoib_recv_desc_t* -__buf_mgr_get_recv( - IN ipoib_port_t* const p_port ); - -static inline void -__buf_mgr_put_recv( - IN ipoib_port_t* const p_port, - IN ipoib_recv_desc_t* const p_desc, - IN NET_BUFFER_LIST* const p_net_buffer_list OPTIONAL ); - -static inline void -__buf_mgr_put_recv_list( - IN ipoib_port_t* const p_port, - IN cl_qlist_t* const p_list ); - -//NDIS60 -static inline NET_BUFFER_LIST* -__buf_mgr_get_ndis_pkt( - IN ipoib_port_t* const p_port, - IN ipoib_recv_desc_t* const p_desc ); - - -/****************************************************************************** -* -* Receive manager operations. -* -******************************************************************************/ -static void -__recv_mgr_construct( - IN ipoib_port_t* const p_port ); - -static ib_api_status_t -__recv_mgr_init( - IN ipoib_port_t* const p_port ); - -static void -__recv_mgr_destroy( - IN ipoib_port_t* const p_port ); - -/* Posts receive buffers to the receive queue. */ -static ib_api_status_t -__recv_mgr_repost( - IN ipoib_port_t* const p_port ); - -static void -__recv_cb( - IN const ib_cq_handle_t h_cq, - IN void *cq_context ); - -static void -__recv_get_endpts( - IN ipoib_port_t* const p_port, - IN ipoib_recv_desc_t* const p_desc, - IN ib_wc_t* const p_wc, - OUT ipoib_endpt_t** const pp_src, - OUT ipoib_endpt_t** const pp_dst ); - -static int32_t -__recv_mgr_filter( - IN ipoib_port_t* const p_port, - IN ib_wc_t* const p_done_wc_list, - OUT cl_qlist_t* const p_done_list, - OUT cl_qlist_t* const p_bad_list ); - -static ib_api_status_t -__recv_gen( - IN const ipoib_pkt_t* const p_ipoib, - OUT eth_pkt_t* const p_eth, - IN ipoib_endpt_t* const p_src, - IN ipoib_endpt_t* const p_dst ); - -static ib_api_status_t -__recv_dhcp( - IN ipoib_port_t* const p_port, - IN const ipoib_pkt_t* const p_ipoib, - OUT eth_pkt_t* const p_eth, - IN ipoib_endpt_t* const p_src, - IN ipoib_endpt_t* const p_dst ); - -static ib_api_status_t -__recv_arp( - IN ipoib_port_t* const p_port, - IN ib_wc_t* const p_wc, - IN const ipoib_pkt_t* const p_ipoib, - OUT eth_pkt_t* const p_eth, - IN ipoib_endpt_t** const p_src, - IN ipoib_endpt_t* const p_dst ); - -static ib_api_status_t -__recv_mgr_prepare_pkt( - IN ipoib_port_t* const p_port, - IN ipoib_recv_desc_t* const p_desc, - OUT NET_BUFFER_LIST** const pp_net_buffer_list ); - -static uint32_t -__recv_mgr_build_pkt_array( - IN ipoib_port_t* const p_port, - IN int32_t shortage, - OUT cl_qlist_t* const p_done_list, - OUT int32_t* const p_discarded ); - -/****************************************************************************** -* -* Send manager operations. -* -******************************************************************************/ -static void -__send_mgr_construct( - IN ipoib_port_t* const p_port ); - -static void -__send_mgr_destroy( - IN ipoib_port_t* const p_port ); - -static NDIS_STATUS -__send_gen( - IN ipoib_port_t* const p_port, - IN ipoib_send_desc_t* const p_desc, - IN SCATTER_GATHER_LIST *p_sgl, - IN INT lso_data_index); - -static NDIS_STATUS -__send_mgr_filter_ip( - IN ipoib_port_t* const p_port, - IN const eth_hdr_t* const p_eth_hdr, - IN MDL* p_mdl, - IN size_t buf_len, - IN SCATTER_GATHER_LIST *p_sgl, - IN OUT ipoib_send_desc_t* const p_desc ); - -static NDIS_STATUS -__send_mgr_filter_igmp_v2( - IN ipoib_port_t* const p_port, - IN const ip_hdr_t* const p_ip_hdr, - IN size_t iph_options_size, - IN MDL* p_mdl, - IN size_t buf_len ); - -static NDIS_STATUS -__send_mgr_filter_udp( - IN ipoib_port_t* const p_port, - IN const ip_hdr_t* const p_ip_hdr, - IN MDL* p_mdl, - IN size_t buf_len, - IN SCATTER_GATHER_LIST *p_sgl, - IN OUT ipoib_send_desc_t* const p_desc ); - -static NDIS_STATUS -__send_mgr_filter_dhcp( - IN ipoib_port_t* const p_port, - IN const udp_hdr_t* const p_udp_hdr, - IN MDL* p_mdl, - IN size_t buf_len, - IN OUT ipoib_send_desc_t* const p_desc ); - -static NDIS_STATUS -__send_mgr_filter_arp( - IN ipoib_port_t* const p_port, - IN const eth_hdr_t* const p_eth_hdr, - IN MDL* p_mdl, - IN size_t buf_len, - IN OUT ipoib_send_desc_t* const p_desc ); - -static void -__process_failed_send( - IN ipoib_port_t* const p_port, - IN ipoib_send_desc_t* const p_desc, - IN const NDIS_STATUS status, - IN ULONG send_complete_flags ); - -static inline NDIS_STATUS -__send_mgr_queue( - IN ipoib_port_t* const p_port, - IN eth_hdr_t* const p_eth_hdr, - OUT ipoib_endpt_t** const pp_endpt ); - -static NDIS_STATUS -__build_send_desc( - IN ipoib_port_t* const p_port, - IN eth_hdr_t* const p_eth_hdr, - IN MDL* const p_mdl, - IN const size_t mdl_len, - IN SCATTER_GATHER_LIST *p_sgl, - IN OUT ipoib_send_desc_t* const p_desc ); - - -static void -__send_cb( - IN const ib_cq_handle_t h_cq, - IN void *cq_context ); - -static NDIS_STATUS -GetLsoHeaderSize( - IN PNET_BUFFER pNetBuffer, - IN LsoData *pLsoData, - OUT UINT *IndexOfData, - IN ipoib_hdr_t *ipoib_hdr ); - - -static NDIS_STATUS -__build_lso_desc( - IN ipoib_port_t* const p_port, - IN OUT ipoib_send_desc_t* const p_desc, - IN ULONG mss, - IN SCATTER_GATHER_LIST *p_sgl, - IN int32_t hdr_idx, - IN PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO p_lso_info ); - -static NDIS_STATUS -__send_fragments( - IN ipoib_port_t* const p_port, - IN ipoib_send_desc_t* const p_desc, - IN eth_hdr_t* const p_eth_hdr, - IN ip_hdr_t* const p_ip_hdr, - IN uint32_t buf_len, - IN NDIS_BUFFER* p_ndis_buf ); - -static void -__update_fragment_ip_hdr( -IN ip_hdr_t* const p_ip_hdr, -IN uint16_t fragment_size, -IN uint16_t fragment_offset, -IN BOOLEAN more_fragments ); - -static void -__copy_ip_options( -IN uint8_t* p_buf, -IN uint8_t* p_options, -IN uint32_t options_len, -IN BOOLEAN copy_all ); -/****************************************************************************** -* -* Endpoint manager operations -* -******************************************************************************/ -static void -__endpt_mgr_construct( - IN ipoib_port_t* const p_port ); - -static ib_api_status_t -__endpt_mgr_init( - IN ipoib_port_t* const p_port ); - -static void -__endpt_mgr_destroy( - IN ipoib_port_t* const p_port ); - -/****f* IPoIB/__endpt_mgr_remove_all -* NAME -* __endpt_mgr_remove_all -* -* DESCRIPTION -* Removes all enpoints from the port, dereferencing them to initiate -* destruction. -* -* SYNOPSIS -*/ -static void -__endpt_mgr_remove_all( - IN ipoib_port_t* const p_port ); -/* -********/ - -static void -__endpt_mgr_remove( - IN ipoib_port_t* const p_port, - IN ipoib_endpt_t* const p_endpt ); - -static void -__endpt_mgr_reset_all( - IN ipoib_port_t* const p_port ); - -static inline NDIS_STATUS -__endpt_mgr_ref( - IN ipoib_port_t* const p_port, - IN const mac_addr_t mac, - OUT ipoib_endpt_t** const pp_endpt ); - -static inline NDIS_STATUS -__endpt_mgr_get_gid_qpn( - IN ipoib_port_t* const p_port, - IN const mac_addr_t mac, - OUT ib_gid_t* const p_gid, - OUT UNALIGNED net32_t* const p_qpn ); - -static inline ipoib_endpt_t* -__endpt_mgr_get_by_gid( - IN ipoib_port_t* const p_port, - IN const ib_gid_t* const p_gid ); - -static inline ipoib_endpt_t* -__endpt_mgr_get_by_lid( - IN ipoib_port_t* const p_port, - IN const net16_t lid ); - -static inline ib_api_status_t -__endpt_mgr_insert_locked( - IN ipoib_port_t* const p_port, - IN const mac_addr_t mac, - IN ipoib_endpt_t* const p_endpt ); - -static inline ib_api_status_t -__endpt_mgr_insert( - IN ipoib_port_t* const p_port, - IN const mac_addr_t mac, - IN ipoib_endpt_t* const p_endpt ); - -static ib_api_status_t -__endpt_mgr_add_local( - IN ipoib_port_t* const p_port, - IN ib_port_info_t* const p_port_info ); - -static ib_api_status_t -__endpt_mgr_add_bcast( - IN ipoib_port_t* const p_port, - IN ib_mcast_rec_t *p_mcast_rec ); - -/****************************************************************************** -* -* MCast operations. -* -******************************************************************************/ -static ib_api_status_t -__port_get_bcast( - IN ipoib_port_t* const p_port ); - -static ib_api_status_t -__port_join_bcast( - IN ipoib_port_t* const p_port, - IN ib_member_rec_t* const p_member_rec ); - -static ib_api_status_t -__port_create_bcast( - IN ipoib_port_t* const p_port ); - - - -static void -__bcast_get_cb( - IN ib_query_rec_t *p_query_rec ); - - -static void -__bcast_cb( - IN ib_mcast_rec_t *p_mcast_rec ); - - -static void -__mcast_cb( - IN ib_mcast_rec_t *p_mcast_rec ); - -void -__leave_error_mcast_cb( - IN void *context ); - - -static intn_t -__gid_cmp( - IN const void* const p_key1, - IN const void* const p_key2 ) -{ - return cl_memcmp( p_key1, p_key2, sizeof(ib_gid_t) ); -} - - -inline void ipoib_port_ref( ipoib_port_t * p_port, int type ) -{ - cl_obj_ref( &p_port->obj ); -#if DBG - cl_atomic_inc( &p_port->ref[type % ref_mask] ); - if ((p_port->obj.ref_cnt % 20)==0) - IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OBJ, - ("ref type %d ref_cnt %d\n", type, p_port->obj.ref_cnt) ); - //TODO remove - //ASSERT (p_port->obj.ref_cnt < 100); -#else - UNREFERENCED_PARAMETER(type); -#endif -} - - -inline void ipoib_port_deref(ipoib_port_t * p_port, int type) -{ -#if DBG - cl_atomic_dec( &p_port->ref[type % ref_mask] ); - if ((p_port->obj.ref_cnt % 20) == 0) - IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OBJ, - ("deref type %d ref_cnt %d\n", type, p_port->obj.ref_cnt) ); -#else - UNREFERENCED_PARAMETER(type); -#endif - cl_obj_deref( &p_port->obj ); - -} - -/* function returns pointer to payload that is going after IP header. -* asssuming that payload and IP header are in the same buffer -*/ -static void* GetIpPayloadPtr(const ip_hdr_t* const p_ip_hdr) -{ - return (void*)((uint8_t*)p_ip_hdr + IP_HEADER_LENGTH(p_ip_hdr)); -} - -/****************************************************************************** -* -* Implementation -* -******************************************************************************/ -ib_api_status_t -ipoib_create_port( - IN ipoib_adapter_t* const p_adapter, - IN ib_pnp_port_rec_t* const p_pnp_rec, - OUT ipoib_port_t** const pp_port ) -{ - ib_api_status_t status; - ipoib_port_t *p_port; - - IPOIB_ENTER( IPOIB_DBG_INIT ); - - CL_ASSERT( !p_adapter->p_port ); - - p_port = cl_zalloc( sizeof(ipoib_port_t) + - (sizeof(ipoib_hdr_t) * (p_adapter->params.sq_depth - 1)) ); - if( !p_port ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed to allocate ipoib_port_t (%d bytes)\n", - sizeof(ipoib_port_t)) ); - return IB_INSUFFICIENT_MEMORY; - } - -#ifdef _DEBUG_ - gp_ipoib_port = p_port; -#endif - - __port_construct( p_port ); - - status = __port_init( p_port, p_adapter, p_pnp_rec ); - if( status != IB_SUCCESS ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ipoib_port_init returned %s.\n", - p_adapter->p_ifc->get_err_str( status )) ); - __port_cleanup( &p_port->obj ); - __port_free( &p_port->obj ); - return status; - } - - *pp_port = p_port; - IPOIB_EXIT( IPOIB_DBG_INIT ); - return IB_SUCCESS; -} - - -void -ipoib_port_destroy( - IN ipoib_port_t* const p_port ) -{ - IPOIB_ENTER( IPOIB_DBG_INIT ); - - CL_ASSERT( p_port ); - CL_ASSERT( p_port->p_adapter ); - CL_ASSERT( !p_port->p_adapter->p_port ); - - cl_obj_destroy( &p_port->obj ); - - IPOIB_EXIT( IPOIB_DBG_INIT ); -} - - -static void -__port_construct( - IN ipoib_port_t* const p_port ) -{ - IPOIB_ENTER( IPOIB_DBG_INIT ); - - p_port->state = IB_QPS_RESET; - - cl_obj_construct( &p_port->obj, IPOIB_OBJ_PORT ); - cl_spinlock_construct( &p_port->send_lock ); - cl_spinlock_construct( &p_port->recv_lock ); - __ib_mgr_construct( p_port ); - __buf_mgr_construct( p_port ); - - __recv_mgr_construct( p_port ); - __send_mgr_construct( p_port ); - - __endpt_mgr_construct( p_port ); - - KeInitializeEvent( &p_port->sa_event, NotificationEvent, TRUE ); - KeInitializeEvent( &p_port->leave_mcast_event, NotificationEvent, TRUE ); - - IPOIB_EXIT( IPOIB_DBG_INIT ); -} - - -static ib_api_status_t -__port_init( - IN ipoib_port_t* const p_port, - IN ipoib_adapter_t* const p_adapter, - IN ib_pnp_port_rec_t* const p_pnp_rec ) -{ - cl_status_t cl_status; - ib_api_status_t status; - - IPOIB_ENTER( IPOIB_DBG_INIT ); - - p_port->port_num = p_pnp_rec->p_port_attr->port_num; - p_port->p_adapter = p_adapter; - - cl_status = cl_spinlock_init( &p_port->send_lock ); - if( cl_status != CL_SUCCESS ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("cl_spinlock_init returned %#x\n", cl_status) ); - return IB_ERROR; - } - - cl_status = cl_spinlock_init( &p_port->recv_lock ); - if( cl_status != CL_SUCCESS ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("cl_spinlock_init returned %#x\n", cl_status) ); - return IB_ERROR; - } - - /* Initialize the IB resource manager. */ - status = __ib_mgr_init( p_port ); - if( status != IB_SUCCESS ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("__ib_mgr_init returned %s\n", - p_adapter->p_ifc->get_err_str( status )) ); - return status; - } - - /* Initialize the buffer manager. */ - status = __buf_mgr_init( p_port ); - if( status != IB_SUCCESS ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("__buf_mgr_init returned %s\n", - p_adapter->p_ifc->get_err_str( status )) ); - return status; - } - - /* Initialize the receive manager. */ - status = __recv_mgr_init( p_port ); - if( status != IB_SUCCESS ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("__recv_mgr_init returned %s\n", - p_adapter->p_ifc->get_err_str( status )) ); - return status; - } - - /* Initialize the endpoint manager. */ - status = __endpt_mgr_init( p_port ); - if( status != IB_SUCCESS ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("__endpt_mgr_init returned %s\n", - p_adapter->p_ifc->get_err_str( status )) ); - return status; - } - - KeInitializeDpc(&p_port->recv_dpc,(PKDEFERRED_ROUTINE)__recv_cb_dpc,p_port); - - - /* Initialize multicast garbage collector timer and DPC object */ - KeInitializeDpc(&p_port->gc_dpc,(PKDEFERRED_ROUTINE)__port_mcast_garbage_dpc,p_port); - KeInitializeTimerEx(&p_port->gc_timer,SynchronizationTimer); - - /* We only ever destroy from the PnP callback thread. */ - cl_status = cl_obj_init( &p_port->obj, CL_DESTROY_SYNC, - __port_destroying, __port_cleanup, __port_free ); - -#if DBG - cl_atomic_inc( &p_port->ref[ref_init] ); - IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OBJ, - ("ref type %d ref_cnt %d\n", ref_init, p_port->obj.ref_cnt) ); -#endif - - if( cl_status != CL_SUCCESS ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("cl_obj_init returned %#x\n", cl_status) ); - return IB_ERROR; - } - - cl_status = cl_obj_insert_rel( &p_port->rel, &p_adapter->obj, &p_port->obj ); - if( cl_status != CL_SUCCESS ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("cl_obj_insert_rel returned %#x\n", cl_status) ); - cl_obj_destroy( &p_port->obj ); - return IB_ERROR; - } - -#if DBG - cl_atomic_inc( &p_port->ref[ref_init] ); - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_OBJ, - ("ref type %d ref_cnt %d\n", ref_init, p_port->obj.ref_cnt) ); -#endif - - IPOIB_EXIT( IPOIB_DBG_INIT ); - return IB_SUCCESS; -} - - -static void -__port_destroying( - IN cl_obj_t* const p_obj ) -{ - ipoib_port_t *p_port; - - IPOIB_ENTER( IPOIB_DBG_INIT ); - - CL_ASSERT( p_obj ); - - p_port = PARENT_STRUCT( p_obj, ipoib_port_t, obj ); - - ipoib_port_down( p_port ); - - __endpt_mgr_remove_all( p_port ); - -#if 0 - if( p_port->p_adapter->params.cm_enabled ) - { - endpt_cm_buf_mgr_destroy( p_port ); - ipoib_port_srq_destroy( p_port ); - p_port->endpt_mgr.thread_is_done = 1; - cl_event_signal( &p_port->endpt_mgr.event ); - } -#endif - ASSERT(FALSE); - //TODO NDIS6.0 - ipoib_port_resume( p_port, FALSE ); - - IPOIB_EXIT( IPOIB_DBG_INIT ); -} - - -static void -__port_cleanup( - IN cl_obj_t* const p_obj ) -{ - ipoib_port_t *p_port; - - IPOIB_ENTER( IPOIB_DBG_INIT ); - - CL_ASSERT( p_obj ); - - p_port = PARENT_STRUCT( p_obj, ipoib_port_t, obj ); - - /* Wait for all sends and receives to get flushed. */ - while( p_port->send_mgr.depth || p_port->recv_mgr.depth ) - cl_thread_suspend( 0 ); - - /* Destroy the send and receive managers before closing the CA. */ - __ib_mgr_destroy( p_port ); - - IPOIB_EXIT( IPOIB_DBG_INIT ); -} - - -static void -__port_free( - IN cl_obj_t* const p_obj ) -{ - ipoib_port_t *p_port; - - IPOIB_ENTER( IPOIB_DBG_INIT ); - - CL_ASSERT( p_obj ); - - p_port = PARENT_STRUCT( p_obj, ipoib_port_t, obj ); - - KeCancelTimer(&p_port->gc_timer); - KeFlushQueuedDpcs(); - __endpt_mgr_destroy( p_port ); - __recv_mgr_destroy( p_port ); - __send_mgr_destroy( p_port ); - __buf_mgr_destroy( p_port ); - - cl_spinlock_destroy( &p_port->send_lock ); - cl_spinlock_destroy( &p_port->recv_lock ); - - cl_obj_deinit( p_obj ); - if( p_port->p_ca_attrs ) - { - cl_free ( p_port->p_ca_attrs ); - } - cl_free( p_port ); - - IPOIB_EXIT( IPOIB_DBG_INIT ); -} - - - -/****************************************************************************** -* -* IB resource manager implementation. -* -******************************************************************************/ -static void -__ib_mgr_construct( - IN ipoib_port_t* const p_port ) -{ - IPOIB_ENTER( IPOIB_DBG_INIT ); - - cl_memclr( &p_port->ib_mgr, sizeof(ipoib_ib_mgr_t) ); - - IPOIB_EXIT( IPOIB_DBG_INIT ); -} - - -static ib_api_status_t -__ib_mgr_init( - IN ipoib_port_t* const p_port ) -{ - ib_api_status_t status; - ib_cq_create_t cq_create; - ib_qp_create_t qp_create; - ib_phys_create_t phys_create; - ib_phys_range_t phys_range; - uint64_t vaddr; - net32_t rkey; - ib_qp_attr_t qp_attr; - - IPOIB_ENTER( IPOIB_DBG_INIT ); - - /* Open the CA. */ - status = p_port->p_adapter->p_ifc->open_ca( - p_port->p_adapter->h_al, p_port->p_adapter->guids.ca_guid, - NULL, p_port, &p_port->ib_mgr.h_ca ); - if( status != IB_SUCCESS ) - { - NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, - EVENT_IPOIB_OPEN_CA, 1, status ); - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ib_open_ca returned %s\n", - p_port->p_adapter->p_ifc->get_err_str( status )) ); - return status; - } - - status = __port_query_ca_attrs( p_port, &p_port->p_ca_attrs ); - if( status != IB_SUCCESS ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Query CA attributes failed\n" ) ); - return status; - } -#if 0 - if( p_port->p_adapter->params.cm_enabled ) - { - uint32_t payload_mtu = __port_attr_to_mtu_size( - p_port->p_ca_attrs->p_port_attr[p_port->port_num - 1].mtu ) - - sizeof(ipoib_hdr_t); - /* adjust ipoib UD payload MTU to actual port MTU size. */ - p_port->p_adapter->params.payload_mtu = - max( DEFAULT_PAYLOAD_MTU, payload_mtu ); - p_port->p_adapter->params.xfer_block_size = - (sizeof(eth_hdr_t) + p_port->p_adapter->params.payload_mtu); - } -#endif -#if IPOIB_USE_DMA - /* init DMA only once while running MiniportInitialize */ - if ( !p_port->p_adapter->reset ) - { - ULONG max_phys_mapping; - if( p_port->p_adapter->params.cm_enabled ) - { - max_phys_mapping = p_port->p_adapter->params.cm_xfer_block_size; - } - else if( p_port->p_adapter->params.lso ) - { - max_phys_mapping = LARGE_SEND_OFFLOAD_SIZE; - } - else - { - max_phys_mapping = p_port->p_adapter->params.xfer_block_size; - } - /*if( NdisMInitializeScatterGatherDma( p_port->p_adapter->h_adapter, - TRUE, max_phys_mapping )!= NDIS_STATUS_SUCCESS ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("NdisMInitializeScatterGatherDma failed\n" ) ); - return IB_INSUFFICIENT_RESOURCES; - }*/ - } -#endif - - /* Allocate the PD. */ - status = p_port->p_adapter->p_ifc->alloc_pd( - p_port->ib_mgr.h_ca, IB_PDT_UD, p_port, &p_port->ib_mgr.h_pd ); - if( status != IB_SUCCESS ) - { - NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, - EVENT_IPOIB_ALLOC_PD, 1, status ); - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ib_alloc_pd returned %s\n", - p_port->p_adapter->p_ifc->get_err_str( status )) ); - return status; - } - - /* Allocate receive CQ. */ - cq_create.size = p_port->p_adapter->params.rq_depth; - cq_create.pfn_comp_cb = __recv_cb; - cq_create.h_wait_obj = NULL; - - status = p_port->p_adapter->p_ifc->create_cq( - p_port->ib_mgr.h_ca, &cq_create, p_port, - __cq_event, &p_port->ib_mgr.h_recv_cq ); - if( status != IB_SUCCESS ) - { - NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, - EVENT_IPOIB_CREATE_RECV_CQ, 1, status ); - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ib_create_cq returned %s.\n", - p_port->p_adapter->p_ifc->get_err_str( status )) ); - return status; - } - - /* Allocate send CQ. */ - cq_create.size = p_port->p_adapter->params.sq_depth; - cq_create.pfn_comp_cb = __send_cb; - - status = p_port->p_adapter->p_ifc->create_cq( - p_port->ib_mgr.h_ca, &cq_create, p_port, - __cq_event, &p_port->ib_mgr.h_send_cq ); - if( status != IB_SUCCESS ) - { - NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, - EVENT_IPOIB_CREATE_SEND_CQ, 1, status ); - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ib_create_cq returned %s.\n", - p_port->p_adapter->p_ifc->get_err_str( status )) ); - return status; - } - - /* Allocate the QP. */ - cl_memclr( &qp_create, sizeof(qp_create) ); - qp_create.qp_type = IB_QPT_UNRELIABLE_DGRM; - qp_create.rq_depth = p_port->p_adapter->params.rq_depth; - qp_create.rq_sge = 2; /* To support buffers spanning pages. */ - qp_create.h_rq_cq = p_port->ib_mgr.h_recv_cq; - qp_create.sq_depth = p_port->p_adapter->params.sq_depth; - -#define UD_QP_USED_SGE 3 - qp_create.sq_sge = MAX_SEND_SGE < p_port->p_ca_attrs->max_sges ? - MAX_SEND_SGE : ( p_port->p_ca_attrs->max_sges - UD_QP_USED_SGE ); - if ( !p_port->p_ca_attrs->ipoib_csum ) - { - /* checksum is not supported by device - user must specify BYPASS to explicitly cancel checksum calculation */ - if (p_port->p_adapter->params.send_chksum_offload == CSUM_ENABLED) - p_port->p_adapter->params.send_chksum_offload = CSUM_DISABLED; - if (p_port->p_adapter->params.recv_chksum_offload == CSUM_ENABLED) - p_port->p_adapter->params.recv_chksum_offload = CSUM_DISABLED; - } - - qp_create.h_sq_cq = p_port->ib_mgr.h_send_cq; - qp_create.sq_signaled = FALSE; - status = p_port->p_adapter->p_ifc->create_qp( - p_port->ib_mgr.h_pd, &qp_create, p_port, - __qp_event, &p_port->ib_mgr.h_qp ); - if( status != IB_SUCCESS ) - { - NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, - EVENT_IPOIB_CREATE_QP, 1, status ); - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ib_create_qp returned %s\n", - p_port->p_adapter->p_ifc->get_err_str( status )) ); - return status; - } - /* Query the QP so we can get our QPN. */ - status = p_port->p_adapter->p_ifc->query_qp( - p_port->ib_mgr.h_qp, &qp_attr ); - if( status != IB_SUCCESS ) - { - NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, - EVENT_IPOIB_QUERY_QP, 1, status ); - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ib_query_qp returned %s\n", - p_port->p_adapter->p_ifc->get_err_str( status )) ); - return status; - } - p_port->ib_mgr.qpn = qp_attr.num; - - /* Register all of physical memory */ - phys_create.length = MEM_REG_SIZE; - phys_create.num_ranges = 1; - phys_create.range_array = &phys_range; - phys_create.buf_offset = 0; - phys_create.hca_page_size = PAGE_SIZE; - phys_create.access_ctrl = IB_AC_LOCAL_WRITE; - phys_range.base_addr = 0; - phys_range.size = MEM_REG_SIZE; - vaddr = 0; - status = p_port->p_adapter->p_ifc->reg_phys( - p_port->ib_mgr.h_pd, &phys_create, &vaddr, - &p_port->ib_mgr.lkey, &rkey, &p_port->ib_mgr.h_mr ); - if( status != IB_SUCCESS ) - { - NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, - EVENT_IPOIB_REG_PHYS, 1, status ); - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ib_reg_phys returned %s\n", - p_port->p_adapter->p_ifc->get_err_str( status )) ); - return status; - } - - status = ipoib_port_srq_init( p_port ); - if( status != IB_SUCCESS ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ipoib_port_srq_init failed %s\n", - p_port->p_adapter->p_ifc->get_err_str( status )) ); - /* disable further CM initialization */ - p_port->p_adapter->params.cm_enabled = FALSE; - - NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, - EVENT_IPOIB_CONNECTED_MODE_ERR, 1, 0xbadc0de1 ); - - } -//CM -#if 0 - if( p_port->p_adapter->params.cm_enabled ) - { - status = endpt_cm_buf_mgr_init( p_port ); - if( status != IB_SUCCESS ) - { - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("CM Init buf mgr failed status %#x\n", status ) ); - ipoib_port_srq_destroy( p_port ); - p_port->p_adapter->params.cm_enabled = FALSE; - - NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, - EVENT_IPOIB_CONNECTED_MODE_ERR, 1, 0xbadc0de2 ); - } - else - { - if ( p_port->p_adapter->params.send_chksum_offload ) - p_port->p_adapter->params.send_chksum_offload = CSUM_DISABLED; - } - } -#endif - IPOIB_EXIT( IPOIB_DBG_INIT ); - return IB_SUCCESS; -} - -static void -__srq_async_event_cb( -IN ib_async_event_rec_t *p_event_rec ) -{ - ipoib_port_t* p_port = - (ipoib_port_t *)p_event_rec->context; - - switch( p_event_rec->code ) - { - case IB_AE_SRQ_LIMIT_REACHED: - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("SRQ ASYNC EVENT CODE %d: %s\n", - p_event_rec->code, "IB_AE_SRQ_LIMIT_REACHED" ) ); - break; - case IB_AE_SRQ_CATAS_ERROR: - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("SRQ ASYNC EVENT CODE %d: %s\n", - p_event_rec->code, "IB_AE_SRQ_CATAS_ERROR" ) ); - /*SRQ is in err state, must reinitialize */ - p_port->p_adapter->hung = TRUE; - break; - case IB_AE_SRQ_QP_LAST_WQE_REACHED: - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("SRQ ASYNC EVENT CODE %d: %s\n", - p_event_rec->code, "IB_AE_SRQ_QP_LAST_WQE_REACHED" ) ); - /*SRQ is in err state, must reinitialize */ - p_port->p_adapter->hung = TRUE; - break; - default: - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ASYNC EVENT CODE ARRIVED %d(%#x)\n", - p_event_rec->code, p_event_rec->code ) ); - } -} - -ib_api_status_t -ipoib_port_srq_init( - IN ipoib_port_t* const p_port ) -{ - ib_api_status_t ib_status; - ib_srq_handle_t h_srq; - ib_srq_attr_t srq_attr; - - IPOIB_ENTER( IPOIB_DBG_INIT ); - - if( !p_port->p_adapter->params.cm_enabled ) - return IB_SUCCESS; - - srq_attr.max_sge = min( 2, p_port->p_ca_attrs->max_srq_sges ); - srq_attr.srq_limit = 10; - srq_attr.max_wr = - min( (uint32_t)p_port->p_adapter->params.rq_depth * 8, - p_port->p_ca_attrs->max_srq_wrs/2 ); - - ib_status = p_port->p_adapter->p_ifc->create_srq( - p_port->ib_mgr.h_pd, - &srq_attr, - p_port, - __srq_async_event_cb, - &h_srq ); - if( ib_status != IB_SUCCESS ) - { - NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, - EVENT_IPOIB_CREATE_QP, 1, ib_status ); - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ib_create_srq failed status %s\n", - p_port->p_adapter->p_ifc->get_err_str( ib_status )) ); - return ib_status; - } - p_port->ib_mgr.h_srq = h_srq; - - IPOIB_EXIT( IPOIB_DBG_INIT ); - - return ib_status; -} - -/* __port_query_ca_attrs() - * returns a pointer to allocated memory. - * must be released by caller. - */ -static ib_api_status_t -__port_query_ca_attrs( - IN ipoib_port_t* const p_port, - IN ib_ca_attr_t** pp_ca_attrs ) -{ - ib_api_status_t ib_status; - uint32_t attr_size; - ib_ca_attr_t* p_ca_attrs; - - *pp_ca_attrs = NULL; - - ib_status = - p_port->p_adapter->p_ifc->query_ca( p_port->ib_mgr.h_ca, NULL , &attr_size ); - if( ib_status != IB_INSUFFICIENT_MEMORY ) - { - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ib_query_ca failed status %s\n", - p_port->p_adapter->p_ifc->get_err_str( ib_status )) ); - goto done; - } - CL_ASSERT( attr_size ); - - p_ca_attrs = cl_zalloc( attr_size ); - if ( p_ca_attrs == NULL ) - { - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Allocate %d bytes failed for CA Attributes\n", attr_size )); - ib_status = IB_INSUFFICIENT_MEMORY; - goto done; - } - - ib_status = - p_port->p_adapter->p_ifc->query_ca( p_port->ib_mgr.h_ca, p_ca_attrs , &attr_size ); - if ( ib_status != IB_SUCCESS ) - { - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("CA attributes query failed\n") ); - cl_free ( p_ca_attrs ); - goto done; - } - - *pp_ca_attrs = p_ca_attrs; -done: - return ib_status; -} - -void -ipoib_port_srq_destroy( - IN ipoib_port_t* const p_port ) -{ - ib_api_status_t status; - - if( p_port->ib_mgr.h_srq ) - { - status = - p_port->p_adapter->p_ifc->destroy_srq( p_port->ib_mgr.h_srq, NULL ); - CL_ASSERT( status == IB_SUCCESS ); - p_port->ib_mgr.h_srq = NULL; - } -} - -static void -__ib_mgr_destroy( - IN ipoib_port_t* const p_port ) -{ - ib_api_status_t status; - - IPOIB_ENTER( IPOIB_DBG_INIT ); - - if( p_port->ib_mgr.h_ca ) - { - status = - p_port->p_adapter->p_ifc->close_ca( p_port->ib_mgr.h_ca, NULL ); - CL_ASSERT( status == IB_SUCCESS ); - p_port->ib_mgr.h_ca = NULL; - } - - IPOIB_EXIT( IPOIB_DBG_INIT ); -} - - - -/****************************************************************************** -* -* Buffer manager implementation. -* -******************************************************************************/ -static void -__buf_mgr_construct( - IN ipoib_port_t* const p_port ) -{ - IPOIB_ENTER( IPOIB_DBG_INIT ); - - cl_qpool_construct( &p_port->buf_mgr.recv_pool ); - - p_port->buf_mgr.h_packet_pool = NULL; - p_port->buf_mgr.h_buffer_pool = NULL; - - NdisInitializeNPagedLookasideList( &p_port->buf_mgr.send_buf_list, - NULL, NULL, 0, MAX_XFER_BLOCK_SIZE, 'bipi', 0 ); - - p_port->buf_mgr.h_send_pkt_pool = NULL; - p_port->buf_mgr.h_send_buf_pool = NULL; - - IPOIB_EXIT( IPOIB_DBG_INIT ); -} - - -static ib_api_status_t -__buf_mgr_init( - IN ipoib_port_t* const p_port ) -{ - cl_status_t cl_status; - ipoib_params_t *p_params; - NET_BUFFER_LIST_POOL_PARAMETERS pool_parameters; - IPOIB_ENTER(IPOIB_DBG_INIT ); - - CL_ASSERT( p_port ); - CL_ASSERT( p_port->p_adapter ); - - p_params = &p_port->p_adapter->params; - - /* Allocate the receive descriptor pool */ - cl_status = cl_qpool_init( &p_port->buf_mgr.recv_pool, - p_params->rq_depth * p_params->recv_pool_ratio, -#if IPOIB_INLINE_RECV - 0, 0, sizeof(ipoib_recv_desc_t), __recv_ctor, NULL, p_port ); -#else /* IPOIB_INLINE_RECV */ - 0, 0, sizeof(ipoib_recv_desc_t), __recv_ctor, __recv_dtor, p_port ); -#endif /* IPOIB_INLINE_RECV */ - if( cl_status != CL_SUCCESS ) - { - NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, - EVENT_IPOIB_RECV_POOL, 1, cl_status ); - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("cl_qpool_init for recvs returned %#x\n", - cl_status) ); - return IB_INSUFFICIENT_MEMORY; - } - - /* Allocate the NET BUFFER list pools for receive indication. */ - NdisZeroMemory(&pool_parameters, sizeof(NET_BUFFER_LIST_POOL_PARAMETERS)); - pool_parameters.Header.Type = NDIS_OBJECT_TYPE_DEFAULT; - pool_parameters.Header.Revision = NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1; - pool_parameters.Header.Size = sizeof(pool_parameters); - pool_parameters.ProtocolId = 0; - pool_parameters.ContextSize = 0; - pool_parameters.fAllocateNetBuffer = TRUE; - pool_parameters.PoolTag = 'CRPI'; - - p_port->buf_mgr.h_packet_pool = NdisAllocateNetBufferListPool( - p_port->p_adapter->h_adapter, - &pool_parameters); - - if( !p_port->buf_mgr.h_packet_pool ) - { - NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, - EVENT_IPOIB_RECV_PKT_POOL, 1, NDIS_STATUS_RESOURCES ); - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("NdisAllocatePacketPool returned %08X\n", (UINT)NDIS_STATUS_RESOURCES) ); - return IB_INSUFFICIENT_RESOURCES; - } -/* - NdisAllocateBufferPool( &ndis_status, &p_port->buf_mgr.h_buffer_pool, - p_params->rq_depth ); - if( ndis_status != NDIS_STATUS_SUCCESS ) - { - NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, - EVENT_IPOIB_RECV_BUF_POOL, 1, ndis_status ); - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("NdisAllocateBufferPool returned %08X\n", ndis_status) ); - return IB_INSUFFICIENT_RESOURCES; - } -*/ - /* Allocate the NET buffer list pool for send formatting. */ - pool_parameters.PoolTag = 'XTPI'; - - p_port->buf_mgr.h_send_pkt_pool = NdisAllocateNetBufferListPool( - p_port->p_adapter->h_adapter, - &pool_parameters); - if( !p_port->buf_mgr.h_send_pkt_pool) - { - NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, - EVENT_IPOIB_SEND_PKT_POOL, 1, NDIS_STATUS_RESOURCES ); - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("NdisAllocatePacketPool returned %08X\n", (UINT)NDIS_STATUS_RESOURCES) ); - return IB_INSUFFICIENT_RESOURCES; - } -/* - NdisAllocateBufferPool( &ndis_status, - &p_port->buf_mgr.h_send_buf_pool, 1 ); - if( ndis_status != NDIS_STATUS_SUCCESS ) - { - NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, - EVENT_IPOIB_SEND_BUF_POOL, 1, ndis_status ); - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("NdisAllocateBufferPool returned %08X\n", ndis_status) ); - return IB_INSUFFICIENT_RESOURCES; - } -*/ - IPOIB_EXIT( IPOIB_DBG_INIT ); - return IB_SUCCESS; -} - - -static void -__buf_mgr_destroy( - IN ipoib_port_t* const p_port ) -{ - IPOIB_ENTER(IPOIB_DBG_INIT ); - - CL_ASSERT( p_port ); - - /* Destroy the send packet and buffer pools. - if( p_port->buf_mgr.h_send_buf_pool ) - NdisFreeBufferPool( p_port->buf_mgr.h_send_buf_pool );*/ - if( p_port->buf_mgr.h_send_pkt_pool ) - NdisFreeNetBufferListPool ( p_port->buf_mgr.h_send_pkt_pool ); - - /* Destroy the receive packet and buffer pools. - if( p_port->buf_mgr.h_buffer_pool ) - NdisFreeBufferPool( p_port->buf_mgr.h_buffer_pool );*/ - if( p_port->buf_mgr.h_packet_pool ) - NdisFreeNetBufferListPool ( p_port->buf_mgr.h_packet_pool ); - - /* Free the receive and send descriptors. */ - cl_qpool_destroy( &p_port->buf_mgr.recv_pool ); - - /* Free the lookaside list of scratch buffers. */ - NdisDeleteNPagedLookasideList( &p_port->buf_mgr.send_buf_list ); - - IPOIB_EXIT( IPOIB_DBG_INIT ); -} - - -static cl_status_t -__recv_ctor( - IN void* const p_object, - IN void* context, - OUT cl_pool_item_t** const pp_pool_item ) -{ - ipoib_recv_desc_t *p_desc; - ipoib_port_t *p_port; - -#if IPOIB_INLINE_RECV - uint32_t ds0_len; -#endif - - IPOIB_ENTER( IPOIB_DBG_ALLOC ); - - CL_ASSERT( p_object ); - CL_ASSERT( context ); - - p_desc = (ipoib_recv_desc_t*)p_object; - p_port = (ipoib_port_t*)context; - - /* Setup the work request. */ - p_desc->wr.ds_array = p_desc->local_ds; - p_desc->wr.wr_id = (uintn_t)p_desc; - -#if IPOIB_INLINE_RECV - /* Sanity check on the receive buffer layout */ - CL_ASSERT( (void*)&p_desc->buf.eth.pkt.type == - (void*)&p_desc->buf.ib.pkt.type ); - CL_ASSERT( sizeof(recv_buf_t) == sizeof(ipoib_pkt_t) + sizeof(ib_grh_t) ); - - /* Setup the local data segment. */ - p_desc->local_ds[0].vaddr = cl_get_physaddr( &p_desc->buf ); - p_desc->local_ds[0].lkey = p_port->ib_mgr.lkey; - ds0_len = - PAGE_SIZE - ((uint32_t)p_desc->local_ds[0].vaddr & (PAGE_SIZE - 1)); - if( ds0_len >= sizeof(recv_buf_t) ) - { - /* The whole buffer is within a page. */ - p_desc->local_ds[0].length = ds0_len; - p_desc->wr.num_ds = 1; - } - else - { - /* The buffer crosses page boundaries. */ - p_desc->local_ds[0].length = ds0_len; - p_desc->local_ds[1].vaddr = cl_get_physaddr( - ((uint8_t*)&p_desc->buf) + ds0_len ); - p_desc->local_ds[1].lkey = p_port->ib_mgr.lkey; - p_desc->local_ds[1].length = sizeof(recv_buf_t) - ds0_len; - p_desc->wr.num_ds = 2; - } -#else /* IPOIB_INLINE_RECV */ - /* Allocate the receive buffer. */ - p_desc->p_buf = (recv_buf_t*)cl_zalloc( sizeof(recv_buf_t) ); - if( !p_desc->p_buf ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed to allocate receive buffer.\n") ); - return CL_INSUFFICIENT_MEMORY; - } - - /* Sanity check on the receive buffer layout */ - CL_ASSERT( (void*)&p_desc->p_buf->eth.pkt.type == - (void*)&p_desc->p_buf->ib.pkt.type ); - - /* Setup the local data segment. */ - p_desc->local_ds[0].vaddr = cl_get_physaddr( p_desc->p_buf ); - p_desc->local_ds[0].length = sizeof(ipoib_pkt_t) + sizeof(ib_grh_t); - p_desc->local_ds[0].lkey = p_port->ib_mgr.lkey; - p_desc->wr.num_ds = 1; -#endif /* IPOIB_INLINE_RECV */ - - *pp_pool_item = &p_desc->item; - - IPOIB_EXIT( IPOIB_DBG_ALLOC ); - return CL_SUCCESS; -} - - -#if !IPOIB_INLINE_RECV -static void -__recv_dtor( - IN const cl_pool_item_t* const p_pool_item, - IN void *context ) -{ - ipoib_recv_desc_t *p_desc; - - IPOIB_ENTER( IPOIB_DBG_ALLOC ); - - UNUSED_PARAM( context ); - - p_desc = PARENT_STRUCT( p_pool_item, ipoib_recv_desc_t, item ); - - if( p_desc->p_buf ) - cl_free( p_desc->p_buf ); - - IPOIB_EXIT( IPOIB_DBG_ALLOC ); -} -#endif - - -static inline ipoib_recv_desc_t* -__buf_mgr_get_recv( - IN ipoib_port_t* const p_port ) -{ - ipoib_recv_desc_t *p_desc; - IPOIB_ENTER( IPOIB_DBG_RECV ); - p_desc = (ipoib_recv_desc_t*)cl_qpool_get( &p_port->buf_mgr.recv_pool ); - /* Reference the port object for the send. */ - if( p_desc ) - { - ipoib_port_ref( p_port, ref_get_recv ); - CL_ASSERT( p_desc->wr.wr_id == (uintn_t)p_desc ); -#if IPOIB_INLINE_RECV - CL_ASSERT( p_desc->local_ds[0].vaddr == - cl_get_physaddr( &p_desc->buf ) ); -#else /* IPOIB_INLINE_RECV */ - CL_ASSERT( p_desc->local_ds[0].vaddr == - cl_get_physaddr( p_desc->p_buf ) ); - CL_ASSERT( p_desc->local_ds[0].length == - (sizeof(ipoib_pkt_t) + sizeof(ib_grh_t)) ); -#endif /* IPOIB_INLINE_RECV */ - CL_ASSERT( p_desc->local_ds[0].lkey == p_port->ib_mgr.lkey ); - } - IPOIB_EXIT( IPOIB_DBG_RECV ); - return p_desc; -} - - -//NDIS60 -static inline void -__buf_mgr_put_recv( - IN ipoib_port_t* const p_port, - IN ipoib_recv_desc_t* const p_desc, - IN NET_BUFFER_LIST* const p_net_buffer_list OPTIONAL ) -{ - NET_BUFFER *p_buf = NULL; - MDL *p_mdl = NULL; - IPOIB_ENTER(IPOIB_DBG_RECV ); - - if( p_net_buffer_list ) - { - NET_BUFFER_LIST_NEXT_NBL(p_net_buffer_list) = NULL; - p_buf = NET_BUFFER_LIST_FIRST_NB(p_net_buffer_list); - CL_ASSERT( p_buf ); - p_mdl = NET_BUFFER_FIRST_MDL(p_buf); - CL_ASSERT( p_mdl ); - NdisFreeMdl(p_mdl); - NdisFreeNetBufferList(p_net_buffer_list); - } - - /* Return the descriptor to its pools. */ - cl_qpool_put( &p_port->buf_mgr.recv_pool, &p_desc->item ); - - /* - * Dereference the port object since the receive is no longer outstanding. - */ - ipoib_port_deref( p_port, ref_get_recv ); - IPOIB_EXIT( IPOIB_DBG_RECV ); -} - - -static inline void -__buf_mgr_put_recv_list( - IN ipoib_port_t* const p_port, - IN cl_qlist_t* const p_list ) -{ - //IPOIB_ENTER( IPOIB_DBG_RECV ); - cl_qpool_put_list( &p_port->buf_mgr.recv_pool, p_list ); - //IPOIB_EXIT( IPOIB_DBG_RECV ); -} - - -static inline NET_BUFFER_LIST* -__buf_mgr_get_ndis_pkt( - IN ipoib_port_t* const p_port, - IN ipoib_recv_desc_t* const p_desc ) -{ - NET_BUFFER_LIST *p_net_buffer_list; - MDL *p_mdl; - - IPOIB_ENTER( IPOIB_DBG_RECV ); - - p_mdl = NdisAllocateMdl(p_port->p_adapter->h_adapter, - &p_desc->buf.eth.pkt, - p_desc->len ); - if( !p_mdl ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed to allocate MDL\n") ); - return NULL; - } - - p_net_buffer_list = NdisAllocateNetBufferAndNetBufferList( - p_port->buf_mgr.h_packet_pool, - 0, - 0, - p_mdl, - 0, - 0); - - if( !p_net_buffer_list ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed to allocate NET_BUFFER_LIST\n") ); - NdisFreeMdl(p_mdl); - return NULL; - } - - NET_BUFFER_LIST_NEXT_NBL(p_net_buffer_list) = NULL; - IPOIB_PORT_FROM_PACKET( p_net_buffer_list ) = p_port; - IPOIB_RECV_FROM_PACKET( p_net_buffer_list ) = p_desc; - p_net_buffer_list->SourceHandle = p_port->p_adapter->h_adapter; - - IPOIB_EXIT( IPOIB_DBG_RECV ); - return p_net_buffer_list; -} - - -/****************************************************************************** -* -* Receive manager implementation. -* -******************************************************************************/ -static void -__recv_mgr_construct( - IN ipoib_port_t* const p_port ) -{ - IPOIB_ENTER( IPOIB_DBG_INIT ); - - cl_qlist_init( &p_port->recv_mgr.done_list ); - - p_port->recv_mgr.recv_pkt_array = NULL; - - IPOIB_EXIT( IPOIB_DBG_INIT ); -} - - -static ib_api_status_t -__recv_mgr_init( - IN ipoib_port_t* const p_port ) -{ - IPOIB_ENTER( IPOIB_DBG_INIT ); - - /* Allocate the NDIS_PACKET pointer array for indicating receives. */ - p_port->recv_mgr.recv_pkt_array = cl_malloc( - sizeof(NET_BUFFER_LIST*) * p_port->p_adapter->params.rq_depth ); - if( !p_port->recv_mgr.recv_pkt_array ) - { - NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, - EVENT_IPOIB_RECV_PKT_ARRAY, 0 ); - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("cl_malloc for PNDIS_PACKET array failed.\n") ); - return IB_INSUFFICIENT_MEMORY; - } - - IPOIB_EXIT( IPOIB_DBG_INIT ); - return IB_SUCCESS; -} - - -static void -__recv_mgr_destroy( - IN ipoib_port_t* const p_port ) -{ - IPOIB_ENTER( IPOIB_DBG_INIT ); - - CL_ASSERT( cl_is_qlist_empty( &p_port->recv_mgr.done_list ) ); - CL_ASSERT( !p_port->recv_mgr.depth ); - - if( p_port->recv_mgr.recv_pkt_array ) - cl_free( p_port->recv_mgr.recv_pkt_array ); - - IPOIB_EXIT( IPOIB_DBG_INIT ); -} - - -/* - * Posts receive buffers to the receive queue and returns the number - * of receives needed to bring the RQ to its low water mark. Note - * that the value is signed, and can go negative. All tests must - * be for > 0. - */ -static int32_t -__recv_mgr_repost( - IN ipoib_port_t* const p_port ) -{ - ipoib_recv_desc_t *p_head = NULL, *p_tail = NULL, *p_next; - ib_api_status_t status; - ib_recv_wr_t *p_failed; - PERF_DECLARE( GetRecv ); - PERF_DECLARE( PostRecv ); - - IPOIB_ENTER( IPOIB_DBG_RECV ); - - CL_ASSERT( p_port ); - cl_obj_lock( &p_port->obj ); - if( p_port->state != IB_QPS_RTS ) - { - cl_obj_unlock( &p_port->obj ); - IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_RECV, - ("Port in invalid state. Not reposting.\n") ); - return 0; - } - ipoib_port_ref( p_port, ref_repost ); - cl_obj_unlock( &p_port->obj ); - - while( p_port->recv_mgr.depth < p_port->p_adapter->params.rq_depth ) - { - /* Pull receives out of the pool and chain them up. */ - cl_perf_start( GetRecv ); - p_next = __buf_mgr_get_recv( p_port ); - cl_perf_stop( &p_port->p_adapter->perf, GetRecv ); - if( !p_next ) - { - IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_RECV, - ("Out of receive descriptors! recv queue depth 0x%x\n",p_port->recv_mgr.depth) ); - break; - } - - if( !p_tail ) - { - p_tail = p_next; - p_next->wr.p_next = NULL; - } - else - { - p_next->wr.p_next = &p_head->wr; - } - - p_head = p_next; - - p_port->recv_mgr.depth++; - } - - if( p_head ) - { - cl_perf_start( PostRecv ); - status = p_port->p_adapter->p_ifc->post_recv( - p_port->ib_mgr.h_qp, &p_head->wr, &p_failed ); - cl_perf_stop( &p_port->p_adapter->perf, PostRecv ); - - if( status != IB_SUCCESS ) - { - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ip_post_recv returned %s\n", - p_port->p_adapter->p_ifc->get_err_str( status )) ); - /* return the descriptors to the pool */ - while( p_failed ) - { - p_head = PARENT_STRUCT( p_failed, ipoib_recv_desc_t, wr ); - p_failed = p_failed->p_next; - - __buf_mgr_put_recv( p_port, p_head, NULL ); - p_port->recv_mgr.depth--; - } - } - } - - ipoib_port_deref( p_port, ref_repost ); - IPOIB_EXIT( IPOIB_DBG_RECV ); - return p_port->p_adapter->params.rq_low_watermark - p_port->recv_mgr.depth; -} - -void -ipoib_return_net_buffer_list( - IN NDIS_HANDLE adapter_context, - IN NET_BUFFER_LIST *p_net_buffer_lists, - IN ULONG return_flags) -{ -// cl_list_item_t *p_item; - ipoib_port_t *p_port; - ipoib_recv_desc_t *p_desc; - NET_BUFFER_LIST *cur_net_buffer_list,*next_net_buffer_list; -// ib_api_status_t status = IB_NOT_DONE; -// int32_t shortage; -// ULONG complete_flags = 0; - PERF_DECLARE( ReturnPacket ); - PERF_DECLARE( ReturnPutRecv ); - PERF_DECLARE( ReturnRepostRecv ); - PERF_DECLARE( ReturnPreparePkt ); - PERF_DECLARE( ReturnNdisIndicate ); - - IPOIB_ENTER( IPOIB_DBG_RECV ); - - UNUSED_PARAM( return_flags ); - - p_port = ((ipoib_adapter_t*)adapter_context)->p_port; - CL_ASSERT( p_net_buffer_lists ); - - cl_perf_start( ReturnPacket ); - cl_spinlock_acquire( &p_port->recv_lock ); - for (cur_net_buffer_list = p_net_buffer_lists; - cur_net_buffer_list != NULL; - cur_net_buffer_list = next_net_buffer_list) - { - next_net_buffer_list = NET_BUFFER_LIST_NEXT_NBL(cur_net_buffer_list); - - /* Get the port and descriptor from the packet. */ - CL_ASSERT(p_port == IPOIB_PORT_FROM_PACKET( cur_net_buffer_list )); - p_desc = IPOIB_RECV_FROM_PACKET( cur_net_buffer_list ); - - - //TODO: NDIS60, rewrite this block - /* Get descriptor from the packet. */ -#if 0 - if( p_desc->type == PKT_TYPE_CM_UCAST ) - { - NDIS_BUFFER *p_buf; - - /* Unchain the NDIS buffer. */ - NdisUnchainBufferAtFront( p_packet, &p_buf ); - CL_ASSERT( p_buf ); - /* Return the NDIS packet and NDIS buffer to their pools. */ - NdisDprFreePacketNonInterlocked( p_packet ); - NdisFreeBuffer( p_buf ); - - endpt_cm_buf_mgr_put_recv( &p_port->cm_buf_mgr, (ipoib_cm_desc_t *)p_desc ); - status = endpt_cm_post_recv( p_port ); - if( status != IB_SUCCESS ) - { - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Post Recv QP failed\n" ) ); - } - cl_spinlock_release( &p_port->recv_lock ); - return; - } -#endif - - cl_perf_start( ReturnPutRecv ); - __buf_mgr_put_recv( p_port, p_desc, cur_net_buffer_list ); - cl_perf_stop( &p_port->p_adapter->perf, ReturnPutRecv ); - } -#if 0 - /* Repost buffers. */ - cl_perf_start( ReturnRepostRecv ); - shortage = __recv_mgr_repost( p_port ); - cl_perf_stop( &p_port->p_adapter->perf, ReturnRepostRecv ); - - for( p_item = cl_qlist_remove_head( &p_port->recv_mgr.done_list ); - p_item != cl_qlist_end( &p_port->recv_mgr.done_list ); - p_item = cl_qlist_remove_head( &p_port->recv_mgr.done_list ) ) - { - p_desc = (ipoib_recv_desc_t*)p_item; - - cl_perf_start( ReturnPreparePkt ); - status = __recv_mgr_prepare_pkt( p_port, p_desc, &cur_net_buffer_list ); - cl_perf_stop( &p_port->p_adapter->perf, ReturnPreparePkt ); - if( status == IB_SUCCESS ) - { - if( shortage > 0 ) - NET_BUFFER_LIST_STATUS( cur_net_buffer_list) = NDIS_STATUS_RESOURCES; - else - NET_BUFFER_LIST_STATUS( cur_net_buffer_list) = NDIS_STATUS_SUCCESS; - - cl_spinlock_release( &p_port->recv_lock ); - NET_BUFFER_LIST_NEXT_NBL(cur_net_buffer_list) = NULL; - cl_perf_start( ReturnNdisIndicate ); - NdisMRecvIndicate( p_port->p_adapter->h_adapter, - cur_net_buffer_list, complete_flags ); - cl_perf_stop( &p_port->p_adapter->perf, ReturnNdisIndicate ); - cl_spinlock_acquire( &p_port->recv_lock ); - - if( shortage > 0 ) - { - cl_perf_start( ReturnPutRecv ); - __buf_mgr_put_recv( p_port, p_desc, cur_net_buffer_list ); - cl_perf_stop( &p_port->p_adapter->perf, ReturnPutRecv ); - - /* Repost buffers. */ - cl_perf_start( ReturnRepostRecv ); - shortage = __recv_mgr_repost( p_port ); - cl_perf_stop( &p_port->p_adapter->perf, ReturnRepostRecv ); - } - } - else if( status != IB_NOT_DONE ) - { - IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_RECV, - ("__recv_mgr_prepare_pkt returned %s\n", - p_port->p_adapter->p_ifc->get_err_str( status )) ); - /* Return the item to the head of the list. */ - cl_qlist_insert_head( &p_port->recv_mgr.done_list, p_item ); - break; - } - } - #endif - cl_spinlock_release( &p_port->recv_lock ); - cl_perf_stop( &p_port->p_adapter->perf, ReturnPacket ); - - IPOIB_EXIT( IPOIB_DBG_RECV ); -} - -static void __recv_cb_dpc(KDPC *p_gc_dpc,void *context,void * s_arg1 , void * s_arg2) -{ - - ipoib_port_t *p_port = context; - - UNREFERENCED_PARAMETER(p_gc_dpc); - UNREFERENCED_PARAMETER(s_arg1); - UNREFERENCED_PARAMETER(s_arg2); - - - __recv_cb(NULL, p_port); - ipoib_port_deref( p_port, ref_recv_cb ); - - -} - - -static void -__recv_cb( - IN const ib_cq_handle_t h_cq, - IN void *cq_context ) -{ - ipoib_port_t *p_port; - ib_api_status_t status; - ib_wc_t wc[MAX_RECV_WC], *p_free, *p_wc; - int32_t pkt_cnt, recv_cnt = 0, shortage, discarded; - cl_qlist_t done_list, bad_list; - size_t i; - ULONG recv_complete_flags = 0; - - PERF_DECLARE( RecvCompBundle ); - PERF_DECLARE( RecvCb ); - PERF_DECLARE( PollRecv ); - PERF_DECLARE( RepostRecv ); - PERF_DECLARE( FilterRecv ); - PERF_DECLARE( BuildPktArray ); - PERF_DECLARE( RecvNdisIndicate ); - PERF_DECLARE( RearmRecv ); - PERF_DECLARE( PutRecvList ); - - IPOIB_ENTER( IPOIB_DBG_RECV ); - - cl_perf_clr( RecvCompBundle ); - - cl_perf_start( RecvCb ); -//return ; - UNUSED_PARAM( h_cq ); - - NDIS_SET_SEND_COMPLETE_FLAG(recv_complete_flags, NDIS_RECEIVE_FLAGS_DISPATCH_LEVEL ); - - p_port = (ipoib_port_t*)cq_context; - - cl_qlist_init( &done_list ); - cl_qlist_init( &bad_list ); - - ipoib_port_ref( p_port, ref_recv_cb ); - for( i = 0; i < MAX_RECV_WC; i++ ) - wc[i].p_next = &wc[i + 1]; - wc[MAX_RECV_WC - 1].p_next = NULL; - - /* - * We'll be accessing the endpoint map so take a reference - * on it to prevent modifications. - */ - cl_obj_lock( &p_port->obj ); - cl_atomic_inc( &p_port->endpt_rdr ); - cl_obj_unlock( &p_port->obj ); - - do - { - /* If we get here, then the list of WCs is intact. */ - p_free = wc; - - cl_perf_start( PollRecv ); - status = p_port->p_adapter->p_ifc->poll_cq( - p_port->ib_mgr.h_recv_cq, &p_free, &p_wc ); - cl_perf_stop( &p_port->p_adapter->perf, PollRecv ); - CL_ASSERT( status == IB_SUCCESS || status == IB_NOT_FOUND ); - - /* Look at the payload now and filter ARP and DHCP packets. */ - cl_perf_start( FilterRecv ); - recv_cnt += __recv_mgr_filter( p_port, p_wc, &done_list, &bad_list ); - cl_perf_stop( &p_port->p_adapter->perf, FilterRecv ); - - } while( (!p_free) && (recv_cnt < 128)); - - /* We're done looking at the endpoint map, release the reference. */ - cl_atomic_dec( &p_port->endpt_rdr ); - - cl_perf_log( &p_port->p_adapter->perf, RecvCompBundle, recv_cnt ); - - cl_spinlock_acquire( &p_port->recv_lock ); - - /* Update our posted depth. */ - p_port->recv_mgr.depth -= recv_cnt; - - /* Return any discarded receives to the pool */ - cl_perf_start( PutRecvList ); - __buf_mgr_put_recv_list( p_port, &bad_list ); - cl_perf_stop( &p_port->p_adapter->perf, PutRecvList ); - - do - { - int32_t cnt; - /* Repost ASAP so we don't starve the RQ. */ - cl_perf_start( RepostRecv ); - shortage = __recv_mgr_repost( p_port ); - cl_perf_stop( &p_port->p_adapter->perf, RepostRecv ); - - cl_perf_start( BuildPktArray ); - /* Notify NDIS of any and all possible receive buffers. */ - pkt_cnt = __recv_mgr_build_pkt_array( - p_port, shortage, &done_list, &discarded ); - cl_perf_stop( &p_port->p_adapter->perf, BuildPktArray ); - - /* Only indicate receives if we actually had any. */ - if( discarded && shortage > 0 ) - { - /* We may have thrown away packets, and have a shortage */ - cl_perf_start( RepostRecv ); - __recv_mgr_repost( p_port ); - cl_perf_stop( &p_port->p_adapter->perf, RepostRecv ); - } - - if( !pkt_cnt ) - break; - - cl_spinlock_release( &p_port->recv_lock ); - for( cnt = 0; cnt < pkt_cnt -1; cnt++) - { - NET_BUFFER_LIST_NEXT_NBL(p_port->recv_mgr.recv_pkt_array[cnt]) = - p_port->recv_mgr.recv_pkt_array[cnt + 1]; - } - cl_perf_start( RecvNdisIndicate ); -#ifndef NDIS_DEFAULT_PORT_NUMBER -#define NDIS_DEFAULT_PORT_NUMBER 0 -#endif - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Indicate NDIS with %d received NBs\n", - pkt_cnt) ); - NdisMIndicateReceiveNetBufferLists( - p_port->p_adapter->h_adapter, - p_port->recv_mgr.recv_pkt_array[0], - NDIS_DEFAULT_PORT_NUMBER, - pkt_cnt, - recv_complete_flags); - - cl_perf_stop( &p_port->p_adapter->perf, RecvNdisIndicate ); - - /* - * Cap the number of receives to put back to what we just indicated - * with NDIS_STATUS_RESOURCES. - */ - if( shortage > 0 ) - { - if( pkt_cnt < shortage ) - shortage = pkt_cnt; - - /* Return all but the last packet to the pool. */ - cl_spinlock_acquire( &p_port->recv_lock ); - while( shortage-- > 1 ) - { - __buf_mgr_put_recv( p_port, - (ipoib_recv_desc_t *)IPOIB_RECV_FROM_PACKET( p_port->recv_mgr.recv_pkt_array[shortage] ), - p_port->recv_mgr.recv_pkt_array[shortage] ); - } - cl_spinlock_release( &p_port->recv_lock ); - - /* - * Return the last packet as if NDIS returned it, so that we repost - * and report any other pending receives. - */ - ipoib_return_net_buffer_list( NULL, p_port->recv_mgr.recv_pkt_array[0],recv_complete_flags ); - } - cl_spinlock_acquire( &p_port->recv_lock ); - - } while( pkt_cnt ); - cl_spinlock_release( &p_port->recv_lock ); - - if (p_free ) { - /* - * Rearm after filtering to prevent contention on the enpoint maps - * and eliminate the possibility of having a call to - * __endpt_mgr_insert find a duplicate. - */ - cl_perf_start( RearmRecv ); - status = p_port->p_adapter->p_ifc->rearm_cq( - p_port->ib_mgr.h_recv_cq, FALSE ); - cl_perf_stop( &p_port->p_adapter->perf, RearmRecv ); - CL_ASSERT( status == IB_SUCCESS ); - - ipoib_port_deref( p_port, ref_recv_cb ); - } else { - // Please note the reference is still up - KeInsertQueueDpc(&p_port->recv_dpc, NULL, NULL); - } - - cl_perf_stop( &p_port->p_adapter->perf, RecvCb ); - - IPOIB_EXIT( IPOIB_DBG_RECV ); -} - - -static void -__recv_get_endpts( - IN ipoib_port_t* const p_port, - IN ipoib_recv_desc_t* const p_desc, - IN ib_wc_t* const p_wc, - OUT ipoib_endpt_t** const pp_src, - OUT ipoib_endpt_t** const pp_dst ) -{ - ib_api_status_t status; - mac_addr_t mac; - PERF_DECLARE( GetEndptByGid ); - PERF_DECLARE( GetEndptByLid ); - PERF_DECLARE( EndptInsert ); - - IPOIB_ENTER( IPOIB_DBG_RECV ); - - /* Setup our shortcut pointers based on whether GRH is valid. */ - if( p_wc->recv.ud.recv_opt & IB_RECV_OPT_GRH_VALID ) - { - /* Lookup the source endpoints based on GID. */ - cl_perf_start( GetEndptByGid ); - *pp_src = -#if IPOIB_INLINE_RECV - __endpt_mgr_get_by_gid( p_port, &p_desc->buf.ib.grh.src_gid ); -#else /* IPOIB_INLINE_RECV */ - __endpt_mgr_get_by_gid( p_port, &p_desc->p_buf->ib.grh.src_gid ); -#endif /* IPOIB_INLINE_RECV */ - cl_perf_stop( &p_port->p_adapter->perf, GetEndptByGid ); - - /* - * Lookup the destination endpoint based on GID. - * This is used along with the packet filter to determine - * whether to report this to NDIS. - */ - cl_perf_start( GetEndptByGid ); - *pp_dst = -#if IPOIB_INLINE_RECV - __endpt_mgr_get_by_gid( p_port, &p_desc->buf.ib.grh.dest_gid ); -#else /* IPOIB_INLINE_RECV */ - __endpt_mgr_get_by_gid( p_port, &p_desc->p_buf->ib.grh.dest_gid ); -#endif /* IPOIB_INLINE_RECV */ - cl_perf_stop( &p_port->p_adapter->perf, GetEndptByGid ); - - /* - * Create the source endpoint if it does not exist. Note that we - * can only do this for globally routed traffic since we need the - * information from the GRH to generate the MAC. - */ - if( !*pp_src ) - { - status = ipoib_mac_from_guid( -#if IPOIB_INLINE_RECV - p_desc->buf.ib.grh.src_gid.unicast.interface_id, p_port->p_adapter->params.guid_mask, &mac ); -#else /* IPOIB_INLINE_RECV */ - p_desc->p_buf->ib.grh.src_gid.unicast.interface_id, p_port->p_adapter->params.guid_mask, &mac ); -#endif /* IPOIB_INLINE_RECV */ - if( status != IB_SUCCESS ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ipoib_mac_from_guid returned %s\n", - p_port->p_adapter->p_ifc->get_err_str( status )) ); - return; - } - - /* Create the endpoint. */ -#if IPOIB_INLINE_RECV - *pp_src = ipoib_endpt_create( &p_desc->buf.ib.grh.src_gid, -#else /* IPOIB_INLINE_RECV */ - *pp_src = ipoib_endpt_create( &p_desc->p_buf->ib.grh.src_gid, -#endif /* IPOIB_INLINE_RECV */ - p_wc->recv.ud.remote_lid, p_wc->recv.ud.remote_qp ); - if( !*pp_src ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ipoib_endpt_create failed\n") ); - return; - } - cl_perf_start( EndptInsert ); - cl_obj_lock( &p_port->obj ); - status = __endpt_mgr_insert( p_port, mac, *pp_src ); - if( status != IB_SUCCESS ) - { - cl_obj_unlock( &p_port->obj ); - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("__endpt_mgr_insert returned %s\n", - p_port->p_adapter->p_ifc->get_err_str( status )) ); - *pp_src = NULL; - return; - } - cl_obj_unlock( &p_port->obj ); - cl_perf_stop( &p_port->p_adapter->perf, EndptInsert ); - } - } - else - { - /* - * Lookup the remote endpoint based on LID. Note that only - * unicast traffic can be LID routed. - */ - cl_perf_start( GetEndptByLid ); - *pp_src = __endpt_mgr_get_by_lid( p_port, p_wc->recv.ud.remote_lid ); - cl_perf_stop( &p_port->p_adapter->perf, GetEndptByLid ); - *pp_dst = p_port->p_local_endpt; - CL_ASSERT( *pp_dst ); - } - - if( *pp_src && !ipoib_is_voltaire_router_gid( &(*pp_src)->dgid ) && - (*pp_src)->qpn != p_wc->recv.ud.remote_qp ) - { - /* Update the QPN for the endpoint. */ - IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_RECV, - ("Updating QPN for MAC: %02X-%02X-%02X-%02X-%02X-%02X\n", - (*pp_src )->mac.addr[0], (*pp_src )->mac.addr[1], - (*pp_src )->mac.addr[2], (*pp_src )->mac.addr[3], - (*pp_src )->mac.addr[4], (*pp_src )->mac.addr[5]) ); -// (*pp_src)->qpn = p_wc->recv.ud.remote_qp; - } - - if( *pp_src && *pp_dst ) - { - IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_RECV, - ("Recv:\n" - "\tsrc MAC: %02X-%02X-%02X-%02X-%02X-%02X\n" - "\tdst MAC: %02X-%02X-%02X-%02X-%02X-%02X\n", - (*pp_src )->mac.addr[0], (*pp_src )->mac.addr[1], - (*pp_src )->mac.addr[2], (*pp_src )->mac.addr[3], - (*pp_src )->mac.addr[4], (*pp_src )->mac.addr[5], - (*pp_dst )->mac.addr[0], (*pp_dst )->mac.addr[1], - (*pp_dst )->mac.addr[2], (*pp_dst )->mac.addr[3], - (*pp_dst )->mac.addr[4], (*pp_dst )->mac.addr[5]) ); - } - - IPOIB_EXIT( IPOIB_DBG_RECV ); -} - - -static int32_t -__recv_mgr_filter( - IN ipoib_port_t* const p_port, - IN ib_wc_t* const p_done_wc_list, - OUT cl_qlist_t* const p_done_list, - OUT cl_qlist_t* const p_bad_list ) -{ - ipoib_recv_desc_t *p_desc; - ib_wc_t *p_wc; - ipoib_pkt_t *p_ipoib; - eth_pkt_t *p_eth; - ipoib_endpt_t *p_src, *p_dst; - ib_api_status_t status; - uint32_t len; - int32_t recv_cnt = 0; - PERF_DECLARE( GetRecvEndpts ); - PERF_DECLARE( RecvGen ); - PERF_DECLARE( RecvTcp ); - PERF_DECLARE( RecvUdp ); - PERF_DECLARE( RecvDhcp ); - PERF_DECLARE( RecvArp ); - - IPOIB_ENTER( IPOIB_DBG_RECV ); - - for( p_wc = p_done_wc_list; p_wc; p_wc = p_wc->p_next ) - { - CL_ASSERT( p_wc->status != IB_WCS_SUCCESS || p_wc->wc_type == IB_WC_RECV ); - p_desc = (ipoib_recv_desc_t*)(uintn_t)p_wc->wr_id; - recv_cnt++; - - if( p_wc->status != IB_WCS_SUCCESS ) - { - if( p_wc->status != IB_WCS_WR_FLUSHED_ERR ) - { - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed completion %s (vendor specific %#x)\n", - p_port->p_adapter->p_ifc->get_wc_status_str( p_wc->status ), - (int)p_wc->vendor_specific) ); - ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_ERROR, 0, 0 ); - } - else - { - IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_RECV, - ("Flushed completion %s\n", - p_port->p_adapter->p_ifc->get_wc_status_str( p_wc->status )) ); - ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_DROPPED, 0, 0 ); - } - cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item ); - /* Dereference the port object on behalf of the failed receive. */ - ipoib_port_deref( p_port, ref_failed_recv_wc ); - continue; - } - - len = p_wc->length - sizeof(ib_grh_t); - - if( len < sizeof(ipoib_hdr_t) ) - { - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Received ETH packet < min size\n") ); - ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_ERROR, 0, 0 ); - cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item ); - ipoib_port_deref( p_port, ref_recv_inv_len ); - continue; - } - - if((len - sizeof(ipoib_hdr_t)) > p_port->p_adapter->params.payload_mtu) - { - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Received ETH packet len %d > payload MTU (%d)\n", - (len - sizeof(ipoib_hdr_t)), - p_port->p_adapter->params.payload_mtu) ); - ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_ERROR, 0, 0 ); - cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item ); - ipoib_port_deref( p_port, ref_recv_inv_len ); - continue; - - } - /* Successful completion. Get the receive information. */ - p_desc->ndis_csum.Value = ( ( p_wc->recv.ud.recv_opt & IB_RECV_OPT_CSUM_MASK ) >> 8 ); - p_desc->len = len + 14 - 4 ; - cl_perf_start( GetRecvEndpts ); - __recv_get_endpts( p_port, p_desc, p_wc, &p_src, &p_dst ); - cl_perf_stop( &p_port->p_adapter->perf, GetRecvEndpts ); - -#if IPOIB_INLINE_RECV - p_ipoib = &p_desc->buf.ib.pkt; - p_eth = &p_desc->buf.eth.pkt; -#else /* IPOIB_INLINE_RECV */ - p_ipoib = &p_desc->p_buf->ib.pkt; - p_eth = &p_desc->p_buf->eth.pkt; -#endif /*IPOIB_INLINE_RECV */ - - if( p_src ) - { - /* Don't report loopback traffic - we requested SW loopback. */ - if( !cl_memcmp( &p_port->p_adapter->params.conf_mac, - &p_src->mac, sizeof(p_port->p_adapter->params.conf_mac) ) ) - { - /* - * "This is not the packet you're looking for" - don't update - * receive statistics, the packet never happened. - */ - cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item ); - /* Dereference the port object on behalf of the failed recv. */ - ipoib_port_deref( p_port, ref_recv_loopback ); - continue; - } - } - - switch( p_ipoib->hdr.type ) - { - case ETH_PROT_TYPE_IP: - if( len < (sizeof(ipoib_hdr_t) + sizeof(ip_hdr_t)) ) - { - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Received IP packet < min size\n") ); - status = IB_INVALID_SETTING; - break; - } - - if( p_ipoib->type.ip.hdr.offset || - p_ipoib->type.ip.hdr.prot != IP_PROT_UDP ) - { - /* Unfiltered. Setup the ethernet header and report. */ - cl_perf_start( RecvTcp ); - status = __recv_gen( p_ipoib, p_eth, p_src, p_dst ); - cl_perf_stop( &p_port->p_adapter->perf, RecvTcp ); - break; - } - - /* First packet of a UDP transfer. */ - if( len < - (sizeof(ipoib_hdr_t) + sizeof(ip_hdr_t) + sizeof(udp_hdr_t)) ) - { - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Received UDP packet < min size\n") ); - status = IB_INVALID_SETTING; - break; - } - - /* Check if DHCP conversion is required. */ - if( (p_ipoib->type.ip.prot.udp.hdr.dst_port == DHCP_PORT_SERVER && - p_ipoib->type.ip.prot.udp.hdr.src_port == DHCP_PORT_CLIENT) || - (p_ipoib->type.ip.prot.udp.hdr.dst_port == DHCP_PORT_CLIENT && - p_ipoib->type.ip.prot.udp.hdr.src_port == DHCP_PORT_SERVER) ) - { - if( len < (sizeof(ipoib_hdr_t) + sizeof(ip_hdr_t) + - sizeof(udp_hdr_t) + DHCP_MIN_SIZE) ) - { - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Received DHCP < min size\n") ); - status = IB_INVALID_SETTING; - break; - } - if ((p_ipoib->type.ip.hdr.ver_hl & 0x0f) != 5 ) { - // If there are IP options in this message, we are in trouble in any case - status = IB_INVALID_SETTING; - break; - } - /* UDP packet with BOOTP ports in src/dst port numbers. */ - cl_perf_start( RecvDhcp ); - status = __recv_dhcp( p_port, p_ipoib, p_eth, p_src, p_dst ); - cl_perf_stop( &p_port->p_adapter->perf, RecvDhcp ); - } - else - { - /* Unfiltered. Setup the ethernet header and report. */ - cl_perf_start( RecvUdp ); - status = __recv_gen( p_ipoib, p_eth, p_src, p_dst ); - cl_perf_stop( &p_port->p_adapter->perf, RecvUdp ); - } - break; - - case ETH_PROT_TYPE_ARP: - if( len < (sizeof(ipoib_hdr_t) + sizeof(ipoib_arp_pkt_t)) ) - { - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Received ARP < min size\n") ); - status = IB_INVALID_SETTING; - break; - } - cl_perf_start( RecvArp ); - status = __recv_arp( p_port, p_wc, p_ipoib, p_eth, &p_src, p_dst ); - cl_perf_stop( &p_port->p_adapter->perf, RecvArp ); - len = sizeof(ipoib_hdr_t) + sizeof(arp_pkt_t); - break; - - default: - /* Unfiltered. Setup the ethernet header and report. */ - cl_perf_start( RecvGen ); - status = __recv_gen( p_ipoib, p_eth, p_src, p_dst ); - cl_perf_stop( &p_port->p_adapter->perf, RecvGen ); - } - - if( status != IB_SUCCESS ) - { - /* Update stats. */ - ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_ERROR, 0, 0 ); - cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item ); - /* Dereference the port object on behalf of the failed receive. */ - ipoib_port_deref( p_port, ref_recv_filter ); - } - else - { - ip_stat_sel_t ip_stat; - p_desc->len = - len + sizeof(eth_hdr_t) - sizeof(ipoib_hdr_t); - if( p_dst->h_mcast) - { - if( p_dst->dgid.multicast.raw_group_id[10] == 0xFF && - p_dst->dgid.multicast.raw_group_id[11] == 0xFF && - p_dst->dgid.multicast.raw_group_id[12] == 0xFF && - p_dst->dgid.multicast.raw_group_id[13] == 0xFF ) - { - p_desc->type = PKT_TYPE_BCAST; - ip_stat = IP_STAT_BCAST_BYTES; - } - else - { - p_desc->type = PKT_TYPE_MCAST; - ip_stat = IP_STAT_MCAST_BYTES; - } - } - else - { - p_desc->type = PKT_TYPE_UCAST; - ip_stat = IP_STAT_UCAST_BYTES; - - } - cl_qlist_insert_tail( p_done_list, &p_desc->item.list_item ); - ipoib_inc_recv_stat( p_port->p_adapter, ip_stat, len, 1 ); - } - } - - IPOIB_EXIT( IPOIB_DBG_RECV ); - return recv_cnt; -} - - -static ib_api_status_t -__recv_gen( - IN const ipoib_pkt_t* const p_ipoib, - OUT eth_pkt_t* const p_eth, - IN ipoib_endpt_t* const p_src, - IN ipoib_endpt_t* const p_dst ) -{ - IPOIB_ENTER( IPOIB_DBG_RECV ); - - if( !p_src || !p_dst ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Received packet with no matching endpoints.\n") ); - return IB_NOT_DONE; - } - - /* - * Fill in the ethernet header. Note that doing so will overwrite - * the IPoIB header, so start by moving the information from the IPoIB - * header. - */ - p_eth->hdr.type = p_ipoib->hdr.type; - p_eth->hdr.src = p_src->mac; - p_eth->hdr.dst = p_dst->mac; - - if ( p_eth->hdr.dst.addr[0] == 1 && - p_eth->hdr.type == ETH_PROT_TYPE_IP && - p_eth->hdr.dst.addr[2] == 0x5E) - { - p_eth->hdr.dst.addr[1] = 0; - p_eth->hdr.dst.addr[3] = p_eth->hdr.dst.addr[3] & 0x7f; - } - if (p_dst->h_mcast) - p_dst->is_in_use = TRUE; - - IPOIB_EXIT( IPOIB_DBG_RECV ); - return IB_SUCCESS; -} - - -static ib_api_status_t -__recv_dhcp( - IN ipoib_port_t* const p_port, - IN const ipoib_pkt_t* const p_ipoib, - OUT eth_pkt_t* const p_eth, - IN ipoib_endpt_t* const p_src, - IN ipoib_endpt_t* const p_dst ) -{ - ib_api_status_t status; - dhcp_pkt_t *p_dhcp; - uint8_t *p_option; - uint8_t *p_cid = NULL; - ib_gid_t gid; - uint8_t msg = 0; - - IPOIB_ENTER( IPOIB_DBG_RECV ); - - UNUSED_PARAM( p_port ); - - /* Create the ethernet header. */ - status = __recv_gen( p_ipoib, p_eth, p_src, p_dst ); - if( status != IB_SUCCESS ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("__recv_gen returned %s.\n", - p_port->p_adapter->p_ifc->get_err_str( status )) ); - return status; - } - - /* Fixup the payload. */ - p_dhcp = &p_eth->type.ip.prot.udp.dhcp; - if( p_dhcp->op != DHCP_REQUEST && p_dhcp->op != DHCP_REPLY ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Invalid DHCP op code.\n") ); - return IB_INVALID_SETTING; - } - - /* - * Find the client identifier option, making sure to skip - * the "magic cookie". - */ - p_option = &p_dhcp->options[0]; - if ( *(uint32_t *)p_option != DHCP_COOKIE ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("DHCP cookie corrupted.\n") ); - return IB_INVALID_PARAMETER; - } - - p_option = &p_dhcp->options[4]; - while( *p_option != DHCP_OPT_END && p_option < &p_dhcp->options[312] ) - { - switch( *p_option ) - { - case DHCP_OPT_PAD: - p_option++; - break; - - case DHCP_OPT_MSG: - msg = p_option[2]; - p_option += 3; - break; - - case DHCP_OPT_CLIENT_ID: - p_cid = p_option; - /* Fall through. */ - - default: - /* - * All other options have a length byte following the option code. - * Offset by the length to get to the next option. - */ - p_option += (p_option[1] + 2); - } - } - - switch( msg ) - { - /* message from client */ - case DHCPDISCOVER: - case DHCPREQUEST: - case DHCPDECLINE: - case DHCPRELEASE: - case DHCPINFORM: - if( !p_cid ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed to find required Client-identifier option.\n") ); - return IB_INVALID_SETTING; - } - if( p_dhcp->htype != DHCP_HW_TYPE_IB ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Invalid hardware address type.\n") ); - return IB_INVALID_SETTING; - } - break; - /* message from DHCP server */ - case DHCPOFFER: - case DHCPACK: - case DHCPNAK: - break; - - default: - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Invalide message type.\n") ); - return IB_INVALID_PARAMETER; - } - p_eth->type.ip.prot.udp.hdr.chksum = 0; - p_dhcp->htype = DHCP_HW_TYPE_ETH; - p_dhcp->hlen = HW_ADDR_LEN; - - if( p_cid ) /* from client */ - { - /* Validate that the length and type of the option is as required. */ - if( p_cid[1] != 21 ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Client-identifier length not 21 as required.\n") ); - return IB_INVALID_SETTING; - } - if( p_cid[2] != DHCP_HW_TYPE_IB ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Client-identifier type is wrong.\n") ); - return IB_INVALID_SETTING; - } - /* - * Copy the GID value from the option so that we can make aligned - * accesses to the contents. - * Recover CID to standard type. - */ - cl_memcpy( &gid, &p_cid[7], sizeof(ib_gid_t) ); - p_cid[1] = HW_ADDR_LEN +1;// CID length - p_cid[2] = DHCP_HW_TYPE_ETH;// CID type - status = ipoib_mac_from_guid( gid.unicast.interface_id, p_port->p_adapter->params.guid_mask, (mac_addr_t*)&p_cid[3] ); - if (status == IB_INVALID_GUID_MASK) - { - IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_ERROR, - ("Invalid GUID mask received, rejecting it") ); - ipoib_create_log(p_port->p_adapter->h_adapter, GUID_MASK_LOG_INDEX, EVENT_IPOIB_WRONG_PARAMETER_WRN); - status = IB_SUCCESS; - } - p_cid[HW_ADDR_LEN + 3] = DHCP_OPT_END; //terminate tag - } - IPOIB_EXIT( IPOIB_DBG_RECV ); - return status; -} - - -static ib_api_status_t -__recv_arp( - IN ipoib_port_t* const p_port, - IN ib_wc_t* const p_wc, - IN const ipoib_pkt_t* const p_ipoib, - OUT eth_pkt_t* const p_eth, - IN ipoib_endpt_t** const pp_src, - IN ipoib_endpt_t* const p_dst ) -{ - ib_api_status_t status; - arp_pkt_t *p_arp; - const ipoib_arp_pkt_t *p_ib_arp; - ib_gid_t gid; - mac_addr_t mac; - ipoib_hw_addr_t null_hw = {0}; - uint8_t cm_capable = 0; - - IPOIB_ENTER( IPOIB_DBG_RECV ); - - if( !p_dst ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Unknown destination endpoint\n") ); - return IB_INVALID_SETTING; - } - - p_ib_arp = &p_ipoib->type.arp; - p_arp = &p_eth->type.arp; - - if( p_ib_arp->hw_type != ARP_HW_TYPE_IB ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ARP hardware type is not IB\n") ); - return IB_INVALID_SETTING; - } - - if( p_ib_arp->hw_size != sizeof(ipoib_hw_addr_t) ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ARP hardware address size is not sizeof(ipoib_hw_addr_t)\n") ); - return IB_INVALID_SETTING; - } - - if( p_ib_arp->prot_type != ETH_PROT_TYPE_IP ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ARP protocal type not IP\n") ); - return IB_INVALID_SETTING; - } - - cm_capable = ipoib_addr_get_flags( &p_ib_arp->src_hw ); - - /* - * If we don't have a source, lookup the endpoint specified in the payload. - */ - if( !*pp_src ) - *pp_src = __endpt_mgr_get_by_gid( p_port, &p_ib_arp->src_hw.gid ); - - /* - * If the endpoint exists for the GID, make sure - * the dlid and qpn match the arp. - */ - if( *pp_src ) - { - if( cl_memcmp( &(*pp_src)->dgid, &p_ib_arp->src_hw.gid, - sizeof(ib_gid_t) ) ) - { - /* - * GIDs for the endpoint are different. The ARP must - * have been proxied. Dereference it. - */ - *pp_src = NULL; - } - else if( (*pp_src)->dlid && - (*pp_src)->dlid != p_wc->recv.ud.remote_lid ) - { - /* Out of date! Destroy the endpoint and replace it. */ - __endpt_mgr_remove( p_port, *pp_src ); - *pp_src = NULL; - } - else if ( ! ((*pp_src)->dlid)) { - /* Out of date! Destroy the endpoint and replace it. */ - __endpt_mgr_remove( p_port, *pp_src ); - *pp_src = NULL; - } - else if( ipoib_is_voltaire_router_gid( &(*pp_src)->dgid ) ) - { - if( (*pp_src)->qpn != ipoib_addr_get_qpn( &p_ib_arp->src_hw ) && - p_wc->recv.ud.remote_qp != ipoib_addr_get_qpn( &p_ib_arp->src_hw ) ) - { - /* Out of date! Destroy the endpoint and replace it. */ - __endpt_mgr_remove( p_port, *pp_src ); - *pp_src = NULL; - } - } - else if( (*pp_src)->qpn != p_wc->recv.ud.remote_qp ) - { - /* Out of date! Destroy the endpoint and replace it. */ - __endpt_mgr_remove( p_port, *pp_src ); - *pp_src = NULL; - } - } - - /* Do we need to create an endpoint for this GID? */ - if( !*pp_src ) - { - /* Copy the src GID to allow aligned access */ - cl_memcpy( &gid, &p_ib_arp->src_hw.gid, sizeof(ib_gid_t) ); - status = ipoib_mac_from_guid( gid.unicast.interface_id, p_port->p_adapter->params.guid_mask, &mac ); - if (status == IB_INVALID_GUID_MASK) - { - IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_ERROR, - ("Invalid GUID mask received, rejecting it") ); - ipoib_create_log(p_port->p_adapter->h_adapter, GUID_MASK_LOG_INDEX, EVENT_IPOIB_WRONG_PARAMETER_WRN); - } - else if( status != IB_SUCCESS ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ipoib_mac_from_guid returned %s\n", - p_port->p_adapter->p_ifc->get_err_str( status )) ); - return status; - } - /* - * Create the endpoint. - */ - *pp_src = ipoib_endpt_create( &p_ib_arp->src_hw.gid, - p_wc->recv.ud.remote_lid, ipoib_addr_get_qpn( &p_ib_arp->src_hw ) ); - - if( !*pp_src ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ipoib_endpt_create failed\n") ); - return status; - } - - cl_obj_lock( &p_port->obj ); - status = __endpt_mgr_insert( p_port, mac, *pp_src ); - if( status != IB_SUCCESS ) - { - cl_obj_unlock( &p_port->obj ); - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("__endpt_mgr_insert return %s \n", - p_port->p_adapter->p_ifc->get_err_str( status )) ); - return status; - } - - cl_obj_unlock( &p_port->obj ); - } - - (*pp_src)->cm_flag = cm_capable; - - CL_ASSERT( !cl_memcmp( - &(*pp_src)->dgid, &p_ib_arp->src_hw.gid, sizeof(ib_gid_t) ) ); - CL_ASSERT( ipoib_is_voltaire_router_gid( &(*pp_src)->dgid ) || - (*pp_src)->qpn == ipoib_addr_get_qpn( &p_ib_arp->src_hw ) ); -#if 0 - if( p_port->p_adapter->params.cm_enabled && - p_ib_arp->op == ARP_OP_REQ && - cm_capable == IPOIB_CM_FLAG_RC ) - { - /* if we've got ARP request and RC flag is set, - save SID for connect REQ to be sent in ARP reply - when requestor's path get resolved */ - if( endpt_cm_get_state( (*pp_src) ) == IPOIB_CM_DISCONNECTED ) - { - (*pp_src)->cm_flag = cm_capable; - ipoib_addr_set_sid( - &(*pp_src)->conn.service_id, - ipoib_addr_get_qpn( &p_ib_arp->src_hw ) ); - } - } -#endif -#if 0 //DBG - if( p_port->p_adapter->params.cm_enabled ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, - (" ARP %s from ENDPT[%p] state %d CM cap: %d QPN: %#x MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", - ((p_ib_arp->op == ARP_OP_REQ )? "REQUEST" : "REPLY"), - *pp_src, endpt_cm_get_state( *pp_src ), - ((cm_capable == IPOIB_CM_FLAG_RC)? 1: 0), - cl_ntoh32( ipoib_addr_get_qpn( &p_ib_arp->src_hw ) ), - (*pp_src)->mac.addr[0], (*pp_src)->mac.addr[1], - (*pp_src)->mac.addr[2], (*pp_src)->mac.addr[3], - (*pp_src)->mac.addr[4], (*pp_src)->mac.addr[5] )); - } -#endif - - /* Now swizzle the data. */ - p_arp->hw_type = ARP_HW_TYPE_ETH; - p_arp->hw_size = sizeof(mac_addr_t); - p_arp->src_hw = (*pp_src)->mac; - p_arp->src_ip = p_ib_arp->src_ip; - - if( cl_memcmp( &p_ib_arp->dst_hw, &null_hw, sizeof(ipoib_hw_addr_t) ) ) - { - if( cl_memcmp( &p_dst->dgid, &p_ib_arp->dst_hw.gid, sizeof(ib_gid_t) ) ) - { - /* - * We received bcast ARP packet that means - * remote port lets everyone know it was changed IP/MAC - * or just activated - */ - - /* Guy: TODO: Check why this check fails in case of Voltaire IPR */ - - if ( !ipoib_is_voltaire_router_gid( &(*pp_src)->dgid ) && - !ib_gid_is_multicast( (const ib_gid_t*)&p_dst->dgid ) ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ARP: is not ARP MCAST\n") ); - return IB_INVALID_SETTING; - } - - p_arp->dst_hw = p_port->p_local_endpt->mac; - p_dst->mac = p_port->p_local_endpt->mac; - /* - * we don't care what receiver ip addr is, - * as long as OS' ARP table is global ??? - */ - p_arp->dst_ip = (net32_t)0; - } - else /* we've got reply to our ARP request */ - { - p_arp->dst_hw = p_dst->mac; - p_arp->dst_ip = p_ib_arp->dst_ip; - CL_ASSERT( p_dst->qpn == ipoib_addr_get_qpn( &p_ib_arp->dst_hw ) ); - } - } - else /* we got ARP reqeust */ - { - cl_memclr( &p_arp->dst_hw, sizeof(mac_addr_t) ); - p_arp->dst_ip = p_ib_arp->dst_ip; - } - - /* - * Create the ethernet header. Note that this is done last so that - * we have a chance to create a new endpoint. - */ - status = __recv_gen( p_ipoib, p_eth, *pp_src, p_dst ); - if( status != IB_SUCCESS ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("__recv_gen returned %s.\n", - p_port->p_adapter->p_ifc->get_err_str( status )) ); - return status; - } - - IPOIB_EXIT( IPOIB_DBG_RECV ); - return IB_SUCCESS; -} - - -static ib_api_status_t -__recv_mgr_prepare_pkt( - IN ipoib_port_t* const p_port, - IN ipoib_recv_desc_t* const p_desc, - OUT NET_BUFFER_LIST** const pp_net_buffer_list ) -{ - NDIS_STATUS status; - uint32_t pkt_filter; - ip_stat_sel_t type; - //NDIS60 - NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO chksum; - //NDIS_TCP_IP_CHECKSUM_PACKET_INFO chksum; - - PERF_DECLARE( GetNdisPkt ); - - IPOIB_ENTER( IPOIB_DBG_RECV ); - - pkt_filter = p_port->p_adapter->packet_filter; - /* Check the packet filter. */ - switch( p_desc->type ) - { - default: - case PKT_TYPE_UCAST: - - if( pkt_filter & NDIS_PACKET_TYPE_PROMISCUOUS || - pkt_filter & NDIS_PACKET_TYPE_ALL_FUNCTIONAL || - pkt_filter & NDIS_PACKET_TYPE_SOURCE_ROUTING || - pkt_filter & NDIS_PACKET_TYPE_DIRECTED ) - { - /* OK to report. */ - type = IP_STAT_UCAST_BYTES; - status = NDIS_STATUS_SUCCESS; - IPOIB_PRINT( TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, - ("Received UCAST PKT.\n")); - } - else - { - type = IP_STAT_DROPPED; - status = NDIS_STATUS_FAILURE; - IPOIB_PRINT( TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, - ("Received UCAST PKT with ERROR !!!!\n")); - } - break; - case PKT_TYPE_BCAST: - if( pkt_filter & NDIS_PACKET_TYPE_PROMISCUOUS || - pkt_filter & NDIS_PACKET_TYPE_BROADCAST ) - { - /* OK to report. */ - type = IP_STAT_BCAST_BYTES; - status = NDIS_STATUS_SUCCESS; - IPOIB_PRINT( TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, - ("Received BCAST PKT.\n")); - } - else - { - type = IP_STAT_DROPPED; - status = NDIS_STATUS_FAILURE; - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Received BCAST PKT with ERROR !!!!\n")); - } - break; - case PKT_TYPE_MCAST: - if( pkt_filter & NDIS_PACKET_TYPE_PROMISCUOUS || - pkt_filter & NDIS_PACKET_TYPE_ALL_MULTICAST || - pkt_filter & NDIS_PACKET_TYPE_MULTICAST ) - { - /* OK to report. */ - type = IP_STAT_MCAST_BYTES; - status = NDIS_STATUS_SUCCESS; - IPOIB_PRINT( TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, - ("Received UCAST PKT.\n")); - } - else - { - type = IP_STAT_DROPPED; - status = NDIS_STATUS_FAILURE; - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Received MCAST PKT with ERROR !!!!\n")); - } - break; - } - - if( status != NDIS_STATUS_SUCCESS ) - { - ipoib_inc_recv_stat( p_port->p_adapter, type, 0, 0 ); - /* Return the receive descriptor to the pool. */ - __buf_mgr_put_recv( p_port, p_desc, NULL ); - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_RECV, - ("Packet filter doesn't match receive. Dropping.\n") ); - /* - * Return IB_NOT_DONE since the packet has been completed, - * but has not consumed an array entry. - */ - return IB_NOT_DONE; - } - - cl_perf_start( GetNdisPkt ); - *pp_net_buffer_list = __buf_mgr_get_ndis_pkt( p_port, p_desc ); - cl_perf_stop( &p_port->p_adapter->perf, GetNdisPkt ); - if( !*pp_net_buffer_list ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("__buf_mgr_get_ndis_pkt failed\n") ); - return IB_INSUFFICIENT_RESOURCES; - } - - chksum.Value = 0; - -{ - PNET_BUFFER NetBuffer = NET_BUFFER_LIST_FIRST_NB(*pp_net_buffer_list); - NET_BUFFER_DATA_LENGTH(NetBuffer) = p_desc->len; -} - - switch( p_port->p_adapter->params.recv_chksum_offload ) - { - default: - CL_ASSERT( FALSE ); - case CSUM_DISABLED: - //NDIS60 - //NDIS_PER_PACKET_INFO_FROM_PACKET( *pp_packet, TcpIpChecksumPacketInfo ) = - //(void*)(uintn_t)chksum.Value; - NET_BUFFER_LIST_INFO(*pp_net_buffer_list, TcpIpChecksumNetBufferListInfo) = - (void*)(uintn_t)chksum.Value; - break; - case CSUM_ENABLED: - /* Get the checksums directly from packet information. */ - /* In this case, no one of cheksum's cat get false value */ - /* If hardware checksum failed or wasn't calculated, NDIS will recalculate it again */ - //NDIS60 - //NDIS_PER_PACKET_INFO_FROM_PACKET( *pp_packet, TcpIpChecksumPacketInfo ) = - NET_BUFFER_LIST_INFO(*pp_net_buffer_list, TcpIpChecksumNetBufferListInfo) = - (void*)(uintn_t)(p_desc->ndis_csum.Value); - break; - case CSUM_BYPASS: - /* Flag the checksums as having been calculated. */ - chksum.Receive.TcpChecksumSucceeded = TRUE; - chksum.Receive.UdpChecksumSucceeded = TRUE; - chksum.Receive.IpChecksumSucceeded = TRUE; - //NDIS60 - //NDIS_PER_PACKET_INFO_FROM_PACKET( *pp_packet, TcpIpChecksumPacketInfo ) = - NET_BUFFER_LIST_INFO(*pp_net_buffer_list, TcpIpChecksumNetBufferListInfo) = - (void*)(uintn_t)chksum.Value; - break; - } - ipoib_inc_recv_stat( p_port->p_adapter, type, p_desc->len, 1 ); - - IPOIB_EXIT( IPOIB_DBG_RECV ); - return IB_SUCCESS; -} - - -static uint32_t -__recv_mgr_build_pkt_array( - IN ipoib_port_t* const p_port, - IN int32_t shortage, - OUT cl_qlist_t* const p_done_list, - OUT int32_t* const p_discarded ) -{ - cl_list_item_t *p_item; - ipoib_recv_desc_t *p_desc; - uint32_t i = 0; - ib_api_status_t status; - PERF_DECLARE( PreparePkt ); - - IPOIB_ENTER( IPOIB_DBG_RECV ); - - *p_discarded = 0; - - /* Move any existing receives to the head to preserve ordering. */ - cl_qlist_insert_list_head( p_done_list, &p_port->recv_mgr.done_list ); - p_item = cl_qlist_remove_head( p_done_list ); - while( p_item != cl_qlist_end( p_done_list ) ) - { - p_desc = (ipoib_recv_desc_t*)p_item; - - cl_perf_start( PreparePkt ); - status = __recv_mgr_prepare_pkt( p_port, p_desc, - &p_port->recv_mgr.recv_pkt_array[i] ); - cl_perf_stop( &p_port->p_adapter->perf, PreparePkt ); - if( status == IB_SUCCESS ) - { - CL_ASSERT( p_port->recv_mgr.recv_pkt_array[i] ); - if( shortage-- > 0 ) - { - NET_BUFFER_LIST_STATUS(p_port->recv_mgr.recv_pkt_array[i])= NDIS_STATUS_RESOURCES; - } - else - { - NET_BUFFER_LIST_STATUS(p_port->recv_mgr.recv_pkt_array[i])= NDIS_STATUS_SUCCESS; - } - i++; - } - else if( status == IB_NOT_DONE ) - { - (*p_discarded)++; - } - else - { - IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_RECV, - ("__recv_mgr_prepare_pkt returned %s\n", - p_port->p_adapter->p_ifc->get_err_str( status )) ); - /* Put all completed receives on the port's done list. */ - cl_qlist_insert_tail( &p_port->recv_mgr.done_list, p_item ); - cl_qlist_insert_list_tail( &p_port->recv_mgr.done_list, p_done_list ); - break; - } - - p_item = cl_qlist_remove_head( p_done_list ); - } - - IPOIB_EXIT( IPOIB_DBG_RECV ); - return i; -} - - - - -/****************************************************************************** -* -* Send manager implementation. -* -******************************************************************************/ -static void -__send_mgr_construct( - IN ipoib_port_t* const p_port ) -{ - IPOIB_ENTER( IPOIB_DBG_SEND ); - p_port->send_mgr.depth = 0; - cl_qlist_init( &p_port->send_mgr.pending_list ); - IPOIB_EXIT( IPOIB_DBG_SEND ); -} - - -static void -__pending_list_destroy( - IN ipoib_port_t* const p_port ) -{ - cl_list_item_t *p_item; - NET_BUFFER_LIST **pp_net_buffer_list, *p_head; - - p_head = NULL; - cl_spinlock_acquire( &p_port->send_lock ); - /* Complete any pending packets. */ - pp_net_buffer_list = &p_head; - for( p_item = cl_qlist_remove_head( &p_port->send_mgr.pending_list ); - p_item != cl_qlist_end( &p_port->send_mgr.pending_list ); - p_item = cl_qlist_remove_head( &p_port->send_mgr.pending_list ) ) - { - *pp_net_buffer_list = IPOIB_PACKET_FROM_LIST_ITEM( p_item ); - NET_BUFFER_LIST_STATUS(*pp_net_buffer_list) = NDIS_STATUS_RESET_IN_PROGRESS; - pp_net_buffer_list = &(NET_BUFFER_LIST_NEXT_NBL(*pp_net_buffer_list)); - } - cl_spinlock_release( &p_port->send_lock ); - if(p_head) - NdisMSendNetBufferListsComplete( - p_port->p_adapter->h_adapter, - p_head, - 0); -} - -static void -__send_mgr_destroy( - IN ipoib_port_t* const p_port ) -{ - IPOIB_ENTER( IPOIB_DBG_SEND ); - __pending_list_destroy(p_port); - - IPOIB_EXIT( IPOIB_DBG_SEND ); -} - - -static NDIS_STATUS -__send_mgr_filter( - IN ipoib_port_t* const p_port, - IN const eth_hdr_t* const p_eth_hdr, - IN MDL* const p_mdl, - IN size_t buf_len, - IN SCATTER_GATHER_LIST *p_sgl, - IN OUT ipoib_send_desc_t* const p_desc ) -{ - NDIS_STATUS status; - - PERF_DECLARE( FilterIp ); - PERF_DECLARE( FilterArp ); - PERF_DECLARE( SendGen ); - - IPOIB_ENTER( IPOIB_DBG_SEND ); - - /* - * We already checked the ethernet header length, so we know it's safe - * to decrement the buf_len without underflowing. - */ - buf_len -= sizeof(eth_hdr_t); - - switch( p_eth_hdr->type ) - { - case ETH_PROT_TYPE_IP: - cl_perf_start( FilterIp ); - status = __send_mgr_filter_ip( - p_port, p_eth_hdr, p_mdl, buf_len, p_sgl, p_desc); - cl_perf_stop( &p_port->p_adapter->perf, FilterIp ); - break; - - case ETH_PROT_TYPE_ARP: - cl_perf_start( FilterArp ); - status = __send_mgr_filter_arp( - p_port, p_eth_hdr, p_mdl, buf_len, p_desc ); - p_desc->send_dir = SEND_UD_QP; - cl_perf_stop( &p_port->p_adapter->perf, FilterArp ); - break; - - default: - /* - * The IPoIB spec doesn't define how to send non IP or ARP packets. - * Just send the payload and hope for the best. - */ - - p_desc->send_dir = SEND_UD_QP; - cl_perf_start( SendGen ); - status = __send_gen( p_port, p_desc, p_sgl, 0 ); - cl_perf_stop( &p_port->p_adapter->perf, SendGen ); - break; - } - - IPOIB_EXIT( IPOIB_DBG_SEND ); - return status; -} - - -static NDIS_STATUS -__send_copy( - IN ipoib_port_t* const p_port, - IN ipoib_send_desc_t* const p_desc ) -{ - NET_BUFFER_LIST *p_net_buffer_list; - NET_BUFFER *p_netbuffer; - MDL *p_mdl; - UINT tot_len = 0; - - IPOIB_ENTER( IPOIB_DBG_SEND ); - - UNREFERENCED_PARAMETER(p_port); - UNREFERENCED_PARAMETER(p_desc); - - p_desc->p_buf = - NdisAllocateFromNPagedLookasideList( &p_port->buf_mgr.send_buf_list ); - if( !p_desc->p_buf ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed to allocate buffer for packet copy.\n") ); - return NDIS_STATUS_RESOURCES; - } - - p_mdl = NdisAllocateMdl(p_port->p_adapter->h_adapter, - p_desc->p_buf, - p_port->p_adapter->params.xfer_block_size ); - if( !p_mdl ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed to allocate MDL\n") ); - return NDIS_STATUS_RESOURCES; - } - - p_net_buffer_list = NdisAllocateNetBufferAndNetBufferList( - p_port->buf_mgr.h_send_buf_pool, - 0, - 0, - p_mdl, - 0, - 0); - - if( !p_net_buffer_list ) - { - NdisFreeMdl(p_mdl); - IPOIB_PRINT_EXIT( TRACE_LEVEL_WARNING, IPOIB_DBG_SEND, - ("Failed to allocate NDIS_PACKET for copy.\n") ); - return NDIS_STATUS_RESOURCES; - } - - for (p_netbuffer = NET_BUFFER_LIST_FIRST_NB(p_net_buffer_list); - p_netbuffer != NULL; - p_netbuffer = NET_BUFFER_NEXT_NB(p_netbuffer)) - { - tot_len +=NET_BUFFER_DATA_LENGTH(p_netbuffer); - } - - /* Setup the work request. */ - p_desc->send_wr[0].local_ds[1].vaddr = cl_get_physaddr( - ((uint8_t*)p_desc->p_buf) + sizeof(eth_hdr_t) ); - p_desc->send_wr[0].local_ds[1].length = tot_len - sizeof(eth_hdr_t); - p_desc->send_wr[0].local_ds[1].lkey = p_port->ib_mgr.lkey; - p_desc->send_wr[0].wr.num_ds = 2; - - /* Free our temp packet now that the data is copied. */ - NdisFreeMdl(p_mdl); - NdisFreeNetBufferList(p_net_buffer_list); - - IPOIB_EXIT( IPOIB_DBG_SEND ); - return NDIS_STATUS_SUCCESS; -} - -static inline NDIS_STATUS -__send_mgr_get_eth_hdr( - IN PNET_BUFFER p_net_buffer, - OUT MDL** const pp_mdl, - OUT eth_hdr_t** const pp_eth_hdr, - OUT UINT* p_mdl_len) -{ - PUCHAR p_head = NULL; - IPOIB_ENTER( IPOIB_DBG_SEND ); - - *pp_mdl = NET_BUFFER_FIRST_MDL(p_net_buffer); - - NdisQueryMdl(*pp_mdl,&p_head,p_mdl_len,NormalPagePriority); - if( ! p_head ) - { - /* Failed to get first buffer. */ - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("NdisQueryMdl failed.\n") ); - return NDIS_STATUS_FAILURE; - } - - if( *p_mdl_len < sizeof(eth_hdr_t) ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("First buffer in packet smaller than eth_hdr_t: %d.\n", - *p_mdl_len) ); - return NDIS_STATUS_BUFFER_TOO_SHORT; - } - - *pp_eth_hdr = (eth_hdr_t*)(p_head + NET_BUFFER_CURRENT_MDL_OFFSET(p_net_buffer)); - - IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_SEND, - ("Ethernet header:\n" - "\tsrc MAC: %02X-%02X-%02X-%02X-%02X-%02X\n" - "\tdst MAC: %02X-%02X-%02X-%02X-%02X-%02X\n" - "\tprotocol type: %04X\n", - (*pp_eth_hdr)->src.addr[0], (*pp_eth_hdr)->src.addr[1], - (*pp_eth_hdr)->src.addr[2], (*pp_eth_hdr)->src.addr[3], - (*pp_eth_hdr)->src.addr[4], (*pp_eth_hdr)->src.addr[5], - (*pp_eth_hdr)->dst.addr[0], (*pp_eth_hdr)->dst.addr[1], - (*pp_eth_hdr)->dst.addr[2], (*pp_eth_hdr)->dst.addr[3], - (*pp_eth_hdr)->dst.addr[4], (*pp_eth_hdr)->dst.addr[5], - cl_ntoh16( (*pp_eth_hdr)->type )) ); - - return NDIS_STATUS_SUCCESS; -} - - -#if !IPOIB_USE_DMA -/* Send using the MDL's page information rather than the SGL. */ -static ib_api_status_t -__send_gen( - IN ipoib_port_t* const p_port, - IN ipoib_send_desc_t* const p_desc ) -{ - uint32_t i, j = 1; - ULONG offset; - MDL *p_mdl; - UINT num_pages, tot_len; - ULONG buf_len; - PPFN_NUMBER page_array; - boolean_t hdr_done = FALSE; - ib_api_status_t status; - PNET_BUFFER p_net_buf; - - IPOIB_ENTER( IPOIB_DBG_SEND ); - p_net_buf = NET_BUFFER_LIST_FIRST_NB(p_desc->p_netbuf_list); - NdisQueryBuffer( p_net_buf, &num_pages, NULL, &p_mdl, - &tot_len ); - - if( !p_mdl ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("No buffers associated with packet.\n") ); - return IB_ERROR; - } - - /* Remember that one of the DS entries is reserved for the IPoIB header. */ - if( num_pages >= MAX_SEND_SGE ) - { - IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_SEND, - ("Too many buffers to fit in WR ds_array. Copying data.\n") ); - status = __send_copy( p_port, p_desc ); - IPOIB_EXIT( IPOIB_DBG_SEND ); - return status; - } - - CL_ASSERT( tot_len > sizeof(eth_hdr_t) ); - CL_ASSERT( tot_len <= p_port->p_adapter->params.xfer_block_size ); - /* - * Assume that the ethernet header is always fully contained - * in the first page of the first MDL. This makes for much - * simpler code. - */ - offset = MmGetMdlByteOffset( p_mdl ) + sizeof(eth_hdr_t); - CL_ASSERT( offset <= PAGE_SIZE ); - - while( tot_len ) - { - buf_len = MmGetMdlByteCount( p_mdl ); - page_array = MmGetMdlPfnArray( p_mdl ); - CL_ASSERT( page_array ); - i = 0; - if( !hdr_done ) - { - CL_ASSERT( buf_len >= sizeof(eth_hdr_t) ); - /* Skip the ethernet header. */ - buf_len -= sizeof(eth_hdr_t); - CL_ASSERT( buf_len <= p_port->p_adapter->params.payload_mtu ); - if( buf_len ) - { - /* The ethernet header is a subset of this MDL. */ - CL_ASSERT( i == 0 ); - if( offset < PAGE_SIZE ) - { - p_desc->send_wr[0].local_ds[j].lkey = p_port->ib_mgr.lkey; - p_desc->send_wr[0].local_ds[j].vaddr = (page_array[i] << PAGE_SHIFT); - /* Add the byte offset since we're on the 1st page. */ - p_desc->send_wr[0].local_ds[j].vaddr += offset; - if( offset + buf_len > PAGE_SIZE ) - { - p_desc->send_wr[0].local_ds[j].length = PAGE_SIZE - offset; - buf_len -= p_desc->send_wr[0].local_ds[j].length; - } - else - { - p_desc->send_wr[0].local_ds[j].length = buf_len; - buf_len = 0; - } - /* This data segment is done. Move to the next. */ - j++; - } - /* This page is done. Move to the next. */ - i++; - } - /* Done handling the ethernet header. */ - hdr_done = TRUE; - } - - /* Finish this MDL */ - while( buf_len ) - { - p_desc->send_wr[0].local_ds[j].lkey = p_port->ib_mgr.lkey; - p_desc->send_wr[0].local_ds[j].vaddr = (page_array[i] << PAGE_SHIFT); - /* Add the first page's offset if we're on the first page. */ - if( i == 0 ) - p_desc->send_wr[0].local_ds[j].vaddr += MmGetMdlByteOffset( p_mdl ); - - if( i == 0 && (MmGetMdlByteOffset( p_mdl ) + buf_len) > PAGE_SIZE ) - { - /* Buffers spans pages. */ - p_desc->send_wr[0].local_ds[j].length = - PAGE_SIZE - MmGetMdlByteOffset( p_mdl ); - buf_len -= p_desc->send_wr[0].local_ds[j].length; - /* This page is done. Move to the next. */ - i++; - } - else - { - /* Last page of the buffer. */ - p_desc->send_wr[0].local_ds[j].length = buf_len; - buf_len = 0; - } - /* This data segment is done. Move to the next. */ - j++; - } - - tot_len -= MmGetMdlByteCount( p_mdl ); - if( !tot_len ) - break; - - NdisGetNextBuffer( p_mdl, &p_mdl ); - if( !p_mdl ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed to get next buffer.\n") ); - return IB_ERROR; - } - } - - /* Set the number of data segments. */ - p_desc->send_wr[0].wr.num_ds = j; - - IPOIB_EXIT( IPOIB_DBG_SEND ); - return IB_SUCCESS; -} - -#else - -#if 0 -void -ipoib_process_sg_list1( - IN PDEVICE_OBJECT pDO, - IN PVOID pIrp, - IN PSCATTER_GATHER_LIST p_sgl, - IN PVOID context - ) -{ - int i; - char temp[200]; - for (i = 0 ; i < 1;i++) - temp[i] = 5; -} -#endif - -void -ipoib_process_sg_list( - IN PDEVICE_OBJECT pDO, - IN PVOID pIrp, - IN PSCATTER_GATHER_LIST p_sgl, - IN PVOID context - ) -{ - NDIS_STATUS status; - ipoib_port_t *p_port; - MDL *p_mdl; - eth_hdr_t *p_eth_hdr; - UINT mdl_len; - static ipoib_send_desc_t *p_desc = NULL; - ib_send_wr_t *p_wr_failed; - NET_BUFFER_LIST *p_net_buffer_list; - NET_BUFFER *p_netbuf; - boolean_t from_queue; - ib_api_status_t ib_status; - ULONG complete_flags = 0; - - IPOIB_ENTER( IPOIB_DBG_SEND ); - - UNREFERENCED_PARAMETER(pDO); - UNREFERENCED_PARAMETER(pIrp); - - PERF_DECLARE( SendCopy ); - PERF_DECLARE( BuildSendDesc ); - PERF_DECLARE( GetEthHdr ); - PERF_DECLARE( QueuePacket ); - PERF_DECLARE( SendMgrQueue ); - PERF_DECLARE( PostSend ); - PERF_DECLARE( ProcessFailedSends ); - PERF_DECLARE( GetEndpt ); - - - p_netbuf = (NET_BUFFER*)context; - p_net_buffer_list = (NET_BUFFER_LIST*)IPOIB_NET_BUFFER_LIST_FROM_NETBUFFER(p_netbuf); - p_port = (ipoib_port_t*)IPOIB_PORT_FROM_PACKET(p_net_buffer_list); - NDIS_SET_SEND_COMPLETE_FLAG(complete_flags, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL); - - - cl_spinlock_acquire( &p_port->send_lock ); - if (p_desc == NULL) { - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_SEND, ("Allocating send_desc First Time\n") ); - p_desc = ExAllocatePoolWithTag(NonPagedPool ,sizeof (ipoib_send_desc_t), 'XMXA'); - } - ASSERT(p_desc); - p_desc->p_netbuf_list = p_net_buffer_list; - p_desc->p_endpt = NULL; - p_desc->p_buf = NULL; - p_desc->num_wrs = 1; - - //IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_SEND, - // ("\n*******\nRECEIVED NB= %x with SG= %x\n********\n", p_netbuf, p_sgl) ); - /* Get the ethernet header so we can find the endpoint. */ - cl_perf_start( GetEthHdr ); - status = __send_mgr_get_eth_hdr( - p_netbuf, &p_mdl, &p_eth_hdr, &mdl_len ); - cl_perf_stop( &p_port->p_adapter->perf, GetEthHdr ); - - if( status != NDIS_STATUS_SUCCESS ) - { - cl_perf_start( ProcessFailedSends ); - /* fail net buffer list */ - __process_failed_send( p_port, p_desc, status, complete_flags); - cl_perf_stop( &p_port->p_adapter->perf, ProcessFailedSends ); - goto send_end; - } - //from_queue = (boolean_t)(IPOIB_FROM_QUEUE(p_netbuf) == (void*)1); - from_queue = (boolean_t)(IPOIB_FROM_QUEUE(p_netbuf) != NULL); - if (from_queue) - { - cl_perf_start( GetEndpt ); - status = __endpt_mgr_ref( p_port, p_eth_hdr->dst, &p_desc->p_endpt ); - cl_perf_stop( &p_port->p_adapter->perf, GetEndpt ); - if( status == NDIS_STATUS_PENDING ) - { - IPOIB_FROM_QUEUE(p_netbuf) = p_sgl; - cl_qlist_insert_head( &p_port->send_mgr.pending_list, - IPOIB_LIST_ITEM_FROM_PACKET( p_desc->p_netbuf_list ) ); - goto send_end; - } - else if( status != NDIS_STATUS_SUCCESS ) - { - ASSERT( status == NDIS_STATUS_NO_ROUTE_TO_DESTINATION ); - - if( ETH_IS_MULTICAST( p_eth_hdr->dst.addr ) ) - { - if( ipoib_port_join_mcast( p_port, p_eth_hdr->dst, - IB_MC_REC_STATE_FULL_MEMBER) == IB_SUCCESS ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_SEND, - ("Multicast Mac - trying to join.\n") ); - IPOIB_FROM_QUEUE(p_netbuf) = p_sgl; - cl_qlist_insert_head( &p_port->send_mgr.pending_list, - IPOIB_LIST_ITEM_FROM_PACKET( p_desc->p_netbuf_list ) ); - goto send_end; - } - } - /* - * Complete the send as if we sent it - WHQL tests don't like the - * sends to fail. - */ - cl_perf_start( ProcessFailedSends ); - __process_failed_send( p_port, p_desc, NDIS_STATUS_SUCCESS,complete_flags ); - cl_perf_stop( &p_port->p_adapter->perf, ProcessFailedSends ); - goto send_end; - } - } - else - { - cl_perf_start( SendMgrQueue ); - if ( ETH_IS_MULTICAST( p_eth_hdr->dst.addr ) && - p_eth_hdr->type == ETH_PROT_TYPE_IP && - !ETH_IS_BROADCAST( p_eth_hdr->dst.addr ) ) - { - ip_hdr_t *p_ip_hdr; - uint8_t *p_tmp; - MDL *p_ip_hdr_mdl; - UINT ip_hdr_mdl_len; - - if(mdl_len >= sizeof(ip_hdr_t) + sizeof(eth_hdr_t)) - { - p_ip_hdr = (ip_hdr_t*)(p_eth_hdr + 1); - } - else - { - NdisGetNextMdl(p_mdl,&p_ip_hdr_mdl); - // Extract the ip hdr - if( !p_ip_hdr_mdl ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed to get IP header buffer.\n") ); - goto mc_end; - } - NdisQueryMdl(p_ip_hdr_mdl,&p_tmp,&ip_hdr_mdl_len,NormalPagePriority); - if( !p_tmp ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed to get IP header.\n") ); - goto mc_end; - } - if( ip_hdr_mdl_len < sizeof(ip_hdr_t) ) - { - /* This buffer is done for. Get the next buffer. */ - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Buffer too small for IP packet.\n") ); - goto mc_end; - } - p_ip_hdr = (ip_hdr_t*)(p_tmp + NET_BUFFER_CURRENT_MDL_OFFSET(p_netbuf)); - p_eth_hdr->dst.addr[1] = ((unsigned char*)&p_ip_hdr->dst_ip)[0] & 0x0f; - p_eth_hdr->dst.addr[3] = ((unsigned char*)&p_ip_hdr->dst_ip)[1]; - } - } -mc_end: - status = __send_mgr_queue( p_port, p_eth_hdr, &p_desc->p_endpt ); - cl_perf_stop( &p_port->p_adapter->perf, SendMgrQueue ); - if( status == NDIS_STATUS_PENDING ) - { - /* Queue net buffer list. */ - cl_perf_start( QueuePacket ); - NET_BUFFER_LIST_NEXT_NBL(p_net_buffer_list) = NULL; - IPOIB_FROM_QUEUE(p_netbuf) = p_sgl; - cl_qlist_insert_tail( &p_port->send_mgr.pending_list, - IPOIB_LIST_ITEM_FROM_PACKET(p_net_buffer_list) ); - cl_perf_stop( &p_port->p_adapter->perf, QueuePacket ); - goto send_end; - } - if( status != NDIS_STATUS_SUCCESS ) - { - ASSERT( status == NDIS_STATUS_NO_ROUTE_TO_DESTINATION ); - /* - * Complete the send as if we sent it - WHQL tests don't like the - * sends to fail. - */ - cl_perf_start( ProcessFailedSends ); - __process_failed_send( p_port, p_desc, NDIS_STATUS_SUCCESS, complete_flags ); - cl_perf_stop( &p_port->p_adapter->perf, ProcessFailedSends ); - goto send_end; - } - } - cl_perf_start( BuildSendDesc ); - status = __build_send_desc( p_port, p_eth_hdr, p_mdl, mdl_len, p_sgl, p_desc ); - cl_perf_stop( &p_port->p_adapter->perf, BuildSendDesc ); - - if( status != NDIS_STATUS_SUCCESS ) - { - cl_perf_start( ProcessFailedSends ); - __process_failed_send( p_port, p_desc, status, complete_flags ); - cl_perf_stop( &p_port->p_adapter->perf, ProcessFailedSends ); - goto send_end; - } - - /* Post the WR. */ - cl_perf_start( PostSend ); - cl_msg_out("sending packet with wr-id =0x%x\n",&p_desc->send_wr[0].wr.wr_id ); - ib_status = p_port->p_adapter->p_ifc->post_send( p_port->ib_mgr.h_qp, &p_desc->send_wr[0].wr, &p_wr_failed ); - cl_perf_stop( &p_port->p_adapter->perf, PostSend ); - if( ib_status != IB_SUCCESS ) - { - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ib_post_send returned %s\n", - p_port->p_adapter->p_ifc->get_err_str( ib_status )) ); - cl_perf_start( ProcessFailedSends ); - __process_failed_send( p_port, p_desc, NDIS_STATUS_FAILURE, complete_flags ); - cl_perf_stop( &p_port->p_adapter->perf, ProcessFailedSends ); - /* Flag the adapter as hung since posting is busted. */ - p_port->p_adapter->hung = TRUE; - } - cl_atomic_inc( &p_port->send_mgr.depth ); - -send_end: - if (status != NDIS_STATUS_SUCCESS) { -// IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_SEND, - // ("Free S/G List: 0x%x.\n", (UINT) (PVOID) p_sgl) ); - /*NdisMFreeNetBufferSGList( - p_port->p_adapter->NdisMiniportDmaHandle, - p_sgl, - p_netbuf);*/ - - } - - - cl_spinlock_release( &p_port->send_lock ); - IPOIB_EXIT( IPOIB_DBG_SEND ); -} - -static NDIS_STATUS -__send_gen( - IN ipoib_port_t* const p_port, - IN ipoib_send_desc_t* const p_desc, - IN SCATTER_GATHER_LIST *p_sgl, - IN INT lso_data_index - ) -{ - ib_api_status_t status; - uint32_t i, j = 1; - uint32_t offset = sizeof(eth_hdr_t); - PERF_DECLARE( SendCopy ); - - IPOIB_ENTER( IPOIB_DBG_SEND ); - - if( !p_sgl ) - { - ASSERT( p_sgl ); - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed to get SGL from packet.\n") ); - return NDIS_STATUS_FAILURE; - } - - /* Remember that one of the DS entries is reserved for the IPoIB header. */ - if( ( p_sgl->NumberOfElements >= MAX_SEND_SGE || - p_sgl->Elements[0].Length < sizeof(eth_hdr_t)) ) - { - - IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_SEND, - ("Too many buffers %d to fit in WR ds_array[%d] \ - Or buffer[0] length %d < Eth header. Copying data.\n", - p_sgl->NumberOfElements, MAX_SEND_SGE, p_sgl->Elements[0].Length ) ); - status = NDIS_STATUS_RESOURCES; - if( !p_port->p_adapter->params.cm_enabled ) - { - cl_perf_start( SendCopy ); - status = __send_copy( p_port, p_desc ); - cl_perf_stop( &p_port->p_adapter->perf, SendCopy ); - } - IPOIB_EXIT( IPOIB_DBG_SEND ); - return status; - } - - /* - * Skip the ethernet header. It is either the first element, - * or part of it. - */ - i = 0; - if( lso_data_index ) - { /* we have an LSO packet */ - i = lso_data_index; - j = 0; - } - else while( offset ) - { - if( p_sgl->Elements[i].Length <= offset ) - { - offset -= p_sgl->Elements[i++].Length; - } - else - { - p_desc->send_wr[0].local_ds[j].vaddr = - p_sgl->Elements[i].Address.QuadPart + offset; - p_desc->send_wr[0].local_ds[j].length = - p_sgl->Elements[i].Length - offset; - p_desc->send_wr[0].local_ds[j].lkey = p_port->ib_mgr.lkey; - i++; - j++; - break; - } - } - /* Now fill in the rest of the local data segments. */ - while( i < p_sgl->NumberOfElements ) - { - p_desc->send_wr[0].local_ds[j].vaddr = p_sgl->Elements[i].Address.QuadPart; - p_desc->send_wr[0].local_ds[j].length = p_sgl->Elements[i].Length; - p_desc->send_wr[0].local_ds[j].lkey = p_port->ib_mgr.lkey; - i++; - j++; - } - - /* Set the number of data segments. */ - p_desc->send_wr[0].wr.num_ds = j; - - IPOIB_EXIT( IPOIB_DBG_SEND ); - return NDIS_STATUS_SUCCESS; -} -#endif - - -static NDIS_STATUS -__send_mgr_filter_ip( - IN ipoib_port_t* const p_port, - IN const eth_hdr_t* const p_eth_hdr, - IN MDL* p_mdl, - IN size_t buf_len, - IN SCATTER_GATHER_LIST *p_sgl, - IN OUT ipoib_send_desc_t* const p_desc ) -{ - NDIS_STATUS status; - ip_hdr_t *p_ip_hdr; - uint32_t ip_packet_len; - size_t iph_size_in_bytes; - size_t iph_options_size; - - PERF_DECLARE( QueryIp ); - PERF_DECLARE( SendTcp ); - PERF_DECLARE( FilterUdp ); - - IPOIB_ENTER( IPOIB_DBG_SEND ); - - if( !buf_len ) - { - cl_perf_start( QueryIp ); - NdisGetNextMdl ( p_mdl, &p_mdl ); - if( !p_mdl ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed to get IP header buffer.\n") ); - return NDIS_STATUS_FAILURE; - } - - NdisQueryMdl(p_mdl, &p_ip_hdr, &buf_len, NormalPagePriority); - if( !p_ip_hdr ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed to query IP header buffer.\n") ); - return NDIS_STATUS_FAILURE; - } - cl_perf_stop( &p_port->p_adapter->perf, QueryIp ); - } - else - { - p_ip_hdr = (ip_hdr_t*)(p_eth_hdr + 1); - } - if( buf_len < sizeof(ip_hdr_t) ) - { - /* This buffer is done for. Get the next buffer. */ - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Buffer too small for IP packet.\n") ); - return NDIS_STATUS_BUFFER_TOO_SHORT; - } - - switch( p_ip_hdr->prot ) - { - case IP_PROT_UDP: - - cl_perf_start( FilterUdp ); - status = __send_mgr_filter_udp( - p_port, p_ip_hdr, p_mdl, (buf_len - sizeof(ip_hdr_t)), p_sgl, p_desc ); - cl_perf_stop( &p_port->p_adapter->perf, FilterUdp ); - if( status == NDIS_STATUS_PENDING ) - { /* not DHCP packet, keep going */ - if( ETH_IS_MULTICAST( p_eth_hdr->dst.addr ) ) - p_desc->send_dir = SEND_UD_QP; - else - p_desc->send_dir = SEND_RC_QP; - break; - } - return status; - - case IP_PROT_TCP: - p_desc->send_dir = SEND_RC_QP; - break; - case IP_PROT_IGMP: - /* - In igmp packet I saw that iph arrive in 2 NDIS_BUFFERs: - 1. iph - 2. ip options - So to get the IGMP packet we need to skip the ip options NDIS_BUFFER - */ - iph_size_in_bytes = (p_ip_hdr->ver_hl & 0xf) * 4; - iph_options_size = iph_size_in_bytes - buf_len; - buf_len -= sizeof(ip_hdr_t);//without ipheader - - /* - Could be a case that arrived igmp packet not from type IGMPv2 , - but IGMPv1 or IGMPv3. - We anyway pass it to __send_mgr_filter_igmp_v2(). - */ - status = - __send_mgr_filter_igmp_v2( p_port, p_ip_hdr, iph_options_size, p_mdl, buf_len ); - if( status != NDIS_STATUS_SUCCESS ) - return status; - - case IP_PROT_ICMP: - p_desc->send_dir = SEND_UD_QP; - default: - break; - } - - if( !p_port->p_adapter->params.cm_enabled ) - { - p_desc->send_dir = SEND_UD_QP; - goto send_gen; - } - else if( endpt_cm_get_state( p_desc->p_endpt ) != IPOIB_CM_CONNECTED ) - { - p_desc->send_dir = SEND_UD_QP; - } - if( p_desc->send_dir == SEND_UD_QP ) - { - ip_packet_len = cl_ntoh16( p_ip_hdr->length ); - if( ip_packet_len > p_port->p_adapter->params.payload_mtu ) - { - //TODO: NDIS60 - #if 0 - status = __send_fragments( p_port, p_desc, (eth_hdr_t* const)p_eth_hdr, - (ip_hdr_t* const)p_ip_hdr, (uint32_t)buf_len, p_mdl ); - return status; - #endif - ASSERT(FALSE); - } - } - -send_gen: - cl_perf_start( SendTcp ); - status = __send_gen( p_port, p_desc, p_sgl, 0 ); - cl_perf_stop( &p_port->p_adapter->perf, SendTcp ); - - IPOIB_EXIT( IPOIB_DBG_SEND ); - return status; -} - -static NDIS_STATUS -__send_mgr_filter_igmp_v2( - IN ipoib_port_t* const p_port, - IN const ip_hdr_t* const p_ip_hdr, - IN size_t iph_options_size, - IN MDL* p_mdl, - IN size_t buf_len ) -{ - igmp_v2_hdr_t *p_igmp_v2_hdr = NULL; - NDIS_STATUS endpt_status; - ipoib_endpt_t* p_endpt = NULL; - mac_addr_t fake_mcast_mac; - - IPOIB_ENTER( IPOIB_DBG_SEND ); - - IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_MCAST, - ("buf_len = %d,iph_options_size = %d\n",(int)buf_len,(int)iph_options_size ) ); - - if( !buf_len ) - { - // To get the IGMP packet we need to skip the ip options NDIS_BUFFER (if exists) - while ( iph_options_size ) - { - NdisGetNextMdl( p_mdl, &p_mdl ); - if( !p_mdl ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed to get IGMPv2 header buffer.\n") ); - return NDIS_STATUS_FAILURE; - } - NdisQueryMdl( p_mdl, &p_igmp_v2_hdr, &buf_len, NormalPagePriority ); - if( !p_igmp_v2_hdr ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed to query IGMPv2 header buffer.\n") ); - return NDIS_STATUS_FAILURE; - } - iph_options_size-=buf_len; - } - - NdisGetNextMdl( p_mdl, &p_mdl ); - if( !p_mdl ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed to get IGMPv2 header buffer.\n") ); - return NDIS_STATUS_FAILURE; - } - NdisQueryMdl( p_mdl, &p_igmp_v2_hdr, &buf_len, NormalPagePriority ); - if( !p_igmp_v2_hdr ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed to query IGMPv2 header buffer.\n") ); - return NDIS_STATUS_FAILURE; - } - } - else - { - /* assuming ip header and options are in the same packet */ - p_igmp_v2_hdr = GetIpPayloadPtr(p_ip_hdr); - } - /* Get the IGMP header length. */ - if( buf_len < sizeof(igmp_v2_hdr_t) ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Buffer not large enough for IGMPv2 packet.\n") ); - return NDIS_STATUS_BUFFER_TOO_SHORT; - } - - // build fake mac from igmp packet group address - fake_mcast_mac.addr[0] = 1; - fake_mcast_mac.addr[1] = ((unsigned char*)&p_igmp_v2_hdr->group_address)[0] & 0x0f; - fake_mcast_mac.addr[2] = 0x5E; - fake_mcast_mac.addr[3] = ((unsigned char*)&p_igmp_v2_hdr->group_address)[1]; - fake_mcast_mac.addr[4] = ((unsigned char*)&p_igmp_v2_hdr->group_address)[2]; - fake_mcast_mac.addr[5] = ((unsigned char*)&p_igmp_v2_hdr->group_address)[3]; - - switch ( p_igmp_v2_hdr->type ) - { - case IGMP_V2_MEMBERSHIP_REPORT: - /* - This mean that some body open listener on this group - Change type of mcast endpt to SEND_RECV endpt. So mcast garbage collector - will not delete this mcast endpt. - */ - IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_MCAST, - ("Catched IGMP_V2_MEMBERSHIP_REPORT message\n") ); - endpt_status = __endpt_mgr_ref( p_port, fake_mcast_mac, &p_endpt ); - if ( p_endpt ) - { - cl_obj_lock( &p_port->obj ); - p_endpt->is_mcast_listener = TRUE; - cl_obj_unlock( &p_port->obj ); - ipoib_endpt_deref( p_endpt ); - } - break; - - case IGMP_V2_LEAVE_GROUP: - /* - This mean that somebody CLOSE listener on this group . - Change type of mcast endpt to SEND_ONLY endpt. So mcast - garbage collector will delete this mcast endpt next time. - */ - IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_MCAST, - ("Catched IGMP_V2_LEAVE_GROUP message\n") ); - endpt_status = __endpt_mgr_ref( p_port, fake_mcast_mac, &p_endpt ); - if ( p_endpt ) - { - cl_obj_lock( &p_port->obj ); - p_endpt->is_mcast_listener = FALSE; - p_endpt->is_in_use = FALSE; - cl_obj_unlock( &p_port->obj ); - ipoib_endpt_deref( p_endpt ); - } - - __port_do_mcast_garbage(p_port); - - break; - - default: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_MCAST, - ("Send Unknown IGMP message: 0x%x \n", p_igmp_v2_hdr->type ) ); - break; - } - - IPOIB_EXIT( IPOIB_DBG_SEND ); - return NDIS_STATUS_SUCCESS; -} - -static NDIS_STATUS -__send_mgr_filter_udp( - IN ipoib_port_t* const p_port, - IN const ip_hdr_t* const p_ip_hdr, - IN MDL* p_mdl, - IN size_t buf_len, - IN SCATTER_GATHER_LIST *p_sgl, - IN OUT ipoib_send_desc_t* const p_desc ) -{ - ib_api_status_t status; - udp_hdr_t *p_udp_hdr; - PERF_DECLARE( QueryUdp ); - PERF_DECLARE( SendUdp ); - PERF_DECLARE( FilterDhcp ); - //TODO NDIS60 remove this param - UNUSED_PARAM(p_sgl); - IPOIB_ENTER( IPOIB_DBG_SEND ); - - if( !buf_len ) - { - cl_perf_start( QueryUdp ); - NdisGetNextMdl( p_mdl, &p_mdl ); - if( !p_mdl ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed to get UDP header buffer.\n") ); - return NDIS_STATUS_FAILURE; - } - NdisQueryMdl( p_mdl, &p_udp_hdr, &buf_len, NormalPagePriority ); - if( !p_udp_hdr ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed to query UDP header buffer.\n") ); - return NDIS_STATUS_FAILURE; - } - cl_perf_stop( &p_port->p_adapter->perf, QueryUdp ); - } - else - { - p_udp_hdr = (udp_hdr_t*)GetIpPayloadPtr(p_ip_hdr); - } - /* Get the UDP header and check the destination port numbers. */ - - if (p_ip_hdr->offset > 0) { - /* This is a fragmented part of UDP packet - * Only first packet will contain UDP header in such case - * So, return if offset > 0 - */ - return NDIS_STATUS_PENDING; - } - - if( buf_len < sizeof(udp_hdr_t) ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Buffer not large enough for UDP packet.\n") ); - return NDIS_STATUS_BUFFER_TOO_SHORT; - } - - if( (p_udp_hdr->src_port != DHCP_PORT_CLIENT || - p_udp_hdr->dst_port != DHCP_PORT_SERVER) && - (p_udp_hdr->src_port != DHCP_PORT_SERVER || - p_udp_hdr->dst_port != DHCP_PORT_CLIENT) ) - { - /* Not a DHCP packet. */ - return NDIS_STATUS_PENDING; - } - - buf_len -= sizeof(udp_hdr_t); - - /* Allocate our scratch buffer. */ - p_desc->p_buf = (send_buf_t*) - ExAllocateFromNPagedLookasideList( &p_port->buf_mgr.send_buf_list ); - if( !p_desc->p_buf ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed to query DHCP packet buffer.\n") ); - return NDIS_STATUS_RESOURCES; - } - /* Copy the IP and UDP headers. */ - cl_memcpy( &p_desc->p_buf->ip.hdr, p_ip_hdr , sizeof(ip_hdr_t) ); - cl_memcpy( - &p_desc->p_buf->ip.prot.udp.hdr, p_udp_hdr, sizeof(udp_hdr_t) ); - - cl_perf_start( FilterDhcp ); - status = __send_mgr_filter_dhcp( - p_port, p_udp_hdr, p_mdl, buf_len, p_desc ); - cl_perf_stop( &p_port->p_adapter->perf, FilterDhcp ); - - IPOIB_EXIT( IPOIB_DBG_SEND ); - return status; -} - -unsigned short ipchksum(unsigned short *ip, int len) -{ - unsigned long sum = 0; - - len >>= 1; - while (len--) { - sum += *(ip++); - if (sum > 0xFFFF) - sum -= 0xFFFF; - } - return (unsigned short)((~sum) & 0x0000FFFF); -} - -static NDIS_STATUS -__send_mgr_filter_dhcp( - IN ipoib_port_t* const p_port, - IN const udp_hdr_t* const p_udp_hdr, - IN NDIS_BUFFER* p_mdl, - IN size_t buf_len, - IN OUT ipoib_send_desc_t* const p_desc ) -{ - dhcp_pkt_t *p_dhcp; - dhcp_pkt_t *p_ib_dhcp; - uint8_t *p_option, *p_cid = NULL; - uint8_t msg = 0; - size_t len; - ib_gid_t gid; - - IPOIB_ENTER( IPOIB_DBG_SEND ); - - if( !buf_len ) - { - NdisGetNextMdl( p_mdl, &p_mdl ); - if( !p_mdl ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed to get DHCP buffer.\n") ); - return NDIS_STATUS_FAILURE; - } - NdisQueryMdl( p_mdl, &p_dhcp, &buf_len, NormalPagePriority ); - if( !p_dhcp ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed to query DHCP buffer.\n") ); - return NDIS_STATUS_FAILURE; - } - } - else - { - p_dhcp = (dhcp_pkt_t*)(p_udp_hdr + 1); - } - - if( buf_len < DHCP_MIN_SIZE ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Buffer not large enough for DHCP packet.\n") ); - return NDIS_STATUS_BUFFER_TOO_SHORT; - } - - p_ib_dhcp = &p_desc->p_buf->ip.prot.udp.dhcp; - cl_memcpy( p_ib_dhcp, p_dhcp, buf_len ); - - /* Now scan through the options looking for the client identifier. */ - p_option = &p_ib_dhcp->options[4]; - while( *p_option != DHCP_OPT_END && p_option < &p_ib_dhcp->options[312] ) - { - switch( *p_option ) - { - case DHCP_OPT_PAD: - p_option++; - break; - - case DHCP_OPT_MSG: - msg = p_option[2]; - p_option += 3; - break; - - case DHCP_OPT_CLIENT_ID: - p_cid = p_option; - /* Fall through. */ - - default: - /* - * All other options have a length byte following the option code. - * Offset by the length to get to the next option. - */ - p_option += (p_option[1] + 2); - } - } - - switch( msg ) - { - /* Client messages */ - case DHCPDISCOVER: - case DHCPREQUEST: - p_ib_dhcp->flags |= DHCP_FLAGS_BROADCAST; - /* Fall through */ - case DHCPDECLINE: - case DHCPRELEASE: - case DHCPINFORM: - /* Fix up the client identifier option */ - if( p_cid ) - { - /* do we need to replace it ? len eq ETH MAC sz 'and' MAC is mine */ - if( p_cid[1] == HW_ADDR_LEN+1 && !cl_memcmp( &p_cid[3], - &p_port->p_adapter->params.conf_mac.addr, HW_ADDR_LEN ) ) - { - /* Make sure there's room to extend it. 23 is the size of - * the CID option for IPoIB. - */ - if( buf_len + 23 - p_cid[1] > sizeof(dhcp_pkt_t) ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Can't convert CID to IPoIB format.\n") ); - return NDIS_STATUS_RESOURCES; - } - /* Move the existing options down, and add a new CID option */ - len = p_option - ( p_cid + p_cid[1] + 2 ); - p_option = p_cid + p_cid[1] + 2; - RtlMoveMemory( p_cid, p_option, len ); - - p_cid += len; - p_cid[0] = DHCP_OPT_CLIENT_ID; - p_cid[1] = 21; - p_cid[2] = DHCP_HW_TYPE_IB; - } - else - { - p_cid[2] = DHCP_HW_TYPE_IB; - } - } - else - { - /* - * Make sure there's room to extend it. 23 is the size of - * the CID option for IPoIB. - */ - if( buf_len + 23 > sizeof(dhcp_pkt_t) ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Can't convert CID to IPoIB format.\n") ); - return NDIS_STATUS_RESOURCES; - } - - p_cid = p_option; - p_option = p_cid + 23; - p_option[0] = DHCP_OPT_END; - p_cid[0] = DHCP_OPT_CLIENT_ID; - p_cid[1] = 21; - p_cid[2] = DHCP_HW_TYPE_IB; - } - - CL_ASSERT( p_cid[1] == 21 ); - p_cid[23]= DHCP_OPT_END; - ib_gid_set_default( &gid, p_port->p_adapter->guids.port_guid.guid ); - cl_memcpy( &p_cid[7], &gid, sizeof(ib_gid_t) ); - cl_memcpy( &p_cid[3], &p_port->ib_mgr.qpn, sizeof(p_port->ib_mgr.qpn) ); - p_ib_dhcp->htype = DHCP_HW_TYPE_IB; - - /* update lengths to include any change we made */ - p_desc->p_buf->ip.hdr.length = cl_ntoh16( sizeof(ip_hdr_t) + sizeof(udp_hdr_t) + sizeof(dhcp_pkt_t) ); - p_desc->p_buf->ip.prot.udp.hdr.length = cl_ntoh16( sizeof(udp_hdr_t) + sizeof(dhcp_pkt_t) ); - - /* update crc in ip header */ - //if( !p_port->p_adapter->params.send_chksum_offload ) - //{ //TODO ? - p_desc->p_buf->ip.hdr.chksum = 0; - p_desc->p_buf->ip.hdr.chksum = ipchksum((unsigned short*) &p_desc->p_buf->ip.hdr, sizeof(ip_hdr_t)); - //} TODO ?? - break; - - /* Server messages. */ - case DHCPOFFER: - case DHCPACK: - case DHCPNAK: - /* don't touch server messages */ - break; - - default: - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Invalide message type.\n") ); - return NDIS_STATUS_INVALID_DATA; - } - /* no chksum for udp */ - p_desc->p_buf->ip.prot.udp.hdr.chksum = 0; - p_desc->send_wr[0].local_ds[1].vaddr = cl_get_physaddr( p_desc->p_buf ); - p_desc->send_wr[0].local_ds[1].length = sizeof(ip_hdr_t) + sizeof(udp_hdr_t) + sizeof(dhcp_pkt_t); - p_desc->send_wr[0].local_ds[1].lkey = p_port->ib_mgr.lkey; - p_desc->send_wr[0].wr.num_ds = 2; - p_desc->send_dir = SEND_UD_QP; - IPOIB_EXIT( IPOIB_DBG_SEND ); - return NDIS_STATUS_SUCCESS; -} - - -static NDIS_STATUS -__send_mgr_filter_arp( - IN ipoib_port_t* const p_port, - IN const eth_hdr_t* const p_eth_hdr, - IN MDL* p_mdl, - IN size_t buf_len, - IN OUT ipoib_send_desc_t* const p_desc ) -{ - arp_pkt_t *p_arp; - ipoib_arp_pkt_t *p_ib_arp; - NDIS_STATUS status; - mac_addr_t null_hw = {0}; - - IPOIB_ENTER( IPOIB_DBG_SEND ); - - if( !buf_len ) - { - NdisGetNextMdl( p_mdl, &p_mdl ); - if( !p_mdl ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed to get ARP buffer.\n") ); - return NDIS_STATUS_FAILURE; - } - NdisQueryMdl( p_mdl, &p_arp, &buf_len, NormalPagePriority ); - if( !p_arp ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed to get query ARP buffer.\n") ); - return NDIS_STATUS_FAILURE; - } - } - else - { - p_arp = (arp_pkt_t*)(p_eth_hdr + 1); - } - - /* Single buffer ARP packet. */ - if( buf_len < sizeof(arp_pkt_t) ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Buffer too short for ARP.\n") ); - return NDIS_STATUS_BUFFER_TOO_SHORT; - } - - if( p_arp->prot_type != ETH_PROT_TYPE_IP ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Unsupported protocol type.\n") ); - return NDIS_STATUS_INVALID_DATA; - } - - /* Allocate our scratch buffer. */ - p_desc->p_buf = (send_buf_t*) - NdisAllocateFromNPagedLookasideList( &p_port->buf_mgr.send_buf_list ); - if( !p_desc->p_buf ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed to query ARP packet buffer.\n") ); - return NDIS_STATUS_RESOURCES; - } - p_ib_arp = (ipoib_arp_pkt_t*)p_desc->p_buf; - - /* Convert the ARP payload. */ - p_ib_arp->hw_type = ARP_HW_TYPE_IB; - p_ib_arp->prot_type = p_arp->prot_type; - p_ib_arp->hw_size = sizeof(ipoib_hw_addr_t); - p_ib_arp->prot_size = p_arp->prot_size; - p_ib_arp->op = p_arp->op; - - ipoib_addr_set_qpn( &p_ib_arp->src_hw, p_port->ib_mgr.qpn ); -#if 0 - - if( p_port->p_adapter->params.cm_enabled ) - { - ipoib_addr_set_flags( &p_ib_arp->src_hw, IPOIB_CM_FLAG_RC ); - } -#endif - - ib_gid_set_default( &p_ib_arp->src_hw.gid, - p_port->p_adapter->guids.port_guid.guid ); - p_ib_arp->src_ip = p_arp->src_ip; - if( cl_memcmp( &p_arp->dst_hw, &null_hw, sizeof(mac_addr_t) ) ) - { - /* Get the endpoint referenced by the dst_hw address. */ - net32_t qpn = 0; - status = __endpt_mgr_get_gid_qpn( p_port, p_arp->dst_hw, - &p_ib_arp->dst_hw.gid, &qpn ); - if( status != NDIS_STATUS_SUCCESS ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed lookup of destination HW address\n") ); - return status; - } - ipoib_addr_set_qpn( &p_ib_arp->dst_hw, qpn ); -#if 0 - if( p_arp->op == ARP_OP_REP && - p_port->p_adapter->params.cm_enabled && - p_desc->p_endpt->cm_flag == IPOIB_CM_FLAG_RC ) - { - cm_state_t cm_state; - cm_state = - ( cm_state_t )InterlockedCompareExchange( (volatile LONG *)&p_desc->p_endpt->conn.state, - IPOIB_CM_CONNECT, IPOIB_CM_DISCONNECTED ); - switch( cm_state ) - { - case IPOIB_CM_DISCONNECTED: - IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, - ("ARP REPLY pending Endpt[%p] QPN %#x MAC %02x:%02x:%02x:%02x:%02x:%02x\n", - p_desc->p_endpt, - cl_ntoh32( ipoib_addr_get_qpn( &p_ib_arp->dst_hw )), - p_desc->p_endpt->mac.addr[0], p_desc->p_endpt->mac.addr[1], - p_desc->p_endpt->mac.addr[2], p_desc->p_endpt->mac.addr[3], - p_desc->p_endpt->mac.addr[4], p_desc->p_endpt->mac.addr[5] ) ); - ipoib_addr_set_sid( &p_desc->p_endpt->conn.service_id, - ipoib_addr_get_qpn( &p_ib_arp->dst_hw ) ); - - NdisFreeToNPagedLookasideList( - &p_port->buf_mgr.send_buf_list, p_desc->p_buf ); - cl_qlist_insert_tail( &p_port->send_mgr.pending_list, - IPOIB_LIST_ITEM_FROM_PACKET( p_desc->p_buf ) ); - NdisInterlockedInsertTailList( &p_port->endpt_mgr.pending_conns, - &p_desc->p_endpt->list_item, - &p_port->endpt_mgr.conn_lock ); - cl_event_signal( &p_port->endpt_mgr.event ); - return NDIS_STATUS_PENDING; - - case IPOIB_CM_CONNECT: - /* queue ARP REP packet until connected */ - NdisFreeToNPagedLookasideList( - &p_port->buf_mgr.send_buf_list, p_desc->p_buf ); - cl_qlist_insert_tail( &p_port->send_mgr.pending_list, - IPOIB_LIST_ITEM_FROM_PACKET( p_desc->p_pkt ) ); - return NDIS_STATUS_PENDING; - default: - break; - } - } -#endif - } - else - { - cl_memclr( &p_ib_arp->dst_hw, sizeof(ipoib_hw_addr_t) ); - } - -#if 0 //DBG - if( p_port->p_adapter->params.cm_enabled ) - { - IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, - (" ARP %s SEND to ENDPT[%p] State: %d flag: %#x, QPN: %#x MAC %02x:%02x:%02x:%02x:%02x:%02x\n", - ( p_ib_arp->op == ARP_OP_REP ? "REP": "REQ"), p_desc->p_endpt, - endpt_cm_get_state( p_desc->p_endpt ), - p_desc->p_endpt->cm_flag, - cl_ntoh32( ipoib_addr_get_qpn( &p_ib_arp->dst_hw )), - p_desc->p_endpt->mac.addr[0], p_desc->p_endpt->mac.addr[1], - p_desc->p_endpt->mac.addr[2], p_desc->p_endpt->mac.addr[3], - p_desc->p_endpt->mac.addr[4], p_desc->p_endpt->mac.addr[5] )); - } -#endif - - p_ib_arp->dst_ip = p_arp->dst_ip; - - p_desc->send_wr[0].local_ds[1].vaddr = cl_get_physaddr( p_ib_arp ); - p_desc->send_wr[0].local_ds[1].length = sizeof(ipoib_arp_pkt_t); - p_desc->send_wr[0].local_ds[1].lkey = p_port->ib_mgr.lkey; - p_desc->send_wr[0].wr.num_ds = 2; - p_desc->send_wr[0].wr.p_next = NULL; - - IPOIB_EXIT( IPOIB_DBG_SEND ); - return NDIS_STATUS_SUCCESS; -} - -static inline NDIS_STATUS -__send_mgr_queue( - IN ipoib_port_t* const p_port, - IN eth_hdr_t* const p_eth_hdr, - OUT ipoib_endpt_t** const pp_endpt ) -{ - NDIS_STATUS status; - - PERF_DECLARE( GetEndpt ); - - IPOIB_ENTER( IPOIB_DBG_SEND ); - - /* Check the send queue and pend the request if not empty. */ - if( cl_qlist_count( &p_port->send_mgr.pending_list ) ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_WARNING, IPOIB_DBG_SEND, - ("Pending list not empty.\n") ); - return NDIS_STATUS_PENDING; - } - - /* Check the send queue and pend the request if not empty. */ - if( p_port->send_mgr.depth == p_port->p_adapter->params.sq_depth ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_WARNING, IPOIB_DBG_SEND, - ("No available WQEs.\n") ); - return NDIS_STATUS_PENDING; - } - - cl_perf_start( GetEndpt ); - status = __endpt_mgr_ref( p_port, p_eth_hdr->dst, pp_endpt ); - cl_perf_stop( &p_port->p_adapter->perf, GetEndpt ); - - if( status == NDIS_STATUS_NO_ROUTE_TO_DESTINATION && - ETH_IS_MULTICAST( p_eth_hdr->dst.addr ) ) - { - if( ipoib_port_join_mcast( p_port, p_eth_hdr->dst, - IB_MC_REC_STATE_FULL_MEMBER) == IB_SUCCESS ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_SEND, - ("Multicast Mac - trying to join.\n") ); - return NDIS_STATUS_PENDING; - } - } - else if ( status == NDIS_STATUS_SUCCESS && - ETH_IS_MULTICAST( p_eth_hdr->dst.addr ) && - !ETH_IS_BROADCAST( p_eth_hdr->dst.addr ) ) - { - CL_ASSERT( (*pp_endpt) ); - CL_ASSERT((*pp_endpt)->h_mcast != NULL); - (*pp_endpt)->is_in_use = TRUE; - } - - IPOIB_EXIT( IPOIB_DBG_SEND ); - return status; -} - - -static NDIS_STATUS -__build_send_desc( - IN ipoib_port_t* const p_port, - IN eth_hdr_t* const p_eth_hdr, - IN MDL* const p_mdl, - IN const size_t mdl_len, - IN SCATTER_GATHER_LIST *p_sgl, - IN OUT ipoib_send_desc_t* const p_desc ) -{ - NDIS_STATUS status; - int32_t hdr_idx; - uint32_t mss; - //PVOID* pp_tmp; - PNDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO p_checksum_list_info; - PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO p_lso_info; - PERF_DECLARE( SendMgrFilter ); - - IPOIB_ENTER( IPOIB_DBG_SEND ); - - /* Format the send descriptor. */ - p_checksum_list_info = NET_BUFFER_LIST_INFO( p_desc->p_netbuf_list,TcpIpChecksumNetBufferListInfo); - //pp_tmp = &NET_BUFFER_LIST_INFO(p_desc->p_netbuf_list, TcpIpChecksumNetBufferListInfo); - //p_checksum_list_info = ( ) ((PULONG)pp_tmp); - p_lso_info = NET_BUFFER_LIST_INFO( p_desc->p_netbuf_list, TcpLargeSendNetBufferListInfo ); - - /* Format the send descriptor. */ - hdr_idx = cl_atomic_inc( &p_port->hdr_idx ); - hdr_idx &= (p_port->p_adapter->params.sq_depth - 1); - ASSERT( hdr_idx < p_port->p_adapter->params.sq_depth ); - p_port->hdr[hdr_idx].type = p_eth_hdr->type; - p_port->hdr[hdr_idx].resv = 0; - - p_desc->send_wr[0].local_ds[0].vaddr = cl_get_physaddr( &p_port->hdr[hdr_idx] ); - p_desc->send_wr[0].local_ds[0].length = sizeof(ipoib_hdr_t); - p_desc->send_wr[0].local_ds[0].lkey = p_port->ib_mgr.lkey; - p_desc->send_wr[0].wr.send_opt = 0; - - mss = (p_lso_info->LsoV1Transmit.MSS | p_lso_info->LsoV2Transmit.MSS); - //TODO: first check params.lso, and thereafter calculate LSO - if( p_port->p_adapter->params.lso && mss ) - - - { - ASSERT( mss == (p_lso_info->LsoV1Transmit.MSS & p_lso_info->LsoV2Transmit.MSS)); - ASSERT ( (mss & (1<<20)) == mss); - status = __build_lso_desc( p_port, p_desc, mss, p_sgl, hdr_idx, p_lso_info ); - if( status != NDIS_STATUS_SUCCESS ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("__build_lso_desc returned 0x%08X.\n", status) ); - return status; - } - } - else - { - uint32_t i; - cl_perf_start( SendMgrFilter ); - status = __send_mgr_filter( - p_port, p_eth_hdr, p_mdl, mdl_len,p_sgl, p_desc ); - cl_perf_stop( &p_port->p_adapter->perf, SendMgrFilter ); - if( status != NDIS_STATUS_SUCCESS ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("__send_mgr_filter returned 0x%08X.\n", status) ); - return status; - } - - if( p_desc->send_dir == SEND_UD_QP ) - { - p_desc->send_qp = p_port->ib_mgr.h_qp; // UD QP - for( i = 0; i < p_desc->num_wrs; i++ ) - { - p_desc->send_wr[i].wr.dgrm.ud.remote_qp = p_desc->p_endpt->qpn; - p_desc->send_wr[i].wr.dgrm.ud.remote_qkey = p_port->ib_mgr.bcast_rec.qkey; - p_desc->send_wr[i].wr.dgrm.ud.h_av = p_desc->p_endpt->h_av; - p_desc->send_wr[i].wr.dgrm.ud.pkey_index = p_port->pkey_index; - p_desc->send_wr[i].wr.dgrm.ud.rsvd = NULL; - p_desc->send_wr[i].wr.send_opt = 0; - - if( p_port->p_adapter->params.send_chksum_offload && - ( p_checksum_list_info->Transmit.IsIPv4 || - p_checksum_list_info->Transmit.IsIPv6 )) - { - // Set transimition checksum offloading - if( p_checksum_list_info->Transmit.IpHeaderChecksum ) - { - p_desc->send_wr[i].wr.send_opt |= IB_SEND_OPT_TX_IP_CSUM; - } - if( p_checksum_list_info->Transmit.TcpChecksum ) - { - p_desc->send_wr[i].wr.send_opt |= IB_SEND_OPT_TX_TCP_UDP_CSUM; - } - } - } - } - else // RC QP - { - CL_ASSERT( p_desc->send_dir == SEND_RC_QP ); - p_desc->send_qp = p_desc->p_endpt->conn.h_work_qp; - } - for( i = 0; i < p_desc->num_wrs; i++ ) - { - p_desc->send_wr[i].wr.wr_type = WR_SEND; - p_desc->send_wr[i].wr.wr_id = 0; - p_desc->send_wr[i].wr.ds_array = &p_desc->send_wr[i].local_ds[0]; - if( i ) - { - p_desc->send_wr[i-1].wr.p_next = &p_desc->send_wr[i].wr; - } - } - //TODO p_net_buf or p_buf -// p_desc->send_wr[p_desc->num_wrs - 1].wr.wr_id = (uintn_t)NET_BUFFER_LIST_FIRST_NB(p_desc->p_netbuf_list ); -//???? IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, ("WR_ID was set to NBL 0x%x \n",p_desc->p_netbuf_list )); - p_desc->send_wr[p_desc->num_wrs - 1].wr.wr_id = (uintn_t)p_desc->p_netbuf_list ; - - p_desc->send_wr[p_desc->num_wrs - 1].wr.send_opt |= IB_SEND_OPT_SIGNALED; - p_desc->send_wr[p_desc->num_wrs - 1].wr.p_next = NULL; - } - - /* Store context in our reserved area of the packet. */ - IPOIB_PORT_FROM_PACKET( p_desc->p_netbuf_list ) = p_port; - IPOIB_ENDPT_FROM_PACKET( p_desc->p_netbuf_list ) = p_desc->p_endpt; - IPOIB_SEND_FROM_NETBUFFER( NET_BUFFER_LIST_FIRST_NB(p_desc->p_netbuf_list ))= p_desc->p_buf; - - IPOIB_EXIT( IPOIB_DBG_SEND ); - return NDIS_STATUS_SUCCESS; -} - -static NDIS_STATUS -__build_lso_desc( - IN ipoib_port_t* const p_port, - IN OUT ipoib_send_desc_t* const p_desc, - IN ULONG mss, - IN SCATTER_GATHER_LIST *p_sgl, - IN int32_t hdr_idx, - IN PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO p_lso_info) -{ - NDIS_STATUS status; - LsoData TheLsoData; - UINT IndexOfData = 0; - - PNET_BUFFER FirstBuffer = NET_BUFFER_LIST_FIRST_NB (p_desc->p_netbuf_list); - ULONG PacketLength = NET_BUFFER_DATA_LENGTH(FirstBuffer); - - IPOIB_ENTER( IPOIB_DBG_SEND ); - - - - memset(&TheLsoData, 0, sizeof TheLsoData ); - status = GetLsoHeaderSize( - FirstBuffer, - &TheLsoData, - &IndexOfData, - &p_port->hdr[hdr_idx] ); - - if ((status != NDIS_STATUS_SUCCESS ) || - (TheLsoData.FullBuffers != TheLsoData.UsedBuffers)) - { - ASSERT(FALSE); - - IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, ("<-- Throwing this packet\n")); - - if( status == NDIS_STATUS_SUCCESS ) - { - status = NDIS_STATUS_INVALID_PACKET; - } - return status; - } - ASSERT(TheLsoData.LsoHeaderSize> 0); - // Tell NDIS how much we will send. - //PktExt->NdisPacketInfo[TcpLargeSendPacketInfo] = UlongToPtr(PacketLength); - p_lso_info->LsoV1TransmitComplete.TcpPayload = PacketLength; - - p_desc->send_wr[0].wr.dgrm.ud.mss = mss; - p_desc->send_wr[0].wr.dgrm.ud.header = TheLsoData.LsoBuffers[0].pData; - p_desc->send_wr[0].wr.dgrm.ud.hlen = TheLsoData.LsoHeaderSize ;//lso_header_size; - p_desc->send_wr[0].wr.dgrm.ud.remote_qp = p_desc->p_endpt->qpn; - p_desc->send_wr[0].wr.dgrm.ud.remote_qkey = p_port->ib_mgr.bcast_rec.qkey; - p_desc->send_wr[0].wr.dgrm.ud.h_av = p_desc->p_endpt->h_av; - p_desc->send_wr[0].wr.dgrm.ud.pkey_index = p_port->pkey_index; - p_desc->send_wr[0].wr.dgrm.ud.rsvd = NULL; - - //TODO: Should be NBL or p_desc - p_desc->send_wr[0].wr.wr_id = (uintn_t)p_desc->p_netbuf_list; - p_desc->send_wr[0].wr.ds_array = p_desc->send_wr[0].local_ds; - p_desc->send_wr[0].wr.wr_type = WR_LSO; - p_desc->send_wr[0].wr.send_opt = - (IB_SEND_OPT_TX_IP_CSUM | IB_SEND_OPT_TX_TCP_UDP_CSUM) | IB_SEND_OPT_SIGNALED; - - p_desc->send_wr[0].wr.p_next = NULL; - p_desc->send_qp = p_port->ib_mgr.h_qp; - p_desc->send_dir = SEND_UD_QP; - status = __send_gen(p_port, p_desc, p_sgl, IndexOfData ); - - IPOIB_EXIT( IPOIB_DBG_SEND ); - return status; -} - -static inline void -__process_failed_send( - IN ipoib_port_t* const p_port, - IN ipoib_send_desc_t* const p_desc, - IN const NDIS_STATUS status, - IN ULONG compl_flags) -{ - IPOIB_ENTER( IPOIB_DBG_SEND ); - - /* Complete the packet. */ - NET_BUFFER_LIST_NEXT_NBL(p_desc->p_netbuf_list) = NULL; - NET_BUFFER_LIST_STATUS(p_desc->p_netbuf_list) = status; - NdisMSendNetBufferListsComplete( p_port->p_adapter->h_adapter, - p_desc->p_netbuf_list, compl_flags ); - ipoib_inc_send_stat( p_port->p_adapter, IP_STAT_ERROR, 0 ); - /* Deref the endpoint. */ - if( p_desc->p_endpt ) - ipoib_endpt_deref( p_desc->p_endpt ); - - if( p_desc->p_buf ) - { - NdisFreeToNPagedLookasideList( - &p_port->buf_mgr.send_buf_list, p_desc->p_buf ); - } - - IPOIB_EXIT( IPOIB_DBG_SEND ); -} - -// max number of physical fragmented buffers -#define MAX_PHYS_BUF_FRAG_ELEMENTS 0x29 -#define MP_FRAG_ELEMENT SCATTER_GATHER_ELEMENT -#define PMP_FRAG_ELEMENT PSCATTER_GATHER_ELEMENT - - -typedef struct _MP_FRAG_LIST { - ULONG NumberOfElements; - ULONG_PTR Reserved; - SCATTER_GATHER_ELEMENT Elements[MAX_PHYS_BUF_FRAG_ELEMENTS]; -} MP_FRAG_LIST, *PMP_FRAG_LIST; - - -void -CreateFragList( - ULONG PhysBufCount, - PNET_BUFFER NetBuff, - ULONG PacketLength, - PMP_FRAG_LIST pFragList - ) -{ -// ETH_ENTER(ETH_SND); - - ULONG i = 0; - int j=0; - - UINT buf_len = NET_BUFFER_DATA_LENGTH(NetBuff); - PMDL pMdl = NET_BUFFER_CURRENT_MDL(NetBuff); - - ULONG CurrentMdlDataOffset = NET_BUFFER_CURRENT_MDL_OFFSET(NetBuff); - ASSERT(MmGetMdlByteCount(pMdl) >= CurrentMdlDataOffset); - - - ASSERT(NetBuff != NULL); -#ifdef DBG - ASSERT(PhysBufCount <= MAX_PHYS_BUF_FRAG_ELEMENTS); -#else - UNREFERENCED_PARAMETER(PhysBufCount); -#endif - - ASSERT(buf_len > 0); - UNREFERENCED_PARAMETER(PacketLength); - - -// ETH_PRINT(TRACE_LEVEL_VERBOSE, ETH_SND, "CreateFragList: NetBuff %p, Length =0x%x\n", NetBuff, buf_len); - - while ( (pMdl != NULL) && (buf_len != 0) ) - { - PPFN_NUMBER page_array = MmGetMdlPfnArray(pMdl); - int MdlBufCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(pMdl), MmGetMdlByteCount(pMdl)); - - ULONG offset = MmGetMdlByteOffset(pMdl) + CurrentMdlDataOffset ; - ULONG MdlBytesCount = MmGetMdlByteCount(pMdl) - CurrentMdlDataOffset; - CurrentMdlDataOffset = 0; - - if( MdlBytesCount == 0 ) - { - pMdl = pMdl->Next; - continue; - } - - ASSERT( (buf_len > 0) && (MdlBytesCount > 0) ); - -// ETH_PRINT(TRACE_LEVEL_VERBOSE, ETH_SND, "CreateFragList: pMdl=%p, MdlBytesCount=x%x, MdlBufCount=0x%x\n", pMdl, MdlBytesCount, MdlBufCount); - - if (MdlBytesCount > 0) - { - if( buf_len > MdlBytesCount) - { - buf_len -= MdlBytesCount; - } - else - { - MdlBytesCount = buf_len; - buf_len = 0; - } - // - // In some cases the mdlcount is greater than needed and in the last page - // there is 0 bytes - // - for (j=0; ((j< MdlBufCount) && (MdlBytesCount > 0)); j++) - { - ASSERT(MdlBytesCount > 0); - if (j ==0 ) - { - // - // First page - // - ULONG64 ul64PageNum = page_array[j]; - pFragList->Elements[i].Address.QuadPart = (ul64PageNum << PAGE_SHIFT)+ offset; - if( offset + MdlBytesCount > PAGE_SIZE ) - { - // - // the data slides behind the page boundry - // - ASSERT(PAGE_SIZE > offset); - pFragList->Elements[i].Length = PAGE_SIZE - offset; - MdlBytesCount -= pFragList->Elements[i].Length; - } - else - { - // - // All the data is hold in one page - // - pFragList->Elements[i].Length = MdlBytesCount; - MdlBytesCount = 0; - } - -// ETH_PRINT(TRACE_LEVEL_VERBOSE, ETH_SND, "CreateFragList: j == 0, MdlBytesCount=x%x, i = %d, element.length=0x%x \n", MdlBytesCount, i, pFragList->Elements[i].Length); - } - else - { - if (page_array[j] == (page_array[j-1] + 1)) - { - - ULONG size = min(PAGE_SIZE, MdlBytesCount); - i -= 1; - pFragList->Elements[i].Length += size; - MdlBytesCount -= size; - } - else - { - // - // Not first page. so the data always start at the begining of the page - // - ULONG64 ul64PageNum = page_array[j]; - pFragList->Elements[i].Address.QuadPart = (ul64PageNum << PAGE_SHIFT); - pFragList->Elements[i].Length = min(PAGE_SIZE, MdlBytesCount); - MdlBytesCount -= pFragList->Elements[i].Length; - } - -// ETH_PRINT(TRACE_LEVEL_VERBOSE, ETH_SND, "CreateFragList: j != 0, MdlBytesCount=x%x, i = %d, element.length=0x%x \n", MdlBytesCount, i, pFragList->Elements[i].Length); - } - i++; - ASSERT(i <= MAX_PHYS_BUF_FRAG_ELEMENTS); - } - } - - pMdl = pMdl->Next; - } - - if (buf_len != 0) - { - // - // In some cases the size in MDL isn't equal to the buffer size. In such - // a case we need to add the rest of packet to last chunk - // - ASSERT(i > 0); // To prevent array underflow - pFragList->Elements[i-1].Length += buf_len; -// ETH_PRINT(TRACE_LEVEL_ERROR, ETH_SND, "CreateFragList: buf_len != 0, i = %d, element.length=0x%x \n", i -1, pFragList->Elements[i-1].Length); - } - - ASSERT(i <= PhysBufCount); - pFragList->NumberOfElements = i; - -#ifdef DBG -{ - ULONG size = 0; - for (i = 0; i < pFragList->NumberOfElements; ++i) - { - size += pFragList->Elements[i].Length; - } - ASSERT(size == PacketLength); -} -#endif - -// ETH_EXIT(ETH_SND); -} - - - - -void -ipoib_port_send( - IN ipoib_port_t* const p_port, - IN NET_BUFFER_LIST *p_net_buffer_list, - IN ULONG send_flags) -{ - NDIS_STATUS status; - PNET_BUFFER p_netbuf; - UINT buf_cnt = 0; - //ipoib_send_desc_t *p_desc; - ULONG send_complete_flags = 0; - KIRQL old_irql; - PVOID p_sgl; - - PERF_DECLARE( GetEthHdr ); - PERF_DECLARE( BuildSendDesc ); - PERF_DECLARE( QueuePacket ); - PERF_DECLARE( SendMgrQueue ); - PERF_DECLARE( PostSend ); - PERF_DECLARE( ProcessFailedSends ); - - IPOIB_ENTER( IPOIB_DBG_SEND ); - - if (NDIS_TEST_SEND_AT_DISPATCH_LEVEL(send_flags)) - { - //TODO Tzachid: make an assert here to validate your IRQL - //ASSERT (KeGetCurrentIRQL() == DISPATCH_LEVEL); - NDIS_SET_SEND_COMPLETE_FLAG(send_complete_flags, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL); - } else { - //ASSERT (KeGetCurrentIRQL() == PASSIVE_LEVEL); - } - - cl_obj_lock( &p_port->obj ); - if( p_port->state != IB_QPS_RTS ) - { - - - cl_obj_unlock( &p_port->obj ); - - - NET_BUFFER_LIST_STATUS(p_net_buffer_list) = NDIS_STATUS_FAILURE; - NET_BUFFER_LIST_NEXT_NBL(p_net_buffer_list) = NULL; - ipoib_inc_send_stat( p_port->p_adapter, IP_STAT_DROPPED, 0 ); - - NdisMSendNetBufferListsComplete( - p_port->p_adapter->h_adapter, - p_net_buffer_list, - send_complete_flags); - - return; - } - cl_obj_unlock( &p_port->obj ); - - //IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - // ("Processing netbuffer list: %x\n", p_net_buffer_list)); - for (p_netbuf = NET_BUFFER_LIST_FIRST_NB(p_net_buffer_list); - p_netbuf != NULL; - p_netbuf = NET_BUFFER_NEXT_NB(p_netbuf)) - { - IPOIB_PORT_FROM_PACKET(p_net_buffer_list) = p_port; - IPOIB_NET_BUFFER_LIST_FROM_NETBUFFER(p_netbuf) = p_net_buffer_list; - IPOIB_FROM_QUEUE(p_netbuf) = NULL; - /*p_desc = &p_port->send_mgr.desc; - p_desc->p_buf = p_netbuf; - p_desc->p_endpt = NULL; - p_desc->p_buf = NULL; - p_desc->send_qp = NULL; - p_desc->num_wrs = 1; - p_desc->send_dir = 0;*/ - - old_irql = KeGetCurrentIrql(); - if (old_irql < DISPATCH_LEVEL) - { - KeRaiseIrqlToDpcLevel(); - } - ++buf_cnt; - //IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - // ("[%d] Netbuf = %x\n",buf_cnt, p_netbuf) ); - if (cl_is_item_in_qlist( &p_port->send_mgr.pending_list, - IPOIB_LIST_ITEM_FROM_PACKET( p_net_buffer_list ))) { - p_sgl = IPOIB_FROM_QUEUE(p_netbuf); - //IPOIB_FROM_QUEUE(p_net_buffer) = (void*)1; - ASSERT (p_sgl); - //IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - // ("[%d] FROM_QUEUE Netbuf = %x, found SGL = %x\n",buf_cnt, p_netbuf, p_sgl) ); - status = NDIS_STATUS_SUCCESS; - } else { - -//#if 0 - CHAR *pTemp = ExAllocatePoolWithTag(NonPagedPool , p_port->p_adapter->sg_list_size, 'abcd'); - CL_ASSERT(pTemp != NULL); - status = NDIS_STATUS_SUCCESS; - p_sgl = pTemp; - CreateFragList(NdisQueryNetBufferPhysicalCount(p_netbuf), p_netbuf, NET_BUFFER_DATA_LENGTH(p_netbuf), p_sgl); - IPOIB_FROM_QUEUE(p_netbuf) = NULL; - /*IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("[%d] Allocation from scratch: Netbuf = %x, found SGL = %x, PhysBufCnt=%ld, NB LEN = %ld, sg_list_size=%ld\n", - buf_cnt, p_netbuf, p_sgl,NdisQueryNetBufferPhysicalCount(p_netbuf) , - NET_BUFFER_DATA_LENGTH(p_netbuf),p_port->p_adapter->sg_list_size) ); - */ - ipoib_process_sg_list(NULL, NULL, p_sgl, p_netbuf); - status = NDIS_STATUS_SUCCESS; -//#endif -#if 0 - status = NdisMAllocateNetBufferSGList( - p_port->p_adapter->NdisMiniportDmaHandle, - p_netbuf, - p_netbuf, - NDIS_SG_LIST_WRITE_TO_DEVICE, - NULL, - 0); -#endif - } - KeLowerIrql (old_irql); - - if( status != NDIS_STATUS_SUCCESS ) - { - /* fail net buffer list */ - NET_BUFFER_LIST_NEXT_NBL(p_net_buffer_list) = NULL; - NET_BUFFER_LIST_STATUS(p_net_buffer_list) = NDIS_STATUS_RESOURCES; - NdisMSendNetBufferListsComplete( - p_port->p_adapter->h_adapter, - p_net_buffer_list, - send_complete_flags); - break; - } - ASSERT(buf_cnt); - IPOIB_GET_NET_BUFFER_LIST_REF_COUNT(p_net_buffer_list) = (PVOID)(ULONG_PTR)buf_cnt; - } - - /* Post the WR. * - cl_perf_start( PostSend ); - ib_status = p_port->p_adapter->p_ifc->post_send( p_desc->send_qp, &p_desc->send_wr[0].wr, &p_wr_failed ); - cl_perf_stop( &p_port->p_adapter->perf, PostSend ); - if( ib_status != IB_SUCCESS ) - { - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ib_post_send returned %s\n", - p_port->p_adapter->p_ifc->get_err_str( ib_status )) ); - cl_perf_start( ProcessFailedSends ); - __process_failed_send( p_port, p_desc, NDIS_STATUS_FAILURE ); - cl_perf_stop( &p_port->p_adapter->perf, ProcessFailedSends ); - * Flag the adapter as hung since posting is busted. * - p_port->p_adapter->hung = TRUE; - continue; - } - - cl_atomic_inc( &p_port->send_mgr.depth ); - } - cl_spinlock_release( &p_port->send_lock ); - - IPOIB_EXIT( IPOIB_DBG_SEND );*/ -} - - -void -ipoib_port_resume( - IN ipoib_port_t* const p_port, - IN boolean_t b_pending ) -{ - NDIS_STATUS status; - cl_list_item_t *p_item; - NET_BUFFER *p_net_buffer; - NET_BUFFER_LIST *p_net_buffer_list; - //ipoib_send_desc_t *p_desc; - KIRQL old_irql; - UINT buf_cnt = 0; - NET_BUFFER_LIST *p_prev_nbl = NULL; - PVOID p_sgl; - static PVOID p_prev_sgl = NULL; - - PERF_DECLARE( GetEndpt ); - PERF_DECLARE( BuildSendDesc ); - PERF_DECLARE( ProcessFailedSends ); - PERF_DECLARE( PostSend ); - - IPOIB_ENTER( IPOIB_DBG_SEND ); - - UNUSED_PARAM(b_pending); - - cl_obj_lock( &p_port->obj ); - if( p_port->state != IB_QPS_RTS ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_WARNING, IPOIB_DBG_SEND, - ("Invalid state - Aborting.\n") ); - cl_obj_unlock( &p_port->obj ); - return; - } - cl_obj_unlock( &p_port->obj ); - -//TODO NDIS60 -////?????????????? cl_spinlock_acquire( &p_port->send_lock ); - - for( p_item = cl_qlist_head( &p_port->send_mgr.pending_list ); - p_item != cl_qlist_end( &p_port->send_mgr.pending_list ); - p_item = cl_qlist_head( &p_port->send_mgr.pending_list ) ) - { - - - /* Check the send queue and pend the request if not empty. */ - if( p_port->send_mgr.depth == p_port->p_adapter->params.sq_depth ) - { - IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_SEND, - ("No available WQEs.\n") ); - break; - } - - p_net_buffer_list = IPOIB_PACKET_FROM_LIST_ITEM( - cl_qlist_remove_head( &p_port->send_mgr.pending_list ) ); - if (p_prev_nbl == p_net_buffer_list) { -// IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - // ("TRYING TO PROCESS ONCE AGAIN, EXITING: %x\n", p_net_buffer_list)); - break; //TODO more sophisticated mechanism to avoid starvation - } - old_irql = KeGetCurrentIrql(); - if (old_irql < DISPATCH_LEVEL) - { - KeRaiseIrqlToDpcLevel(); - } -// IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - // ("Processing netbuffer list from queue: %x\n", (UINT) (PVOID) p_net_buffer_list)); - - for( p_net_buffer = NET_BUFFER_LIST_FIRST_NB(p_net_buffer_list); - p_net_buffer != NULL; - p_net_buffer = NET_BUFFER_NEXT_NB(p_net_buffer), buf_cnt++) - { - - - p_sgl = IPOIB_FROM_QUEUE(p_net_buffer); - //IPOIB_FROM_QUEUE(p_net_buffer) = (void*)1; - ASSERT (p_sgl); - IPOIB_PORT_FROM_PACKET(p_net_buffer_list) = p_port; - IPOIB_NET_BUFFER_LIST_FROM_NETBUFFER(p_net_buffer) = p_net_buffer_list; - /*p_desc = &p_port->send_mgr.desc; - p_desc->p_buf = p_net_buffer; - p_desc->p_endpt = NULL; - p_desc->p_buf = NULL; - p_desc->send_qp = NULL; - p_desc->num_wrs = 1; - p_desc->send_dir = 0;*/ - -// IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - // ("[%d] Netbuf = %x, p_sgl = %x\n",buf_cnt, p_net_buffer, p_sgl) ); - ASSERT(p_sgl); - if (p_sgl != (void*) 1) { - ipoib_process_sg_list(NULL, NULL, p_sgl, p_net_buffer); - status = NDIS_STATUS_SUCCESS; - } - else { - ASSERT(FALSE); - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Getting strange flow\n") ); - NdisMFreeNetBufferSGList( - p_port->p_adapter->NdisMiniportDmaHandle, - p_sgl, - p_net_buffer ); - status = NdisMAllocateNetBufferSGList( - p_port->p_adapter->NdisMiniportDmaHandle, - p_net_buffer, - p_net_buffer, - NDIS_SG_LIST_WRITE_TO_DEVICE, - NULL, - 0 /*p_port->p_adapter->sg_list_size*/ ); - } - p_prev_sgl = p_sgl; - if( status != NDIS_STATUS_SUCCESS ) - { - /* fail net buffer list */ - NET_BUFFER_LIST_NEXT_NBL(p_net_buffer_list) = NULL; - NET_BUFFER_LIST_STATUS(p_net_buffer_list) = NDIS_STATUS_RESOURCES; - NdisMSendNetBufferListsComplete( - p_port->p_adapter->h_adapter, - p_net_buffer_list, - 0); - break; - } - } - - KeLowerIrql (old_irql); - - - p_prev_nbl = p_net_buffer_list; - - } - IPOIB_EXIT( IPOIB_DBG_SEND ); -} - - - -static void -__send_cb( - IN const ib_cq_handle_t h_cq, - IN void *cq_context ) -{ - ipoib_port_t *p_port; - ib_api_status_t status; - ib_wc_t wc[MAX_SEND_WC], *p_wc, *p_free; - cl_qlist_t done_list; - NET_BUFFER_LIST *p_nbl; - uint32_t length; - ipoib_endpt_t *p_endpt; - send_buf_t *p_send_buf; - ip_stat_sel_t type; - size_t i; - NET_BUFFER *p_netbuffer = NULL; - - PERF_DECLARE( SendCompBundle ); - PERF_DECLARE( SendCb ); - PERF_DECLARE( PollSend ); - PERF_DECLARE( SendComp ); - PERF_DECLARE( FreeSendBuf ); - PERF_DECLARE( RearmSend ); - PERF_DECLARE( PortResume ); -//return;//??????????? - IPOIB_ENTER( IPOIB_DBG_SEND ); - - cl_perf_clr( SendCompBundle ); - - cl_perf_start( SendCb ); - - UNUSED_PARAM( h_cq ); - - cl_qlist_init( &done_list ); - - p_port = (ipoib_port_t*)cq_context; - - ipoib_port_ref( p_port, ref_send_cb ); - - for( i = 0; i < MAX_SEND_WC; i++ ) - wc[i].p_next = &wc[i + 1]; - wc[MAX_SEND_WC - 1].p_next = NULL; - - do - { - p_free = wc; - cl_perf_start( PollSend ); - status = p_port->p_adapter->p_ifc->poll_cq( p_port->ib_mgr.h_send_cq, &p_free, &p_wc ); - cl_perf_stop( &p_port->p_adapter->perf, PollSend ); - CL_ASSERT( status == IB_SUCCESS || status == IB_NOT_FOUND ); - - while( p_wc ) - { - cl_perf_start( SendComp ); - CL_ASSERT( p_wc->status != IB_WCS_SUCCESS || p_wc->wc_type == IB_WC_SEND ); - p_nbl = (NET_BUFFER_LIST*)(uintn_t)p_wc->wr_id; - //IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_SEND, - //("[1]Successfull send completion for NBL=0x%x .\n", (UINT) (PVOID) p_nbl )); - CL_ASSERT( p_nbl ); - CL_ASSERT( IPOIB_PORT_FROM_PACKET( p_nbl ) == p_port ); - length = 0; - p_endpt = IPOIB_ENDPT_FROM_PACKET( p_nbl ); - p_send_buf = IPOIB_SEND_FROM_NETBUFFER( NET_BUFFER_LIST_FIRST_NB (p_nbl )); - - switch( p_wc->status ) - { - case IB_WCS_SUCCESS: - if( p_endpt->h_mcast ) - { - if( p_endpt->dgid.multicast.raw_group_id[11] == 0xFF && - p_endpt->dgid.multicast.raw_group_id[10] == 0xFF && - p_endpt->dgid.multicast.raw_group_id[12] == 0xFF && - p_endpt->dgid.multicast.raw_group_id[13] == 0xFF ) - { - type = IP_STAT_BCAST_BYTES; - } - else - { - type = IP_STAT_MCAST_BYTES; - } - } - else - { - type = IP_STAT_UCAST_BYTES; - } - for (p_netbuffer = NET_BUFFER_LIST_FIRST_NB(p_nbl); - p_netbuffer != NULL; - p_netbuffer = NET_BUFFER_NEXT_NB(p_netbuffer)) - { - length += NET_BUFFER_DATA_LENGTH(p_netbuffer); - } - ipoib_inc_send_stat( p_port->p_adapter, type, length ); - // IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_SEND, - //("Successfull send completion for NBL=0x%x .\n", (UINT) (PVOID) p_nbl) ); - NET_BUFFER_LIST_STATUS(p_nbl) = NDIS_STATUS_SUCCESS; - IPOIB_DEC_NET_BUFFER_LIST_REF_COUNT(p_nbl); - if (IPOIB_GET_NET_BUFFER_LIST_REF_COUNT(p_nbl) == 0) - NdisMSendNetBufferListsComplete(p_port->p_adapter->h_adapter, - p_nbl, - 0); - break; - - case IB_WCS_WR_FLUSHED_ERR: - IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_SEND, - ("Flushed send completion.\n") ); - ipoib_inc_send_stat( p_port->p_adapter, IP_STAT_DROPPED, 0 ); - NET_BUFFER_LIST_STATUS(p_nbl) = NDIS_STATUS_RESET_IN_PROGRESS; - NdisMSendNetBufferListsComplete(p_port->p_adapter->h_adapter, - p_nbl, - 0); - break; - - default: - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Send failed with %s (vendor specific %#x)\n", - p_port->p_adapter->p_ifc->get_wc_status_str( p_wc->status ), - (int)p_wc->vendor_specific) ); - ipoib_inc_send_stat( p_port->p_adapter, IP_STAT_ERROR, 0 ); - NET_BUFFER_LIST_STATUS(p_nbl) = NDIS_STATUS_FAILURE; - NdisMSendNetBufferListsComplete(p_port->p_adapter->h_adapter, - p_nbl, - 0); - break; - } - cl_perf_stop( &p_port->p_adapter->perf, SendComp ); - /* Dereference the enpoint used for the transfer. */ - ipoib_endpt_deref( p_endpt ); - - if( p_send_buf ) - { - cl_perf_start( FreeSendBuf ); - NdisFreeToNPagedLookasideList( &p_port->buf_mgr.send_buf_list, - p_send_buf ); - cl_perf_stop( &p_port->p_adapter->perf, FreeSendBuf ); - } - - cl_atomic_dec( &p_port->send_mgr.depth ); - - p_wc = p_wc->p_next; - cl_perf_inc( SendCompBundle ); - } - /* If we didn't use up every WC, break out. */ - } while( !p_free ); - - /* Rearm the CQ. */ - cl_perf_start( RearmSend ); - status = p_port->p_adapter->p_ifc->rearm_cq( p_port->ib_mgr.h_send_cq, FALSE ); - cl_perf_stop( &p_port->p_adapter->perf, RearmSend ); - CL_ASSERT( status == IB_SUCCESS ); - - /* Resume any sends awaiting resources. */ - cl_perf_start( PortResume ); - ipoib_port_resume( p_port, TRUE ); - cl_perf_stop( &p_port->p_adapter->perf, PortResume ); - - ipoib_port_deref( p_port, ref_send_cb ); - - cl_perf_stop( &p_port->p_adapter->perf, SendCb ); - cl_perf_update_ctr( &p_port->p_adapter->perf, SendCompBundle ); - - IPOIB_EXIT( IPOIB_DBG_SEND ); -} - - -/****************************************************************************** -* -* Endpoint manager implementation -* -******************************************************************************/ -static void -__endpt_mgr_construct( - IN ipoib_port_t* const p_port ) -{ - IPOIB_ENTER( IPOIB_DBG_INIT ); - cl_qmap_init( &p_port->endpt_mgr.mac_endpts ); - cl_qmap_init( &p_port->endpt_mgr.lid_endpts ); - cl_fmap_init( &p_port->endpt_mgr.gid_endpts, __gid_cmp ); - IPOIB_EXIT( IPOIB_DBG_INIT ); -} - -static void -__endpt_cm_mgr_thread( -IN void* p_context ); - -static ib_api_status_t -__endpt_mgr_init( - IN ipoib_port_t* const p_port ) -{ - IPOIB_ENTER( IPOIB_DBG_INIT ); -#if 0 - if( p_port->p_adapter->params.cm_enabled ) - { - cl_fmap_init( &p_port->endpt_mgr.conn_endpts, __gid_cmp ); - - NdisInitializeListHead( &p_port->endpt_mgr.pending_conns ); - NdisAllocateSpinLock( &p_port->endpt_mgr.conn_lock ); - cl_event_init( &p_port->endpt_mgr.event, FALSE ); - - NdisInitializeListHead( &p_port->endpt_mgr.remove_conns ); - NdisAllocateSpinLock( &p_port->endpt_mgr.remove_lock ); - - cl_thread_init( &p_port->endpt_mgr.h_thread, - __endpt_cm_mgr_thread, - ( const void *)p_port, - "CmEndPtMgr" ); - } -#endif - UNUSED_PARAM(p_port); - IPOIB_EXIT( IPOIB_DBG_INIT ); - return IB_SUCCESS; -} - -static void -__endpt_cm_mgr_thread( -IN void* p_context ) -{ - ib_api_status_t ib_status; - LIST_ENTRY *p_item; - ipoib_endpt_t *p_endpt; - ipoib_port_t *p_port =( ipoib_port_t *)p_context; - - IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, - ("Starting Port [%d] Endpt CM thread \n", p_port->port_num ) ); - - while( !p_port->endpt_mgr.thread_is_done ) - { - cl_event_wait_on( &p_port->endpt_mgr.event, EVENT_NO_TIMEOUT, FALSE ); - - while( ( p_item = NdisInterlockedRemoveHeadList( - &p_port->endpt_mgr.pending_conns, - &p_port->endpt_mgr.conn_lock) ) != NULL ) - { - - p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, list_item ); - if( p_port->endpt_mgr.thread_is_done ) - { - endpt_cm_set_state( p_endpt, IPOIB_CM_DISCONNECTED ); - continue; - } - - IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, - ("Endpt[%p] CONNECT REQ to MAC %02x:%02x:%02x:%02x:%02x:%02x\n", - p_endpt, - p_endpt->mac.addr[0], p_endpt->mac.addr[1], - p_endpt->mac.addr[2], p_endpt->mac.addr[3], - p_endpt->mac.addr[4], p_endpt->mac.addr[5] ) ); - - if( !p_endpt->conn.h_send_qp ) - { - ib_status = endpt_cm_create_qp( p_endpt, &p_endpt->conn.h_send_qp ); - if( ib_status != IB_SUCCESS ) - { - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Endpt [%p ] CM create QP failed status %#x\n", p_endpt, ib_status ) ); - } - else - { - ib_status = ipoib_endpt_connect( p_endpt ); - if( ib_status != IB_SUCCESS && ib_status != IB_PENDING ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Endpt [ %p ] conn REQ failed status %#x\n", p_endpt, ib_status ) ); - } - } - if( ib_status != IB_SUCCESS && ib_status != IB_PENDING ) - { - endpt_cm_set_state( p_endpt, IPOIB_CM_DESTROY ); - endpt_cm_flush_recv( p_port, p_endpt ); - endpt_cm_set_state( p_endpt, IPOIB_CM_DISCONNECTED ); - } - } - - }//while( p_item != NULL ) - - while( ( p_item = NdisInterlockedRemoveHeadList( - &p_port->endpt_mgr.remove_conns, - &p_port->endpt_mgr.remove_lock ) ) != NULL ) - { - p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, list_item ); - - endpt_cm_set_state( p_endpt, IPOIB_CM_DESTROY ); - - IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_INIT, - ("\nDESTROYING Endpt[%p] MAC %02x:%02x:%02x:%02x:%02x:%02x\n", - p_endpt, - p_endpt->mac.addr[0], p_endpt->mac.addr[1], - p_endpt->mac.addr[2], p_endpt->mac.addr[3], - p_endpt->mac.addr[4], p_endpt->mac.addr[5] ) ); - endpt_cm_flush_recv( p_port, p_endpt ); - endpt_cm_set_state( p_endpt, IPOIB_CM_DISCONNECTED ); - cl_obj_destroy( &p_endpt->obj ); - } - } - - p_port->endpt_mgr.thread_is_done++; - NdisFreeSpinLock( &p_port->endpt_mgr.conn_lock ); - - IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, - (" Port [%d] Endpt thread is done\n", p_port->port_num ) ); -} - -static void -__endpt_mgr_destroy( - IN ipoib_port_t* const p_port ) -{ - IPOIB_ENTER( IPOIB_DBG_INIT ); - CL_ASSERT( cl_is_qmap_empty( &p_port->endpt_mgr.mac_endpts ) ); - CL_ASSERT( cl_is_qmap_empty( &p_port->endpt_mgr.lid_endpts ) ); - CL_ASSERT( cl_is_fmap_empty( &p_port->endpt_mgr.gid_endpts ) ); - UNUSED_PARAM(p_port); -#if 0 - if( p_port->p_adapter->params.cm_enabled ) - { - CL_ASSERT( cl_is_fmap_empty( &p_port->endpt_mgr.conn_endpts ) ); - } -#endif - IPOIB_EXIT( IPOIB_DBG_INIT ); -} - - -static void -__endpt_mgr_remove_all( - IN ipoib_port_t* const p_port ) -{ - IPOIB_ENTER( IPOIB_DBG_ENDPT ); - - cl_obj_lock( &p_port->obj ); - /* Wait for all readers to complete. */ - while( p_port->endpt_rdr ) - ; - /* - * We don't need to initiate destruction - this is called only - * from the __port_destroying function, and destruction cascades - * to all child objects. Just clear all the maps. - */ - cl_qmap_remove_all( &p_port->endpt_mgr.mac_endpts ); - cl_qmap_remove_all( &p_port->endpt_mgr.lid_endpts ); - cl_fmap_remove_all( &p_port->endpt_mgr.gid_endpts ); - cl_obj_unlock( &p_port->obj ); - - IPOIB_EXIT( IPOIB_DBG_ENDPT ); -} - - -static void -__endpt_mgr_reset_all( - IN ipoib_port_t* const p_port ) -{ - cl_map_item_t *p_item; - cl_fmap_item_t *p_fmap_item; - ipoib_endpt_t *p_endpt; - cl_qlist_t mc_list; - cl_qlist_t conn_list; - uint32_t local_exist = 0; - NDIS_LINK_STATE link_state; - NDIS_STATUS_INDICATION status_indication; - - - IPOIB_ENTER( IPOIB_DBG_ENDPT ); - - cl_qlist_init( &mc_list ); - cl_qlist_init( &conn_list ); -//??? cl_obj_lock( &p_port->obj ); - /* Wait for all readers to complete. */ - while( p_port->endpt_rdr ) - ; - -#if 0 - __endpt_mgr_remove_all(p_port); -#else - link_state.Header.Revision = NDIS_LINK_STATE_REVISION_1; - link_state.Header.Type = NDIS_OBJECT_TYPE_DEFAULT; - link_state.Header.Size = sizeof(NDIS_LINK_STATE); - link_state.MediaConnectState = MediaConnectStateDisconnected; - link_state.MediaDuplexState = MediaDuplexStateFull; - link_state.XmitLinkSpeed = link_state.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED; - - IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication, - p_port->p_adapter->h_adapter, - NDIS_STATUS_LINK_STATE, - (PVOID)&link_state, - sizeof(link_state)); - IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, ("Indicate DISCONNECT!\n") ); - NdisMIndicateStatusEx(p_port->p_adapter->h_adapter,&status_indication); - - link_state.MediaConnectState = MediaConnectStateConnected; - IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication, - p_port->p_adapter->h_adapter, - NDIS_STATUS_LINK_STATE, - (PVOID)&link_state, - sizeof(link_state)); - IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, ("Indicate Connect\n") ); - NdisMIndicateStatusEx(p_port->p_adapter->h_adapter,&status_indication); - - - // IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, - // ("Link DOWN!\n") ); - - if( p_port->p_local_endpt ) - { - //TODO: CM RESTORE - //ipoib_port_cancel_listen( p_port, p_port->p_local_endpt ); - - cl_fmap_remove_item( &p_port->endpt_mgr.gid_endpts, - &p_port->p_local_endpt->gid_item ); - cl_qmap_remove_item( &p_port->endpt_mgr.mac_endpts, - &p_port->p_local_endpt->mac_item ); - cl_qmap_remove_item( &p_port->endpt_mgr.lid_endpts, - &p_port->p_local_endpt->lid_item ); - - cl_qlist_insert_head( - &mc_list, &p_port->p_local_endpt->mac_item.pool_item.list_item ); - local_exist = 1; - - p_port->p_local_endpt = NULL; - } - - p_item = cl_qmap_head( &p_port->endpt_mgr.mac_endpts ); - while( p_item != cl_qmap_end( &p_port->endpt_mgr.mac_endpts ) ) - { - p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item ); - p_item = cl_qmap_next( p_item ); - if( p_endpt->h_mcast ) - { - /* - * We destroy MC endpoints since they will get recreated - * when the port comes back up and we rejoin the MC groups. - */ - cl_qmap_remove_item( &p_port->endpt_mgr.mac_endpts, - &p_endpt->mac_item ); - cl_fmap_remove_item( &p_port->endpt_mgr.gid_endpts, - &p_endpt->gid_item ); - - cl_qlist_insert_tail( - &mc_list, &p_endpt->mac_item.pool_item.list_item ); - } - /* destroy connected endpoints if any */ - else if( p_port->p_adapter->params.cm_enabled && - endpt_cm_get_state( p_endpt ) != IPOIB_CM_DISCONNECTED ) - { - p_fmap_item = cl_fmap_get( &p_port->endpt_mgr.conn_endpts, &p_endpt->dgid ); - if( p_fmap_item != cl_fmap_end( &p_port->endpt_mgr.conn_endpts ) ) - { - cl_fmap_remove_item( &p_port->endpt_mgr.conn_endpts, - &p_endpt->conn_item ); - } - cl_qmap_remove_item( &p_port->endpt_mgr.mac_endpts, - &p_endpt->mac_item ); - cl_fmap_remove_item( &p_port->endpt_mgr.gid_endpts, - &p_endpt->gid_item ); - - cl_qlist_insert_tail( - &conn_list, &p_endpt->mac_item.pool_item.list_item ); - } - if( p_endpt->h_av ) - { - /* Destroy the AV for all other endpoints. */ - p_port->p_adapter->p_ifc->destroy_av( p_endpt->h_av ); - p_endpt->h_av = NULL; - } - - if( p_endpt->dlid ) - { - cl_qmap_remove_item( &p_port->endpt_mgr.lid_endpts, - &p_endpt->lid_item ); - IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT, - ("<__endptr_mgr_reset_all: setting p_endpt->dlid to 0\n")); - p_endpt->dlid = 0; - } - - } -#endif -//??? cl_obj_unlock( &p_port->obj ); - - //TODO CM - /*while( cl_qlist_count( &conn_list ) ) - { - endpt_cm_destroy_conn( p_port, - PARENT_STRUCT( cl_qlist_remove_head( &conn_list ), - ipoib_endpt_t, mac_item.pool_item.list_item ) ); - }*/ - - if(cl_qlist_count( &mc_list ) - local_exist) - { - p_port->mcast_cnt = (uint32_t)cl_qlist_count( &mc_list ) - local_exist; - } - else - { - p_port->mcast_cnt = 0; - KeSetEvent( &p_port->leave_mcast_event, EVENT_INCREMENT, FALSE ); - } - - IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,("p_port->mcast_cnt = %d\n", p_port->mcast_cnt - local_exist)); - - /* Destroy all multicast endpoints now that we have released the lock. */ - while( cl_qlist_count( &mc_list ) ) - { - cl_list_item_t *p_item; - p_item = cl_qlist_remove_head( &mc_list ); - p_endpt = PARENT_STRUCT(p_item, ipoib_endpt_t, mac_item.pool_item.list_item); - cl_obj_destroy( &p_endpt->obj); - } - - IPOIB_EXIT( IPOIB_DBG_ENDPT ); -} - - -/* - * Called when updating an endpoint entry in response to an ARP. - * Because receive processing is serialized, and holds a reference - * on the endpoint reader, we wait for all *other* readers to exit before - * removing the item. - */ -static void -__endpt_mgr_remove( - IN ipoib_port_t* const p_port, - IN ipoib_endpt_t* const p_endpt ) -{ -#if 0 //CM - cl_fmap_item_t* p_fmap_item; -#endif - IPOIB_ENTER( IPOIB_DBG_ENDPT ); - - /* This function must be called from the receive path */ - CL_ASSERT(p_port->endpt_rdr > 0); - - cl_obj_lock( &p_port->obj ); - /* Wait for all readers to complete. */ - while( p_port->endpt_rdr > 1 ) - ; - - /* Remove the endpoint from the maps so further requests don't find it. */ - cl_qmap_remove_item( &p_port->endpt_mgr.mac_endpts, &p_endpt->mac_item ); - /* - * The enpoints are *ALWAYS* in both the MAC and GID maps. They are only - * in the LID map if the GID has the same subnet prefix as us. - */ - cl_fmap_remove_item( &p_port->endpt_mgr.gid_endpts, &p_endpt->gid_item ); -#if 0 - - if( p_port->p_adapter->params.cm_enabled ) - { - p_fmap_item = cl_fmap_get( &p_port->endpt_mgr.conn_endpts, &p_endpt->dgid ); - - if( p_fmap_item != cl_fmap_end( &p_port->endpt_mgr.conn_endpts ) ) - { - cl_fmap_remove_item( &p_port->endpt_mgr.conn_endpts, - &p_endpt->conn_item ); - } - } -#endif - if( p_endpt->dlid ) - { - cl_qmap_remove_item( &p_port->endpt_mgr.lid_endpts, - &p_endpt->lid_item ); - } - - cl_obj_unlock( &p_port->obj ); - - //TODO CM - //endpt_cm_destroy_conn( p_port, p_endpt ); - - IPOIB_EXIT( IPOIB_DBG_ENDPT ); -} - - -NTSTATUS -ipoib_mac_to_gid( - IN ipoib_port_t* const p_port, - IN const mac_addr_t mac, - OUT ib_gid_t* p_gid ) -{ - ipoib_endpt_t* p_endpt; - cl_map_item_t *p_item; - uint64_t key = 0; - - IPOIB_ENTER( IPOIB_DBG_ENDPT ); - - cl_memcpy( &key, &mac, sizeof(mac_addr_t) ); - - cl_obj_lock( &p_port->obj ); - - p_item = cl_qmap_get( &p_port->endpt_mgr.mac_endpts, key ); - if( p_item == cl_qmap_end( &p_port->endpt_mgr.mac_endpts ) ) - { - cl_obj_unlock( &p_port->obj ); - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed endpoint lookup.\n") ); - return STATUS_INVALID_PARAMETER; - } - - p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item ); - *p_gid = p_endpt->dgid; - - cl_obj_unlock( &p_port->obj ); - - IPOIB_EXIT( IPOIB_DBG_ENDPT ); - return STATUS_SUCCESS; -} - - -NTSTATUS -ipoib_mac_to_path( - IN ipoib_port_t* const p_port, - IN const mac_addr_t mac, - OUT ib_path_rec_t* p_path ) -{ - ipoib_endpt_t* p_endpt; - cl_map_item_t *p_item; - uint64_t key = 0; - uint8_t sl; - net32_t flow_lbl; - uint8_t hop_limit; - uint8_t pkt_life; - - IPOIB_ENTER( IPOIB_DBG_ENDPT ); - - cl_memcpy( &key, &mac, sizeof(mac_addr_t) ); - - cl_obj_lock( &p_port->obj ); - - if( p_port->p_local_endpt == NULL ) - { - cl_obj_unlock( &p_port->obj ); - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("No local endpoint.\n") ); - return STATUS_INVALID_PARAMETER; - } - - if( mac.addr[0] == 0 && mac.addr[1] == 0 && mac.addr[2] == 0 && - mac.addr[3] == 0 && mac.addr[4] == 0 && mac.addr[5] == 0 ) - { - p_endpt = p_port->p_local_endpt; - } - else - { - p_item = cl_qmap_get( &p_port->endpt_mgr.mac_endpts, key ); - if( p_item == cl_qmap_end( &p_port->endpt_mgr.mac_endpts ) ) - { - cl_obj_unlock( &p_port->obj ); - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed endpoint lookup.\n") ); - return STATUS_INVALID_PARAMETER; - } - - p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item ); - } - - p_path->service_id = 0; - p_path->dgid = p_endpt->dgid; - p_path->sgid = p_port->p_local_endpt->dgid; - p_path->dlid = p_endpt->dlid; - p_path->slid = p_port->p_local_endpt->dlid; - - ib_member_get_sl_flow_hop( - p_port->ib_mgr.bcast_rec.sl_flow_hop, - &sl, - &flow_lbl, - &hop_limit - ); - - if( p_path->slid == p_path->dlid ) - pkt_life = 0; - else - pkt_life = p_port->ib_mgr.bcast_rec.pkt_life; - - ib_path_rec_init_local( - p_path, - &p_endpt->dgid, - &p_port->p_local_endpt->dgid, - p_endpt->dlid, - p_port->p_local_endpt->dlid, - 1, - p_port->ib_mgr.bcast_rec.pkey, - sl, 0, - IB_PATH_SELECTOR_EXACTLY, p_port->ib_mgr.bcast_rec.mtu, - IB_PATH_SELECTOR_EXACTLY, p_port->ib_mgr.bcast_rec.rate, - IB_PATH_SELECTOR_EXACTLY, pkt_life, - 0 ); - - /* Set global routing information. */ - ib_path_rec_set_hop_flow_raw( p_path, hop_limit, flow_lbl, FALSE ); - p_path->tclass = p_port->ib_mgr.bcast_rec.tclass; - - cl_obj_unlock( &p_port->obj ); - - IPOIB_EXIT( IPOIB_DBG_ENDPT ); - return STATUS_SUCCESS; -} - - -static inline NDIS_STATUS -__endpt_mgr_ref( - IN ipoib_port_t* const p_port, - IN const mac_addr_t mac, - OUT ipoib_endpt_t** const pp_endpt ) -{ - NDIS_STATUS status; - cl_map_item_t *p_item; - uint64_t key; - - PERF_DECLARE( EndptQueue ); - - IPOIB_ENTER( IPOIB_DBG_ENDPT ); - - if( !cl_memcmp( &mac, &p_port->p_adapter->params.conf_mac, sizeof(mac) ) ) - { - /* Discard loopback traffic. */ - IPOIB_PRINT(TRACE_LEVEL_WARNING, IPOIB_DBG_ENDPT, - ("Discarding loopback traffic\n") ); - IPOIB_EXIT( IPOIB_DBG_ENDPT ); - return NDIS_STATUS_NO_ROUTE_TO_DESTINATION; - } - - key = 0; - cl_memcpy( &key, &mac, sizeof(mac_addr_t) ); - - cl_obj_lock( &p_port->obj ); - - IPOIB_PRINT( TRACE_LEVEL_VERBOSE, IPOIB_DBG_ENDPT, - ("Look for :\t MAC: %02X-%02X-%02X-%02X-%02X-%02X\n", - mac.addr[0], mac.addr[1], mac.addr[2], - mac.addr[3], mac.addr[4], mac.addr[5]) ); - - p_item = cl_qmap_get( &p_port->endpt_mgr.mac_endpts, key ); - if( p_item == cl_qmap_end( &p_port->endpt_mgr.mac_endpts ) ) - { - cl_obj_unlock( &p_port->obj ); - IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT, - ("Failed endpoint lookup.\n") ); - return NDIS_STATUS_NO_ROUTE_TO_DESTINATION; - } - - *pp_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item ); - ipoib_endpt_ref( *pp_endpt ); - - cl_obj_unlock( &p_port->obj ); - - cl_perf_start( EndptQueue ); - status = ipoib_endpt_queue( *pp_endpt ); - cl_perf_stop( &p_port->p_adapter->perf, EndptQueue ); - if( status != NDIS_STATUS_SUCCESS ) - *pp_endpt = NULL; - - IPOIB_EXIT( IPOIB_DBG_ENDPT ); - return status; -} - - -static inline NDIS_STATUS -__endpt_mgr_get_gid_qpn( - IN ipoib_port_t* const p_port, - IN const mac_addr_t mac, - OUT ib_gid_t* const p_gid, - OUT UNALIGNED net32_t* const p_qpn ) -{ - UNALIGNED - cl_map_item_t *p_item; - ipoib_endpt_t *p_endpt; - uint64_t key; - - IPOIB_ENTER( IPOIB_DBG_ENDPT ); - - cl_obj_lock( &p_port->obj ); - - key = 0; - cl_memcpy( &key, &mac, sizeof(mac_addr_t) ); - p_item = cl_qmap_get( &p_port->endpt_mgr.mac_endpts, key ); - if( p_item == cl_qmap_end( &p_port->endpt_mgr.mac_endpts ) ) - { - cl_obj_unlock( &p_port->obj ); - IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT, - ("Failed endpoint lookup.\n") ); - return NDIS_STATUS_FAILURE; - } - - p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item ); - - *p_gid = p_endpt->dgid; - *p_qpn = p_endpt->qpn; - - cl_obj_unlock( &p_port->obj ); - - IPOIB_EXIT( IPOIB_DBG_ENDPT ); - return NDIS_STATUS_SUCCESS; -} - - -static inline ipoib_endpt_t* -__endpt_mgr_get_by_gid( - IN ipoib_port_t* const p_port, - IN const ib_gid_t* const p_gid ) -{ - cl_fmap_item_t *p_item; - ipoib_endpt_t *p_endpt; - - IPOIB_ENTER( IPOIB_DBG_ENDPT ); - - p_item = cl_fmap_get( &p_port->endpt_mgr.gid_endpts, p_gid ); - if( p_item == cl_fmap_end( &p_port->endpt_mgr.gid_endpts ) ) - p_endpt = NULL; - else - p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, gid_item ); - - IPOIB_EXIT( IPOIB_DBG_ENDPT ); - return p_endpt; -} - - -static ipoib_endpt_t* -__endpt_mgr_get_by_lid( - IN ipoib_port_t* const p_port, - IN const net16_t lid ) -{ - cl_map_item_t *p_item; - ipoib_endpt_t *p_endpt; - - IPOIB_ENTER( IPOIB_DBG_ENDPT ); - - p_item = cl_qmap_get( &p_port->endpt_mgr.lid_endpts, lid ); - if( p_item == cl_qmap_end( &p_port->endpt_mgr.lid_endpts ) ) - p_endpt = NULL; - else - p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, lid_item ); - - IPOIB_EXIT( IPOIB_DBG_ENDPT ); - return p_endpt; -} - - -inline ib_api_status_t -__endpt_mgr_insert_locked( - IN ipoib_port_t* const p_port, - IN const mac_addr_t mac, - IN ipoib_endpt_t* const p_endpt ) -{ - ib_api_status_t status; - - IPOIB_ENTER( IPOIB_DBG_ENDPT ); - - IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT, - ("insert :\t MAC: %02X-%02X-%02X-%02X-%02X-%02X\n", - mac.addr[0], mac.addr[1], mac.addr[2], - mac.addr[3], mac.addr[4], mac.addr[5]) ); - - cl_obj_lock( &p_port->obj ); - while( p_port->endpt_rdr ) - { - cl_obj_unlock( &p_port->obj ); - cl_obj_lock( &p_port->obj ); - } - /* __endpt_mgr_insert expects *one* reference to be held when being called. */ - cl_atomic_inc( &p_port->endpt_rdr ); - status= __endpt_mgr_insert( p_port, mac, p_endpt ); - cl_atomic_dec( &p_port->endpt_rdr ); - cl_obj_unlock( &p_port->obj ); - - return status; -} - - -inline ib_api_status_t -__endpt_mgr_insert( - IN ipoib_port_t* const p_port, - IN const mac_addr_t mac, - IN ipoib_endpt_t* const p_endpt ) -{ - uint64_t key; - cl_status_t cl_status; - cl_map_item_t *p_qitem; - cl_fmap_item_t *p_fitem; - - IPOIB_ENTER( IPOIB_DBG_ENDPT ); - - /* Wait for all accesses to the map to complete. */ - while( p_port->endpt_rdr > 1 ) - ; - - /* Link the endpoint to the port. */ - cl_status = cl_obj_insert_rel_parent_locked( - &p_endpt->rel, &p_port->obj, &p_endpt->obj ); - - if( cl_status != CL_SUCCESS ) - { - cl_obj_destroy( &p_endpt->obj ); - return IB_INVALID_STATE; - } - -#if DBG - cl_atomic_inc( &p_port->ref[ref_endpt_track] ); - IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OBJ, - ("ref type %d ref_cnt %d\n", ref_endpt_track, p_port->obj.ref_cnt) ); -#endif - - p_endpt->mac = mac; - key = 0; - cl_memcpy( &key, &mac, sizeof(mac_addr_t) ); - p_qitem = cl_qmap_insert( - &p_port->endpt_mgr.mac_endpts, key, &p_endpt->mac_item ); - CL_ASSERT( p_qitem == &p_endpt->mac_item ); - p_fitem = cl_fmap_insert( - &p_port->endpt_mgr.gid_endpts, &p_endpt->dgid, &p_endpt->gid_item ); - CL_ASSERT( p_fitem == &p_endpt->gid_item ); - if( p_endpt->dlid ) - { - p_qitem = cl_qmap_insert( - &p_port->endpt_mgr.lid_endpts, p_endpt->dlid, &p_endpt->lid_item ); - CL_ASSERT( p_qitem == &p_endpt->lid_item ); - if (p_qitem != &p_endpt->lid_item) { - // Since we failed to insert into the list, make sure it is not removed - p_endpt->dlid =0; - } - } - - IPOIB_EXIT( IPOIB_DBG_ENDPT ); - return IB_SUCCESS; -} - - -static ib_api_status_t -__endpt_mgr_add_bcast( - IN ipoib_port_t* const p_port, - IN ib_mcast_rec_t *p_mcast_rec ) -{ - ib_api_status_t status; - ipoib_endpt_t *p_endpt; - mac_addr_t bcast_mac; - - IPOIB_ENTER( IPOIB_DBG_INIT ); - - /* - * Cache the broadcast group properties for creating future mcast groups. - */ - p_port->ib_mgr.bcast_rec = *p_mcast_rec->p_member_rec; - - /* Allocate the broadcast endpoint. */ - p_endpt = ipoib_endpt_create( &p_mcast_rec->p_member_rec->mgid, - 0 , CL_HTON32(0x00FFFFFF) ); - if( !p_endpt ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ipoib_endpt_create failed.\n") ); - return IB_INSUFFICIENT_RESOURCES; - } - /* set reference to transport to be used while is not attached to the port */ - p_endpt->is_mcast_listener = TRUE; - p_endpt->p_ifc = p_port->p_adapter->p_ifc; - status = ipoib_endpt_set_mcast( p_endpt, p_port->ib_mgr.h_pd, - p_port->port_num, p_mcast_rec ); - if( status != IB_SUCCESS ) - { - cl_obj_destroy( &p_endpt->obj ); - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ipoib_create_mcast_endpt returned %s\n", - p_port->p_adapter->p_ifc->get_err_str( status )) ); - return status; - } - - /* Add the broadcast endpoint to the endpoint map. */ - cl_memset( &bcast_mac, 0xFF, sizeof(bcast_mac) ); - status = __endpt_mgr_insert_locked( p_port, bcast_mac, p_endpt ); - - IPOIB_EXIT( IPOIB_DBG_INIT ); - return status; -} - - -void -ipoib_port_remove_endpt( - IN ipoib_port_t* const p_port, - IN const mac_addr_t mac ) -{ - cl_map_item_t *p_item; - //TODO CM -// cl_fmap_item_t *p_fmap_item; - ipoib_endpt_t *p_endpt; - uint64_t key; - - IPOIB_ENTER( IPOIB_DBG_ENDPT ); - - key = 0; - cl_memcpy( &key, &mac, sizeof(mac_addr_t) ); - - /* Remove the endpoint from the maps so further requests don't find it. */ - cl_obj_lock( &p_port->obj ); - /* Wait for all readers to finish */ - while( p_port->endpt_rdr ) - ; - p_item = cl_qmap_remove( &p_port->endpt_mgr.mac_endpts, key ); - /* - * Dereference the endpoint. If the ref count goes to zero, it - * will get freed. - */ - if( p_item != cl_qmap_end( &p_port->endpt_mgr.mac_endpts ) ) - { - p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item ); - /* - * The enpoints are *ALWAYS* in both the MAC and GID maps. They are only - * in the LID map if the GID has the same subnet prefix as us. - */ - cl_fmap_remove_item( - &p_port->endpt_mgr.gid_endpts, &p_endpt->gid_item ); -#if 0 - if( p_port->p_adapter->params.cm_enabled ) - { - p_fmap_item = cl_fmap_get( &p_port->endpt_mgr.conn_endpts, &p_endpt->dgid ); - - if( p_fmap_item != cl_fmap_end( &p_port->endpt_mgr.conn_endpts ) ) - { - cl_fmap_remove_item( &p_port->endpt_mgr.conn_endpts, - &p_endpt->conn_item ); - } - } -#endif - - if( p_endpt->dlid ) - { - cl_qmap_remove_item( - &p_port->endpt_mgr.lid_endpts, &p_endpt->lid_item ); - } - - cl_obj_unlock( &p_port->obj ); - //TODO CM - //endpt_cm_destroy_conn( p_port, p_endpt ); - -#if DBG - cl_atomic_dec( &p_port->ref[ref_endpt_track] ); - IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT, - ("ref type %d ref_cnt %d\n", ref_endpt_track, p_port->obj.ref_cnt) ); -#endif - - } - else - { - cl_obj_unlock( &p_port->obj ); - } - - IPOIB_EXIT( IPOIB_DBG_ENDPT ); -} - -/* - * The sequence for port up is as follows: - * 1. The port goes active. This allows the adapter to send SA queries - * and join the broadcast group (and other groups). - * - * 2. The adapter sends an SA query for the broadcast group. - * - * 3. Upon completion of the query, the adapter joins the broadcast group. - */ - - -/* - * Query the SA for the broadcast group. - */ -void -ipoib_port_up( - IN ipoib_port_t* const p_port, - IN const ib_pnp_port_rec_t* const p_pnp_rec ) -{ - ib_port_info_t *p_port_info; - ib_mad_t *mad_in = NULL; - ib_mad_t *mad_out = NULL; - ib_api_status_t status = IB_INSUFFICIENT_MEMORY; - static int cnt = 0; - - IPOIB_ENTER( IPOIB_DBG_INIT ); - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_INIT, - ("[%d] Entering port_up.\n", ++cnt) ); - - cl_obj_lock( &p_port->obj ); - if ( p_port->state == IB_QPS_INIT ) - { - cl_obj_unlock( &p_port->obj ); - status = IB_SUCCESS; - IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, - ("p_port->state = %d - Aborting.\n", p_port->state) ); - goto up_done; - } - else if ( p_port->state == IB_QPS_RTS ) - { - cl_obj_unlock( &p_port->obj ); - cl_obj_lock( &p_port->p_adapter->obj ); - if( p_port->p_adapter->state == IB_PNP_PORT_INIT ) - { - p_port->p_adapter->state = IB_PNP_PORT_ACTIVE; - } - cl_obj_unlock( &p_port->p_adapter->obj ); - status = IB_SUCCESS; - IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, - ("Port init is done. p_port->state = %d.\n", p_port->state ) ); - goto up_done; - } - p_port->state = IB_QPS_INIT; - cl_obj_unlock( &p_port->obj ); - - - /* Wait for all work requests to get flushed. */ - while( p_port->recv_mgr.depth || p_port->send_mgr.depth ) - cl_thread_suspend( 0 ); - - KeResetEvent( &p_port->sa_event ); - - mad_out = (ib_mad_t*)cl_zalloc(256); - if(! mad_out) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("failed to allocate mad mad_out\n")); - goto up_done; - } - mad_in = (ib_mad_t*)cl_zalloc(256); - if(! mad_in) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("failed to allocate mad mad_in\n")); - goto up_done; - } - - mad_in->attr_id = IB_MAD_ATTR_PORT_INFO; - mad_in->method = IB_MAD_METHOD_GET; - mad_in->base_ver = 1; - mad_in->class_ver =1; - mad_in->mgmt_class = IB_MCLASS_SUBN_LID; - - status = p_port->p_adapter->p_ifc->local_mad( - p_port->ib_mgr.h_ca ,p_port->port_num ,mad_in ,mad_out); - - if( status != IB_SUCCESS ) - { - ipoib_set_inactive( p_port->p_adapter ); - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ib_local_mad returned %s\n", - p_port->p_adapter->p_ifc->get_err_str( status )) ); - goto up_done; - } - - p_port_info = (ib_port_info_t*)(((ib_smp_t*)mad_out)->data); - p_port->base_lid = p_pnp_rec->p_port_attr->lid; - IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, - ("Received port info: link width = %d.\n", - p_port_info->link_width_active) ); - p_port->ib_mgr.rate = - ib_port_info_compute_rate( p_port_info ); - - ipoib_set_rate( p_port->p_adapter, - p_port_info->link_width_active, - ib_port_info_get_link_speed_active( p_port_info ) ); - - status = __port_get_bcast( p_port ); - if (status != IB_SUCCESS) - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - (" __port_get_bcast returned %s\n",p_port->p_adapter->p_ifc->get_err_str( status ))); - -up_done: - if( status != IB_SUCCESS ) - { - if( status != IB_CANCELED ) - { - ipoib_set_inactive( p_port->p_adapter ); - __endpt_mgr_reset_all( p_port ); - } - ASSERT(p_port->state == IB_QPS_INIT || p_port->state == IB_QPS_ERROR); - p_port->state = IB_QPS_ERROR; - KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE ); - } - - if(mad_out) - cl_free(mad_out); - if(mad_in) - cl_free(mad_in); - - IPOIB_EXIT( IPOIB_DBG_INIT ); -} - - -static ib_api_status_t -__endpt_mgr_add_local( - IN ipoib_port_t* const p_port, - IN ib_port_info_t* const p_port_info ) -{ - ib_api_status_t status; - ib_gid_t gid; - ipoib_endpt_t *p_endpt; - ib_av_attr_t av_attr; - - IPOIB_ENTER( IPOIB_DBG_INIT ); - - ib_gid_set_default( &gid, p_port->p_adapter->guids.port_guid.guid ); - p_endpt = ipoib_endpt_create( - &gid, p_port_info->base_lid, p_port->ib_mgr.qpn ); - if( !p_endpt ) - { - p_port->p_adapter->hung = TRUE; - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed to create local endpt\n") ); - return IB_INSUFFICIENT_MEMORY; - } - - cl_memclr( &av_attr, sizeof(ib_av_attr_t) ); - av_attr.port_num = p_port->port_num; - av_attr.sl = 0; - IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT, - (" av_attr.dlid = p_port_info->base_lid = %d\n", cl_ntoh16( p_port_info->base_lid ) )); - av_attr.dlid = p_port_info->base_lid; - av_attr.static_rate = p_port->ib_mgr.rate; - av_attr.path_bits = 0; - status = p_port->p_adapter->p_ifc->create_av( - p_port->ib_mgr.h_pd, &av_attr, &p_endpt->h_av ); - if( status != IB_SUCCESS ) - { - cl_obj_destroy( &p_endpt->obj ); - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ib_create_av for local endpoint returned %s\n", - p_port->p_adapter->p_ifc->get_err_str( status )) ); - return status; - } - - /* __endpt_mgr_insert expects *one* reference to be held. */ - cl_atomic_inc( &p_port->endpt_rdr ); - status = __endpt_mgr_insert( p_port, p_port->p_adapter->params.conf_mac, p_endpt ); - cl_atomic_dec( &p_port->endpt_rdr ); - if( status != IB_SUCCESS ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("__endpt_mgr_insert for local endpoint returned %s\n", - p_port->p_adapter->p_ifc->get_err_str( status )) ); - return status; - } - - p_port->p_local_endpt = p_endpt; - - IPOIB_EXIT( IPOIB_DBG_INIT ); - return status; -} - - - - -static ib_api_status_t -__port_get_bcast( - IN ipoib_port_t* const p_port ) -{ - ib_api_status_t status; - ib_query_req_t query; - ib_user_query_t info; - ib_member_rec_t member_rec; - - IPOIB_ENTER( IPOIB_DBG_INIT ); - - info.method = IB_MAD_METHOD_GETTABLE; - info.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD; - info.attr_size = sizeof(ib_member_rec_t); - info.comp_mask = IB_MCR_COMPMASK_MGID; - info.p_attr = &member_rec; - - /* Query requires only the MGID. */ - cl_memclr( &member_rec, sizeof(ib_member_rec_t) ); - member_rec.mgid = bcast_mgid_template; - - member_rec.mgid.raw[4] = (uint8_t) (p_port->p_adapter->guids.port_guid.pkey >> 8) ; - member_rec.mgid.raw[5] = (uint8_t) p_port->p_adapter->guids.port_guid.pkey; - member_rec.pkey = cl_hton16(p_port->p_adapter->guids.port_guid.pkey); - cl_memclr( &query, sizeof(ib_query_req_t) ); - query.query_type = IB_QUERY_USER_DEFINED; - query.p_query_input = &info; - query.port_guid = p_port->p_adapter->guids.port_guid.guid; - query.timeout_ms = p_port->p_adapter->params.sa_timeout; - query.retry_cnt = p_port->p_adapter->params.sa_retry_cnt; - query.query_context = p_port; - query.pfn_query_cb = __bcast_get_cb; - - /* reference the object for the multicast query. */ - ipoib_port_ref( p_port, ref_get_bcast ); - - status = p_port->p_adapter->p_ifc->query( - p_port->p_adapter->h_al, &query, &p_port->ib_mgr.h_query ); - if( status != IB_SUCCESS ) - { - ipoib_port_deref( p_port, ref_get_bcast ); - ASSERT(FALSE); - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ib_query returned %s\n", - p_port->p_adapter->p_ifc->get_err_str( status )) ); - } - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ib_query returned SUCCESS\n")); - IPOIB_EXIT( IPOIB_DBG_INIT ); - return status; -} - - -/* Callback for the MCMemberRecord Get query for the IPv4 broadcast group. */ -static void -__bcast_get_cb( - IN ib_query_rec_t *p_query_rec ) -{ - ipoib_port_t *p_port; - ib_member_rec_t *p_mc_req; - ib_api_status_t status; - - IPOIB_ENTER( IPOIB_DBG_INIT ); - - p_port = (ipoib_port_t*)p_query_rec->query_context; - - cl_obj_lock( &p_port->obj ); - p_port->ib_mgr.h_query = NULL; - - CL_ASSERT(p_port->state == IB_QPS_INIT || p_port->state == IB_QPS_ERROR); - if( p_port->state != IB_QPS_INIT ) - { - status = IB_CANCELED; - goto done; - } - - status = p_query_rec->status; - - IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, - ("status of request %s\n", - p_port->p_adapter->p_ifc->get_err_str( status )) ); - - switch( status ) - { - case IB_SUCCESS: - if( p_query_rec->result_cnt ) - { - p_mc_req = (ib_member_rec_t*) - ib_get_query_result( p_query_rec->p_result_mad, 0 ); - - /* Join the broadcast group. */ - status = __port_join_bcast( p_port, p_mc_req ); - break; - } - /* Fall through. */ - - case IB_REMOTE_ERROR: - /* SA failed the query. Broadcast group doesn't exist, create it. */ - status = __port_create_bcast( p_port ); - break; - - case IB_CANCELED: - IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, - ("Instance destroying - Aborting.\n") ); - break; - - default: - NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, - EVENT_IPOIB_BCAST_GET, 1, p_query_rec->status ); - } -done: - cl_obj_unlock( &p_port->obj ); - - if( status != IB_SUCCESS ) - { - if( status != IB_CANCELED ) - { - ipoib_set_inactive( p_port->p_adapter ); - __endpt_mgr_reset_all( p_port ); - } - p_port->state = IB_QPS_ERROR; - KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE ); - } - - /* Return the response MAD to AL. */ - if( p_query_rec->p_result_mad ) - p_port->p_adapter->p_ifc->put_mad( p_query_rec->p_result_mad ); - - /* Release the reference taken when issuing the member record query. */ - ipoib_port_deref( p_port, ref_bcast_get_cb ); - - IPOIB_EXIT( IPOIB_DBG_INIT ); -} - - -static ib_api_status_t -__port_join_bcast( - IN ipoib_port_t* const p_port, - IN ib_member_rec_t* const p_member_rec ) -{ - ib_api_status_t status; - ib_mcast_req_t mcast_req; - - IPOIB_ENTER( IPOIB_DBG_INIT ); - - /* Check that the rate is realizable for our port. */ - if( p_port->ib_mgr.rate < (p_member_rec->rate & 0x3F) && - (g_ipoib.bypass_check_bcast_rate == 0)) - { - /* - * The MC group rate is higher than our port's rate. Log an error - * and stop. A port transition will drive the retry. - */ - IPOIB_PRINT(TRACE_LEVEL_WARNING, IPOIB_DBG_INIT, - ("Unrealizable join due to rate mismatch.\n") ); - NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, - EVENT_IPOIB_BCAST_RATE, 2, - (uint32_t)(p_member_rec->rate & 0x3F), - (uint32_t)p_port->ib_mgr.rate ); - return IB_ERROR; - } - - /* Join the broadcast group. */ - cl_memclr( &mcast_req, sizeof(mcast_req) ); - /* Copy the results of the Get to use as parameters. */ - mcast_req.member_rec = *p_member_rec; - /* We specify our port GID for the join operation. */ - mcast_req.member_rec.port_gid.unicast.prefix = IB_DEFAULT_SUBNET_PREFIX; - mcast_req.member_rec.port_gid.unicast.interface_id = - p_port->p_adapter->guids.port_guid.guid; - - mcast_req.mcast_context = p_port; - mcast_req.pfn_mcast_cb = __bcast_cb; - mcast_req.timeout_ms = p_port->p_adapter->params.sa_timeout; - mcast_req.retry_cnt = p_port->p_adapter->params.sa_retry_cnt; - mcast_req.port_guid = p_port->p_adapter->guids.port_guid.guid; - mcast_req.pkey_index = p_port->pkey_index; - - if( ib_member_get_state( mcast_req.member_rec.scope_state ) != - IB_MC_REC_STATE_FULL_MEMBER ) - { - IPOIB_PRINT(TRACE_LEVEL_WARNING, IPOIB_DBG_INIT, - ("Incorrect MC member rec join state in query response.\n") ); - ib_member_set_state( &mcast_req.member_rec.scope_state, - IB_MC_REC_STATE_FULL_MEMBER ); - } - - /* reference the object for the multicast join request. */ - ipoib_port_ref( p_port, ref_join_bcast ); - - status = p_port->p_adapter->p_ifc->join_mcast( - p_port->ib_mgr.h_qp, &mcast_req ); - if( status != IB_SUCCESS ) - { - ipoib_port_deref( p_port, ref_bcast_join_failed ); - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ib_join_mcast returned %s\n", - p_port->p_adapter->p_ifc->get_err_str( status )) ); - } - IPOIB_EXIT( IPOIB_DBG_INIT ); - return status; -} - - -static ib_api_status_t -__port_create_bcast( - IN ipoib_port_t* const p_port ) -{ - ib_api_status_t status; - ib_mcast_req_t mcast_req; - - IPOIB_ENTER( IPOIB_DBG_INIT ); - - /* Join the broadcast group. */ - cl_memclr( &mcast_req, sizeof(mcast_req) ); - mcast_req.create = TRUE; - /* - * Create requires pkey, qkey, SL, flow label, traffic class, joing state - * and port GID. - * - * We specify the MGID since we don't want the SA to generate it for us. - */ - mcast_req.member_rec.mgid = bcast_mgid_template; - mcast_req.member_rec.mgid.raw[4] = (uint8_t) (p_port->p_adapter->guids.port_guid.pkey >> 8); - mcast_req.member_rec.mgid.raw[5] = (uint8_t) p_port->p_adapter->guids.port_guid.pkey; - ib_gid_set_default( &mcast_req.member_rec.port_gid, - p_port->p_adapter->guids.port_guid.guid ); - /* - * IPOIB spec requires that the QKEY have the MSb set so that the QKEY - * from the QP is used rather than the QKEY in the send WR. - */ - mcast_req.member_rec.qkey = - (uint32_t)(uintn_t)p_port | IB_QP_PRIVILEGED_Q_KEY; - mcast_req.member_rec.mtu = - (IB_PATH_SELECTOR_EXACTLY << 6) | IB_MTU_LEN_2048; - - mcast_req.member_rec.pkey = cl_hton16(p_port->p_adapter->guids.port_guid.pkey); - - mcast_req.member_rec.sl_flow_hop = ib_member_set_sl_flow_hop( 0, 0, 0 ); - mcast_req.member_rec.scope_state = - ib_member_set_scope_state( 2, IB_MC_REC_STATE_FULL_MEMBER ); - - mcast_req.mcast_context = p_port; - mcast_req.pfn_mcast_cb = __bcast_cb; - mcast_req.timeout_ms = p_port->p_adapter->params.sa_timeout; - mcast_req.retry_cnt = p_port->p_adapter->params.sa_retry_cnt; - mcast_req.port_guid = p_port->p_adapter->guids.port_guid.guid; - mcast_req.pkey_index = p_port->pkey_index; - - /* reference the object for the multicast join request. */ - ipoib_port_ref( p_port, ref_join_bcast ); - - status = p_port->p_adapter->p_ifc->join_mcast( p_port->ib_mgr.h_qp, &mcast_req ); - if( status != IB_SUCCESS ) - { - ipoib_port_deref( p_port, ref_bcast_create_failed ); - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ib_join_mcast returned %s\n", - p_port->p_adapter->p_ifc->get_err_str( status )) ); - } - IPOIB_EXIT( IPOIB_DBG_INIT ); - return status; -} - - -void -ipoib_port_down( - IN ipoib_port_t* const p_port ) -{ - ib_api_status_t status; - ib_qp_mod_t qp_mod; - - IPOIB_ENTER( IPOIB_DBG_INIT ); - - /* - * Mark our state. This causes all callbacks to abort. - * Note that we hold the receive lock so that we synchronize - * with reposting. We must take the receive lock before the - * object lock since that is the order taken when reposting. - */ - cl_spinlock_acquire( &p_port->recv_lock ); - cl_obj_lock( &p_port->obj ); - p_port->state = IB_QPS_ERROR; - - NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, - EVENT_IPOIB_PORT_DOWN, 0 ); - - if( p_port->ib_mgr.h_query ) - { - p_port->p_adapter->p_ifc->cancel_query( - p_port->p_adapter->h_al, p_port->ib_mgr.h_query ); - p_port->ib_mgr.h_query = NULL; - } - cl_obj_unlock( &p_port->obj ); - cl_spinlock_release( &p_port->recv_lock ); - - KeWaitForSingleObject( - &p_port->sa_event, Executive, KernelMode, FALSE, NULL ); - - /* garbage collector timer is not needed when link is down */ - KeCancelTimer(&p_port->gc_timer); - KeFlushQueuedDpcs(); - - /* - * Put the QP in the error state. This removes the need to - * synchronize with send/receive callbacks. - */ - CL_ASSERT( p_port->ib_mgr.h_qp ); - cl_memclr( &qp_mod, sizeof(ib_qp_mod_t) ); - qp_mod.req_state = IB_QPS_ERROR; - status = p_port->p_adapter->p_ifc->modify_qp( p_port->ib_mgr.h_qp, &qp_mod ); - if( status != IB_SUCCESS ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ib_modify_qp to error state returned %s.\n", - p_port->p_adapter->p_ifc->get_err_str( status )) ); - p_port->p_adapter->hung = TRUE; - return; - } - - KeResetEvent(&p_port->leave_mcast_event); - - /* Reset all endpoints so we don't flush our ARP cache. */ - __endpt_mgr_reset_all( p_port ); - - KeWaitForSingleObject( - &p_port->leave_mcast_event, Executive, KernelMode, FALSE, NULL ); - - __pending_list_destroy(p_port); - - cl_obj_lock( &p_port->p_adapter->obj ); - ipoib_dereg_addrs( p_port->p_adapter ); - cl_obj_unlock( &p_port->p_adapter->obj ); - - IPOIB_EXIT( IPOIB_DBG_INIT ); -} - - -static void -__bcast_cb( - IN ib_mcast_rec_t *p_mcast_rec ) -{ - ipoib_port_t *p_port; - ib_api_status_t status; - LARGE_INTEGER gc_due_time; - - IPOIB_ENTER( IPOIB_DBG_INIT ); - - p_port = (ipoib_port_t*)p_mcast_rec->mcast_context; - - cl_obj_lock( &p_port->obj ); - - ASSERT(p_port->state == IB_QPS_INIT || p_port->state == IB_QPS_ERROR); - if( p_port->state != IB_QPS_INIT ) - { - cl_obj_unlock( &p_port->obj ); - if( p_mcast_rec->status == IB_SUCCESS ) - { - ipoib_port_ref(p_port, ref_leave_mcast); - p_port->p_adapter->p_ifc->leave_mcast( p_mcast_rec->h_mcast, __leave_error_mcast_cb ); - } - KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE ); - ipoib_port_deref( p_port, ref_bcast_inv_state ); - IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, - ("Invalid state - Aborting.\n") ); - return; - } - status = p_mcast_rec->status; - if( status != IB_SUCCESS ) - { - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Multicast join for broadcast group returned %s.\n", - p_port->p_adapter->p_ifc->get_err_str( p_mcast_rec->status )) ); - if( status == IB_REMOTE_ERROR ) - { - /* - * Either: - * - the join failed because the group no longer exists - * - the create failed because the group already exists - * - * Kick off a new Get query to the SA to restart the join process - * from the top. Note that as an optimization, it would be - * possible to distinguish between the join and the create. - * If the join fails, try the create. If the create fails, start - * over with the Get. - */ - /* TODO: Assert is a place holder. Can we ever get here if the - state isn't IB_PNP_PORT_ADD or PORT_DOWN or PORT_INIT? */ - CL_ASSERT( p_port->p_adapter->state == IB_PNP_PORT_ADD || - p_port->p_adapter->state == IB_PNP_PORT_DOWN || - p_port->p_adapter->state == IB_PNP_PORT_INIT ); - if(++p_port->bc_join_retry_cnt < p_port->p_adapter->params.bc_join_retry) - { - status = __port_get_bcast( p_port ); - } - else - { - NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, - EVENT_IPOIB_BCAST_JOIN, 1, p_mcast_rec->status ); - p_port->bc_join_retry_cnt = 0; - } - } - else - { - NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, - EVENT_IPOIB_BCAST_JOIN, 1, p_mcast_rec->status ); - } - - cl_obj_unlock( &p_port->obj ); - if( status != IB_SUCCESS ) - { - ipoib_set_inactive( p_port->p_adapter ); - __endpt_mgr_reset_all( p_port ); - ASSERT(p_port->state == IB_QPS_INIT || p_port->state == IB_QPS_ERROR); - p_port->state = IB_QPS_ERROR; - KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE ); - } - ipoib_port_deref( p_port, ref_bcast_req_failed ); - IPOIB_EXIT( IPOIB_DBG_INIT ); - return; - } - p_port->bc_join_retry_cnt = 0; - - while( p_port->endpt_rdr ) - { - cl_obj_unlock( &p_port->obj ); - cl_obj_lock( &p_port->obj ); - } - - if( !p_port->p_local_endpt ) - { - ib_port_info_t port_info; - cl_memclr(&port_info, sizeof(port_info)); - port_info.base_lid = p_port->base_lid; - status = __endpt_mgr_add_local( p_port, &port_info ); - if( status != IB_SUCCESS ) - { - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("__endpt_mgr_add_local returned %s\n", - p_port->p_adapter->p_ifc->get_err_str( status )) ); - cl_obj_unlock( &p_port->obj ); - goto err; - } - } - - cl_obj_unlock( &p_port->obj ); - - status = __endpt_mgr_add_bcast( p_port, p_mcast_rec ); - if( status != IB_SUCCESS ) - { - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("__endpt_mgr_add_bcast returned %s\n", - p_port->p_adapter->p_ifc->get_err_str( status )) ); - ipoib_port_ref(p_port, ref_leave_mcast); - status = p_port->p_adapter->p_ifc->leave_mcast( p_mcast_rec->h_mcast, __leave_error_mcast_cb ); - CL_ASSERT( status == IB_SUCCESS ); - goto err; - } - - /* Get the QP ready for action. */ - status = __ib_mgr_activate( p_port ); - if( status != IB_SUCCESS ) - { - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("__ib_mgr_activate returned %s\n", - p_port->p_adapter->p_ifc->get_err_str( status )) ); - -err: - /* Flag the adapter as hung. */ - p_port->p_adapter->hung = TRUE; - ASSERT(p_port->state == IB_QPS_INIT || p_port->state == IB_QPS_ERROR); - p_port->state = IB_QPS_ERROR; - KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE ); - ipoib_port_deref( p_port, ref_bcast_error ); - IPOIB_EXIT( IPOIB_DBG_INIT ); - return; - } - - cl_obj_lock( &p_port->obj ); - /* Only change the state if we're still in INIT. */ - ASSERT( p_port->state == IB_QPS_INIT || p_port->state == IB_QPS_ERROR); - if (p_port->state == IB_QPS_INIT) { - p_port->state = IB_QPS_RTS; - } - cl_obj_unlock( &p_port->obj ); - - /* Prepost receives. */ - cl_spinlock_acquire( &p_port->recv_lock ); - __recv_mgr_repost( p_port ); - cl_spinlock_release( &p_port->recv_lock ); - - /* Notify the adapter that we now have an active connection. */ - status = ipoib_set_active( p_port->p_adapter ); - if( status != IB_SUCCESS ) - { - ib_qp_mod_t qp_mod; - ipoib_set_inactive( p_port->p_adapter ); - KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE ); - IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, - ("ipoib_set_active returned %s.\n",p_port->p_adapter->p_ifc->get_err_str( status ))); - cl_spinlock_acquire( &p_port->recv_lock ); - cl_obj_lock( &p_port->obj ); - p_port->state = IB_QPS_ERROR; - if( p_port->ib_mgr.h_query ) - { - p_port->p_adapter->p_ifc->cancel_query( - p_port->p_adapter->h_al, p_port->ib_mgr.h_query ); - p_port->ib_mgr.h_query = NULL; - } - cl_obj_unlock( &p_port->obj ); - cl_spinlock_release( &p_port->recv_lock ); - - CL_ASSERT( p_port->ib_mgr.h_qp ); - cl_memclr( &qp_mod, sizeof(ib_qp_mod_t) ); - qp_mod.req_state = IB_QPS_ERROR; - status = p_port->p_adapter->p_ifc->modify_qp( p_port->ib_mgr.h_qp, &qp_mod ); - __endpt_mgr_reset_all( p_port ); - - ipoib_port_deref( p_port, ref_join_bcast ); - return; - } -#if 0 //CM - if( p_port->p_adapter->params.cm_enabled && - !p_port->p_local_endpt->conn.h_cm_listen ) - { - if( ipoib_port_listen( p_port ) != IB_SUCCESS ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Port CM Listen failed\n" ) ); - /*keep going with UD only */ - p_port->p_adapter->params.cm_enabled = FALSE; - - NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, - EVENT_IPOIB_CONNECTED_MODE_ERR, 1, 0xbadc0de3 ); - } - } -#endif - /* garbage collector timer is needed when link is active */ - gc_due_time.QuadPart = -(int64_t)(((uint64_t)p_port->p_adapter->params.mc_leave_rescan * 2000000) * 10); - KeSetTimerEx(&p_port->gc_timer,gc_due_time, - (LONG)p_port->p_adapter->params.mc_leave_rescan*1000,&p_port->gc_dpc); - - KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE ); - ipoib_port_deref( p_port, ref_join_bcast ); - IPOIB_EXIT( IPOIB_DBG_INIT ); -} - - -static void -__qp_event( - IN ib_async_event_rec_t *p_event_rec ) -{ - UNUSED_PARAM( p_event_rec ); - CL_ASSERT( p_event_rec->context ); - ((ipoib_port_t*)p_event_rec->context)->p_adapter->hung = TRUE; -} - - -static void -__cq_event( - IN ib_async_event_rec_t *p_event_rec ) -{ - UNUSED_PARAM( p_event_rec ); - CL_ASSERT( p_event_rec->context ); - ((ipoib_port_t*)p_event_rec->context)->p_adapter->hung = TRUE; -} - - -static ib_api_status_t -__ib_mgr_activate( - IN ipoib_port_t* const p_port ) -{ - ib_api_status_t status; - ib_dgrm_info_t dgrm_info; - ib_qp_mod_t qp_mod; - - IPOIB_ENTER( IPOIB_DBG_INIT ); - /* - * Move the QP to RESET. This allows us to reclaim any - * unflushed receives. - */ - cl_memclr( &qp_mod, sizeof(ib_qp_mod_t) ); - qp_mod.req_state = IB_QPS_RESET; - status = p_port->p_adapter->p_ifc->modify_qp( p_port->ib_mgr.h_qp, &qp_mod ); - if( status != IB_SUCCESS ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ib_modify_qp returned %s\n", - p_port->p_adapter->p_ifc->get_err_str( status )) ); - return status; - } - - /* Move the QP to RTS. */ - dgrm_info.port_guid = p_port->p_adapter->guids.port_guid.guid; - dgrm_info.qkey = p_port->ib_mgr.bcast_rec.qkey; - dgrm_info.pkey_index = p_port->pkey_index; - status = p_port->p_adapter->p_ifc->init_dgrm_svc( p_port->ib_mgr.h_qp, &dgrm_info ); - if( status != IB_SUCCESS ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ib_init_dgrm_svc returned %s\n", - p_port->p_adapter->p_ifc->get_err_str( status )) ); - return status; - } - - /* Rearm the CQs. */ - status = p_port->p_adapter->p_ifc->rearm_cq( p_port->ib_mgr.h_recv_cq, FALSE ); - if( status != IB_SUCCESS ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ib_rearm_cq for recv returned %s\n", - p_port->p_adapter->p_ifc->get_err_str( status )) ); - return status; - } - status = p_port->p_adapter->p_ifc->rearm_cq( p_port->ib_mgr.h_send_cq, FALSE ); - if( status != IB_SUCCESS ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ib_rearm_cq for send returned %s\n", - p_port->p_adapter->p_ifc->get_err_str( status )) ); - return status; - } - - IPOIB_EXIT( IPOIB_DBG_INIT ); - return IB_SUCCESS; -} - - -/* Transition to a passive level thread. */ -ib_api_status_t -ipoib_port_join_mcast( - IN ipoib_port_t* const p_port, - IN const mac_addr_t mac, - IN const uint8_t state) -{ - ib_api_status_t status; - ib_mcast_req_t mcast_req; - ipoib_endpt_t *p_endpt; - - IPOIB_ENTER( IPOIB_DBG_MCAST ); - - switch( __endpt_mgr_ref( p_port, mac, &p_endpt ) ) - { - case NDIS_STATUS_NO_ROUTE_TO_DESTINATION: - break; - - case NDIS_STATUS_SUCCESS: - ipoib_endpt_deref( p_endpt ); - /* Fall through */ - - case NDIS_STATUS_PENDING: - return IB_SUCCESS; - } - - /* - * Issue the mcast request, using the parameters of the broadcast group. - * This allows us to do a create request that should always succeed since - * the required parameters are known. - */ - cl_memclr( &mcast_req, sizeof(mcast_req) ); - mcast_req.create = TRUE; - - /* Copy the settings from the broadcast group. */ - mcast_req.member_rec = p_port->ib_mgr.bcast_rec; - /* Clear fields that aren't specified in the join */ - mcast_req.member_rec.mlid = 0; - ib_member_set_state( &mcast_req.member_rec.scope_state,state); - - if( (mac.addr[0] == 1) && (mac.addr[2] == 0x5E )) - { - /* - * Update the address portion of the MGID with the 28 lower bits of the - * IP address. Since we're given a MAC address, we are using - * 24 lower bits of that network-byte-ordered value (assuming MSb - * is zero) and 4 lsb bits of the first byte of IP address. - */ - mcast_req.member_rec.mgid.raw[12] = mac.addr[1]; - mcast_req.member_rec.mgid.raw[13] = mac.addr[3]; - mcast_req.member_rec.mgid.raw[14] = mac.addr[4]; - mcast_req.member_rec.mgid.raw[15] = mac.addr[5]; - } - else - { - /* Handle non IP mutlicast MAC addresses. */ - /* Update the signature to use the lower 2 bytes of the OpenIB OUI. */ - mcast_req.member_rec.mgid.raw[2] = 0x14; - mcast_req.member_rec.mgid.raw[3] = 0x05; - /* Now copy the MAC address into the last 6 bytes of the GID. */ - cl_memcpy( &mcast_req.member_rec.mgid.raw[10], mac.addr, 6 ); - } - - mcast_req.mcast_context = p_port; - mcast_req.pfn_mcast_cb = __mcast_cb; - mcast_req.timeout_ms = p_port->p_adapter->params.sa_timeout; - mcast_req.retry_cnt = p_port->p_adapter->params.sa_retry_cnt; - mcast_req.port_guid = p_port->p_adapter->guids.port_guid.guid; - mcast_req.pkey_index = p_port->pkey_index; - mcast_req.member_rec.pkey = cl_hton16(p_port->p_adapter->guids.port_guid.pkey); - /* - * Create the endpoint and insert it in the port. Since we don't wait for - * the mcast SA operations to complete before returning from the multicast - * list set OID asynchronously, it is possible for the mcast entry to be - * cleared before the SA interaction completes. In this case, when the - * mcast callback is invoked, it would not find the corresponding endpoint - * and would be undone. - */ - p_endpt = ipoib_endpt_create( - &mcast_req.member_rec.mgid, 0, CL_HTON32(0x00FFFFFF) ); - if( !p_endpt ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ipoib_endpt_create failed.\n") ); - return IB_INSUFFICIENT_MEMORY; - } - - status = __endpt_mgr_insert_locked( p_port, mac, p_endpt ); - if( status != IB_SUCCESS ) - { - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("__endpt_mgr_insert_locked returned %s\n", - p_port->p_adapter->p_ifc->get_err_str( status )) ); - return status; - } - - /* reference the object for the multicast join request. */ - ipoib_port_ref( p_port, ref_join_mcast ); - - status = p_port->p_adapter->p_ifc->join_mcast( p_port->ib_mgr.h_qp, &mcast_req ); - if( status != IB_SUCCESS ) - { - ipoib_port_deref( p_port, ref_mcast_join_failed ); - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("ib_join_mcast returned %s\n", - p_port->p_adapter->p_ifc->get_err_str( status )) ); - } - - IPOIB_EXIT( IPOIB_DBG_MCAST ); - return status; -} - - -static void -__mcast_cb( - IN ib_mcast_rec_t *p_mcast_rec ) -{ - ib_api_status_t status; - ipoib_port_t *p_port; - cl_fmap_item_t *p_item; - ipoib_endpt_t *p_endpt; - - IPOIB_ENTER( IPOIB_DBG_MCAST ); - - p_port = (ipoib_port_t*)p_mcast_rec->mcast_context; - - cl_obj_lock( &p_port->obj ); - while( p_port->endpt_rdr ) - { - cl_obj_unlock( &p_port->obj ); - cl_obj_lock( &p_port->obj ); - } - if( p_port->state != IB_QPS_RTS ) - { - cl_obj_unlock( &p_port->obj ); - if( p_mcast_rec->status == IB_SUCCESS ) - - { - ipoib_port_ref(p_port, ref_leave_mcast); - p_port->p_adapter->p_ifc->leave_mcast( p_mcast_rec->h_mcast, __leave_error_mcast_cb ); - } - ipoib_port_deref( p_port, ref_mcast_inv_state ); - IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, - ("Invalid state - Aborting.\n") ); - return; - } - - if( p_mcast_rec->status != IB_SUCCESS ) - { - cl_obj_unlock( &p_port->obj ); - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Multicast join request failed with status %s.\n", - p_port->p_adapter->p_ifc->get_err_str( p_mcast_rec->status )) ); - /* Flag the adapter as hung. */ - p_port->p_adapter->hung =TRUE; - ipoib_port_deref( p_port, ref_mcast_req_failed ); - IPOIB_EXIT( IPOIB_DBG_MCAST ); - return; - } - - p_item = cl_fmap_get( - &p_port->endpt_mgr.gid_endpts, &p_mcast_rec->p_member_rec->mgid ); - if( p_item == cl_fmap_end( &p_port->endpt_mgr.gid_endpts ) ) - { - /* - * The endpoint must have been flushed while the join request - * was outstanding. Just leave the group and return. This - * is not an error. - */ - cl_obj_unlock( &p_port->obj ); - IPOIB_PRINT(TRACE_LEVEL_WARNING, IPOIB_DBG_ERROR, - ("Failed to find endpoint for update.\n") ); - - ipoib_port_ref(p_port, ref_leave_mcast); - p_port->p_adapter->p_ifc->leave_mcast( p_mcast_rec->h_mcast, __leave_error_mcast_cb ); - ipoib_port_deref( p_port, ref_mcast_no_endpt ); - IPOIB_EXIT( IPOIB_DBG_MCAST ); - return; - } - - p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, gid_item ); - p_endpt->p_ifc = p_port->p_adapter->p_ifc; - - /* Setup the endpoint for use. */ - status = ipoib_endpt_set_mcast( - p_endpt, p_port->ib_mgr.h_pd, p_port->port_num, p_mcast_rec ); - if( status != IB_SUCCESS ) - { - cl_obj_unlock( &p_port->obj ); - IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_MCAST, - ("ipoib_endpt_set_mcast returned %s.\n", - p_port->p_adapter->p_ifc->get_err_str( status )) ); - /* Flag the adapter as hung. */ - p_port->p_adapter->hung = TRUE; - ipoib_port_deref( p_port, ref_mcast_av_failed ); - IPOIB_EXIT( IPOIB_DBG_MCAST ); - return; - } - - /* - * The endpoint is already in the GID and MAC maps. - * mast endpoint are not used in the LID map. - */ - CL_ASSERT(p_endpt->dlid == 0); - /* set flag that endpoint is use */ - p_endpt->is_in_use = TRUE; - cl_obj_unlock( &p_port->obj ); - - /* Try to send all pending sends. */ - ipoib_port_resume( p_port , FALSE); - - ipoib_port_deref( p_port, ref_join_mcast ); - - IPOIB_EXIT( IPOIB_DBG_MCAST ); -} - - -void -ipoib_leave_mcast_cb( - IN void *context ) -{ - ipoib_port_t *p_port; - - IPOIB_ENTER( IPOIB_DBG_MCAST ); - - p_port = (ipoib_port_t*)context; - - IPOIB_PRINT( TRACE_LEVEL_VERBOSE, IPOIB_DBG_MCAST,("p_port->mcast_cnt = %d\n", p_port->mcast_cnt)); - - ipoib_port_deref( p_port, ref_leave_mcast); - cl_atomic_dec( &p_port->mcast_cnt); - - if(0 == p_port->mcast_cnt) - { - KeSetEvent( &p_port->leave_mcast_event, EVENT_INCREMENT, FALSE ); - } - - IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_MCAST, - ("Leave mcast callback deref ipoib_port \n") ); - - IPOIB_EXIT( IPOIB_DBG_MCAST ); -} - - - -void -__leave_error_mcast_cb( - IN void *context ) -{ - ipoib_port_t *p_port; - - IPOIB_ENTER( IPOIB_DBG_MCAST ); - - p_port = (ipoib_port_t*)context; - - ipoib_port_deref( p_port, ref_leave_mcast); - IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_MCAST, - ("Leave mcast callback deref ipoib_port \n") ); - - IPOIB_EXIT( IPOIB_DBG_MCAST ); -} - -/*++ -Routine Description: - The routine process the packet and returns LSO information - -Arguments: - pNetBuffer - a pointer to the first net buffer object of the packet - TcpHeaderOffset - offset to the begining of the TCP header in the packet - pLsoData - pointer to LsoData object in which the routine returns the LSO information - pHeaderSize - pointer to ULONG object in which the header size is returned - IndexOfData - - -Return Value: - NDIS_STATUS - -NOTE: - called at DISPATCH level ---*/ - -NDIS_STATUS GetLsoHeaderSize( - IN PNET_BUFFER pNetBuffer, - IN LsoData *pLsoData, - OUT UINT *IndexOfData, - IN ipoib_hdr_t *ipoib_hdr - ) -{ - UINT CurrLength; - PUCHAR pSrc; - PUCHAR pCopiedData = pLsoData->coppied_data; - ip_hdr_t UNALIGNED *IpHdr; - tcp_hdr_t UNALIGNED *TcpHdr; - uint16_t TcpHeaderLen; - uint16_t IpHeaderLen; - uint16_t IpOffset; - INT FullBuffers = 0; - PMDL pMDL; - NDIS_STATUS status = NDIS_STATUS_INVALID_PACKET; - - -#define IP_OFFSET 14; - // - // This Flag indicates the way we gets the headers - // RegularFlow = we get the headers (ETH+IP+TCP) in the same Buffer - // in sequence. - // - boolean_t IsRegularFlow = TRUE; - - const uint16_t ETH_OFFSET = IP_OFFSET; - - pLsoData->LsoHeaderSize = 0; - IpOffset = IP_OFFSET; //(uint16_t)pPort->EncapsulationFormat.EncapsulationHeaderSize; - *IndexOfData = 0; - - pMDL = NET_BUFFER_CURRENT_MDL(pNetBuffer); - NdisQueryMdl(pMDL, &pSrc, &CurrLength, NormalPagePriority); - //NdisQueryBufferSafe( CurrBuffer, &pSrc, &CurrLength, NormalPagePriority ); - if (pSrc == NULL) { - IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, ("Error processing packets\n")); - return status; - } - // We start by looking for the ethernet and the IP - if (CurrLength < ETH_OFFSET) { - IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, ("Error porcessing packets\n")); - return status; - } - //pLsoData->LsoHeaderSize = pLsoData->LsoHeaderSize + ETH_OFFSET; - if (CurrLength == ETH_OFFSET) { - ASSERT(FALSE); - IsRegularFlow = FALSE; - memcpy(pCopiedData, pSrc, ETH_OFFSET); - pCopiedData += ETH_OFFSET; - FullBuffers++; - // First buffer was only ethernet - pNetBuffer = NET_BUFFER_NEXT_NB(pNetBuffer); - NdisQueryMdl(NET_BUFFER_CURRENT_MDL(pNetBuffer), &pSrc, &CurrLength, NormalPagePriority); - if (pSrc == NULL) { - IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, ("Error porcessing packets\n")); - return status; - } - } else { - // This is ETH + IP together (at least) - pLsoData->LsoBuffers[0].pData = pSrc + (ETH_OFFSET - sizeof (ipoib_hdr_t)); - memcpy (pLsoData->LsoBuffers[0].pData, ipoib_hdr, sizeof (ipoib_hdr_t)); - CurrLength -= ETH_OFFSET; - pSrc = pSrc + ETH_OFFSET; - pLsoData->LsoHeaderSize = pLsoData->LsoHeaderSize + sizeof (ipoib_hdr_t); - } - // we should now be having at least the size of ethernet data - if (CurrLength < sizeof (ip_hdr_t)) { - IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, ("Error porcessing packets\n")); - return status; - } - IpHdr = (ip_hdr_t UNALIGNED*)pSrc; - IpHeaderLen = (uint16_t)IP_HEADER_LENGTH(IpHdr); - ASSERT(IpHdr->prot == IP_PROT_TCP); - if (CurrLength < IpHeaderLen) { - IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, ("Error processing packets\n")); - return status; - } - pLsoData->LsoHeaderSize = pLsoData->LsoHeaderSize + IpHeaderLen; - // We now start to find where the TCP header starts - if (CurrLength == IpHeaderLen) { - ASSERT(FALSE); - // two options : - // if(IsRegularFlow = FALSE) ==> ETH and IP seperated in two buffers - // if(IsRegularFlow = TRUE ) ==> ETH and IP in the same buffer - // TCP will start at next buffer - if(IsRegularFlow){ - memcpy(pCopiedData, pSrc-ETH_OFFSET ,ETH_OFFSET+IpHeaderLen); - pCopiedData += (ETH_OFFSET + IpHeaderLen); - } else { - memcpy(pCopiedData, pSrc,IpHeaderLen); - pCopiedData += IpHeaderLen; - } - - FullBuffers++; - IsRegularFlow = FALSE; - //NdisGetNextBuffer( CurrBuffer, &CurrBuffer); - //NdisQueryBufferSafe( CurrBuffer, &pSrc, &CurrLength, NormalPagePriority ); - pNetBuffer = NET_BUFFER_NEXT_NB(pNetBuffer); - NdisQueryMdl(NET_BUFFER_CURRENT_MDL(pNetBuffer), &pSrc, &CurrLength, NormalPagePriority); - if (pSrc == NULL) { - IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, ("Error porcessing packets\n")); - return status; - } - } else { - // if(IsRegularFlow = TRUE ) ==> the ETH and IP and TCP in the same buffer - // if(IsRegularFlow = FLASE ) ==> ETH in one buffer , IP+TCP together in the same buffer - if (IsRegularFlow) { - pLsoData->LsoBuffers[0].Len += IpHeaderLen; - } else { - memcpy(pCopiedData, pSrc, IpHeaderLen); - pCopiedData += IpHeaderLen; - } - - CurrLength -= IpHeaderLen; - pSrc = pSrc + IpHeaderLen; - } - if (CurrLength < sizeof (tcp_hdr_t)) { - IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, ("Error porcessing packets\n")); - return status; - } - // We have finaly found the TCP header - TcpHdr = (tcp_hdr_t UNALIGNED *)pSrc; - TcpHeaderLen = TCP_HEADER_LENGTH(TcpHdr); - - //ASSERT(TcpHeaderLen == 20); - - if (CurrLength < TcpHeaderLen) { - //IPOIB_PRINT(TRACE_LEVEL_VERBOSE, ETH, ("Error porcessing packets\n")); - return status; - } - pLsoData->LsoHeaderSize = pLsoData->LsoHeaderSize + TcpHeaderLen; - if(IsRegularFlow){ - pLsoData->LsoBuffers[0].Len += TcpHeaderLen; - } - else{ - memcpy(pCopiedData, pSrc, TcpHeaderLen); - pCopiedData += TcpHeaderLen; - } - if (CurrLength == TcpHeaderLen) { - FullBuffers++; - pLsoData->UsedBuffers = FullBuffers; - *IndexOfData = FullBuffers ; - } else { - pLsoData->UsedBuffers = FullBuffers + 1; - *IndexOfData = FullBuffers - 1; - } - pLsoData->FullBuffers = FullBuffers; - if (!IsRegularFlow){ - pLsoData->LsoBuffers[0].pData = pLsoData->coppied_data; - pLsoData->LsoBuffers[0].Len = ETH_OFFSET + IpHeaderLen + TcpHeaderLen; - ASSERT(pLsoData->LsoBuffers[0].Len <= LSO_MAX_HEADER); - } - return NDIS_STATUS_SUCCESS; -} - -static void __port_do_mcast_garbage(ipoib_port_t* const p_port) -{ - const mac_addr_t DEFAULT_MCAST_GROUP = {0x01, 0x00, 0x5E, 0x00, 0x00, 0x01}; - /* Do garbage collecting... */ - - cl_map_item_t *p_item; - ipoib_endpt_t *p_endpt; - cl_qlist_t destroy_mc_list; - uint8_t cnt; - const static GC_MAX_LEAVE_NUM = 80; - - cl_qlist_init( &destroy_mc_list ); - - cl_obj_lock( &p_port->obj ); - /* Wait for all readers to finish */ - while( p_port->endpt_rdr ) - { - cl_obj_unlock( &p_port->obj ); - cl_obj_lock( &p_port->obj ); - } - cnt = 0; - p_item = cl_qmap_head( &p_port->endpt_mgr.mac_endpts ); - while( (p_item != cl_qmap_end( &p_port->endpt_mgr.mac_endpts )) && (cnt < GC_MAX_LEAVE_NUM)) - { - p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item ); - p_item = cl_qmap_next( p_item ); - - /* Check if the current endpoint is not a multicast listener */ - - if( p_endpt->h_mcast && - (!p_endpt->is_mcast_listener) && - ( cl_memcmp( &p_endpt->mac, &DEFAULT_MCAST_GROUP, sizeof(mac_addr_t) ) && - (!p_endpt->is_in_use) )) - { - cl_qmap_remove_item( &p_port->endpt_mgr.mac_endpts, - &p_endpt->mac_item ); - cl_fmap_remove_item( &p_port->endpt_mgr.gid_endpts, - &p_endpt->gid_item ); - - if( p_endpt->dlid ) - { - cl_qmap_remove_item( &p_port->endpt_mgr.lid_endpts, - &p_endpt->lid_item ); - p_endpt->dlid = 0; - } - - cl_qlist_insert_tail( - &destroy_mc_list, &p_endpt->mac_item.pool_item.list_item ); - cnt++; - } - else - p_endpt->is_in_use = FALSE; - } - cl_obj_unlock( &p_port->obj ); - - /* Destroy all multicast endpoints now that we have released the lock. */ - while( cl_qlist_count( &destroy_mc_list ) ) - { - p_endpt = PARENT_STRUCT( cl_qlist_remove_head( &destroy_mc_list ), - ipoib_endpt_t, mac_item.pool_item.list_item ); - IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT, - ("mcast garbage collector: destroying endpoint %02x:%02x:%02x:%02x:%02x:%02x \n", - p_endpt->mac.addr[0], - p_endpt->mac.addr[1], - p_endpt->mac.addr[2], - p_endpt->mac.addr[3], - p_endpt->mac.addr[4], - p_endpt->mac.addr[5]) ); - cl_obj_destroy( &p_endpt->obj ); - } -} - -static void __port_mcast_garbage_dpc(KDPC *p_gc_dpc,void *context,void *s_arg1, void *s_arg2) -{ - ipoib_port_t *p_port = context; - - UNREFERENCED_PARAMETER(p_gc_dpc); - UNREFERENCED_PARAMETER(s_arg1); - UNREFERENCED_PARAMETER(s_arg2); - - __port_do_mcast_garbage(p_port); -} - -ipoib_endpt_t* -ipoib_endpt_get_by_gid( - IN ipoib_port_t* const p_port, - IN const ib_gid_t* const p_gid ) -{ - return __endpt_mgr_get_by_gid( p_port, p_gid ); -} - -ipoib_endpt_t* -ipoib_endpt_get_by_lid( - IN ipoib_port_t* const p_port, - IN const net16_t lid ) -{ - return __endpt_mgr_get_by_lid( p_port, lid ); -} - -ib_api_status_t -ipoib_recv_dhcp( - IN ipoib_port_t* const p_port, - IN const ipoib_pkt_t* const p_ipoib, - OUT eth_pkt_t* const p_eth, - IN ipoib_endpt_t* const p_src, - IN ipoib_endpt_t* const p_dst ) -{ - return __recv_dhcp( - p_port, p_ipoib, p_eth, p_src,p_dst ); -} - - -void -ipoib_port_cancel_xmit( - IN ipoib_port_t* const p_port, - IN PVOID cancel_id ) -{ - cl_list_item_t *p_item; - PNET_BUFFER_LIST p_nbl; - PVOID nbl_id; - cl_qlist_t cancel_list; - ULONG send_complete_flags = 0; - IPOIB_ENTER( IPOIB_DBG_SEND ); - - cl_qlist_init( &cancel_list ); - - cl_spinlock_acquire( &p_port->send_lock ); - - for( p_item = cl_qlist_head( &p_port->send_mgr.pending_list ); - p_item != cl_qlist_end( &p_port->send_mgr.pending_list ); - p_item = cl_qlist_next( p_item ) ) - { - p_nbl = IPOIB_PACKET_FROM_LIST_ITEM( p_item ); - nbl_id = NDIS_GET_NET_BUFFER_LIST_CANCEL_ID( p_nbl ); - if( nbl_id == cancel_id ) - { - cl_qlist_remove_item( &p_port->send_mgr.pending_list, p_item ); - NET_BUFFER_LIST_STATUS( p_nbl) = NDIS_STATUS_REQUEST_ABORTED ; - cl_qlist_insert_tail( &cancel_list, IPOIB_LIST_ITEM_FROM_PACKET( p_nbl ) ); - } - } - cl_spinlock_release( &p_port->send_lock ); - - if( cl_qlist_count( &cancel_list ) ) - { - while( ( p_item = cl_qlist_remove_head( &cancel_list )) - != cl_qlist_end( &cancel_list )) - { - p_nbl = IPOIB_PACKET_FROM_LIST_ITEM( p_item ); - NET_BUFFER_LIST_STATUS( p_nbl) = NDIS_STATUS_SEND_ABORTED; - send_complete_flags = 0; - if (NDIS_CURRENT_IRQL() == DISPATCH_LEVEL) - { - NDIS_SET_SEND_COMPLETE_FLAG(send_complete_flags, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL); - } - NdisMSendNetBufferListsComplete( p_port->p_adapter->h_adapter, - p_nbl, send_complete_flags ); - } - } - IPOIB_EXIT( IPOIB_DBG_SEND ); -} - -/* -* Put all fragments into separate WR and chain together. -* The last WR will be set to generate CQ Event. -* lookaside buffer is used for ipoib and ip headers attached to each WR. -* Buffer will be released on last WR send completion. -*/ -#if 0 -static NDIS_STATUS -__send_fragments( -IN ipoib_port_t* const p_port, -IN ipoib_send_desc_t* const p_desc, -IN eth_hdr_t* const p_eth_hdr, -IN ip_hdr_t* const p_ip_hdr, -IN uint32_t buf_len, -IN NDIS_BUFFER* p_ndis_buf ) -{ - uint32_t ds_idx = 1; - uint32_t wr_idx = 0; - uint32_t sgl_idx = 2; //skip eth hdr, ip hdr - uint32_t options_len = 0; - uint8_t* p_options = NULL; - uint8_t* p_buf; - uint32_t frag_offset = 0; - uint32_t next_sge; - uint32_t wr_size = 0; - uint32_t ip_hdr_len = IP_HEADER_LENGTH( p_ip_hdr ); - uint32_t total_ip_len = cl_ntoh16( p_ip_hdr->length ); - - SCATTER_GATHER_LIST *p_sgl; - - IPOIB_ENTER( IPOIB_DBG_SEND ); - - if( IP_DONT_FRAGMENT(p_ip_hdr) ) - return NDIS_STATUS_INVALID_PACKET; - - p_sgl = NDIS_PER_PACKET_INFO_FROM_PACKET( p_desc->p_pkt, ScatterGatherListPacketInfo ); - if( !p_sgl ) - { - ASSERT( p_sgl ); - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed to get SGL from packet.\n") ); - return NDIS_STATUS_FAILURE; - } - if( ( p_sgl->NumberOfElements > MAX_SEND_SGE || - p_sgl->Elements[0].Length < sizeof(eth_hdr_t)) ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Too many SG Elements in packet.\n") ); - return NDIS_STATUS_FAILURE; - } - p_buf = (uint8_t *) - ExAllocateFromNPagedLookasideList( &p_port->buf_mgr.send_buf_list ); - if( !p_buf ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed to allocate lookaside buffer.\n") ); - return NDIS_STATUS_RESOURCES; - } - p_desc->p_buf = (send_buf_t*)p_buf; - - if( buf_len < ip_hdr_len ) - { /* ip options in a separate buffer */ - CL_ASSERT( buf_len == sizeof( ip_hdr_t ) ); - NdisGetNextBuffer( p_ndis_buf, &p_ndis_buf ); - if( !p_ndis_buf ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed to get IP options buffer.\n") ); - return NDIS_STATUS_FAILURE; - } - NdisQueryBufferSafe( p_ndis_buf, &p_options, &options_len, NormalPagePriority ); - if( !p_options ) - { - IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, - ("Failed to query IP options buffer address.\n") ); - return NDIS_STATUS_FAILURE; - } - cl_memcpy( p_buf, p_ip_hdr, sizeof( ip_hdr_t ) ); - if( p_options && options_len ) - { - __copy_ip_options( &p_buf[sizeof(ip_hdr_t)], - p_options, options_len, TRUE ); - } - wr_size = buf_len + options_len; - sgl_idx++; - } - else - { /*options probably in the same buffer */ - cl_memcpy( p_buf, p_ip_hdr, buf_len ); - options_len = ip_hdr_len - sizeof( ip_hdr_t ); - if( options_len ) - { - p_options = p_buf + sizeof( ip_hdr_t ); - } - frag_offset += ( buf_len - ip_hdr_len ); - wr_size = buf_len; - } - - p_desc->send_wr[wr_idx].local_ds[ds_idx].vaddr = cl_get_physaddr( p_buf ); - p_desc->send_wr[wr_idx].local_ds[ds_idx].lkey = p_port->ib_mgr.lkey; - p_desc->send_wr[wr_idx].local_ds[ds_idx].length = wr_size; - - /* count how much data can be put into the first WR beside IP header. - * other protocols headers possibly supplied in subsequent buffers. - */ - for( sgl_idx; sgl_idx < p_sgl->NumberOfElements; sgl_idx++ ) - { - next_sge = p_sgl->Elements[sgl_idx].Length; - - /* add sgl if it can fit into the same WR - * Note: so far not going to split large SGE between WRs, - * so first fragment could be a smaller size. - */ - if( next_sge <= ( p_port->p_adapter->params.payload_mtu - wr_size ) ) - { - ++ds_idx; - wr_size += next_sge; - frag_offset += next_sge; - p_desc->send_wr[wr_idx].local_ds[ds_idx].vaddr = - p_sgl->Elements[sgl_idx].Address.QuadPart; - p_desc->send_wr[wr_idx].local_ds[ds_idx].length = next_sge; - p_desc->send_wr[wr_idx].local_ds[ds_idx].lkey = p_port->ib_mgr.lkey; - } - else - { - /* fix ip hdr for the first fragment and move on */ - __update_fragment_ip_hdr( (ip_hdr_t* const)p_buf, - (uint16_t)wr_size, IP_FRAGMENT_OFFSET(p_ip_hdr), TRUE ); - - p_desc->send_wr[wr_idx].wr.num_ds = ds_idx + 1; - p_buf += ip_hdr_len; - p_buf += (( buf_len > ip_hdr_len ) ? ( buf_len - ip_hdr_len ): 0); - frag_offset += ( (IP_FRAGMENT_OFFSET(p_ip_hdr)) << 3 ); - ++wr_idx; - ds_idx = 0; - break; - } - } - total_ip_len -= wr_size; - wr_size = 0; - - for( sgl_idx, wr_idx; sgl_idx < p_sgl->NumberOfElements; sgl_idx++ ) - { - uint32_t seg_len; - uint64_t next_sgl_addr; - - if( wr_idx >= ( MAX_WRS_PER_MSG - 1 ) ) - return NDIS_STATUS_RESOURCES; - - next_sge = p_sgl->Elements[sgl_idx].Length; - next_sgl_addr = p_sgl->Elements[sgl_idx].Address.QuadPart; - - while( next_sge ) - { - if( ds_idx == 0 ) - { /* new ipoib + ip header */ - ((ipoib_hdr_t*)p_buf)->type = p_eth_hdr->type; - ((ipoib_hdr_t*)p_buf)->resv = 0; - p_desc->send_wr[wr_idx].local_ds[ds_idx].vaddr = cl_get_physaddr( p_buf ); - p_desc->send_wr[wr_idx].local_ds[ds_idx].lkey = p_port->ib_mgr.lkey; - p_desc->send_wr[wr_idx].local_ds[ds_idx].length = sizeof( ipoib_hdr_t ); - p_buf += sizeof( ipoib_hdr_t ); - ++ds_idx; - - cl_memcpy( p_buf, p_ip_hdr, sizeof( ip_hdr_t ) ); - if( p_options && options_len ) - { - /* copy ip options if needed */ - __copy_ip_options( &p_buf[sizeof(ip_hdr_t)], - p_options, options_len, FALSE ); - } - wr_size = ip_hdr_len; - } - if( ds_idx == 1 ) - { - p_desc->send_wr[wr_idx].local_ds[ds_idx].length = ip_hdr_len; - p_desc->send_wr[wr_idx].local_ds[ds_idx].vaddr = cl_get_physaddr( p_buf ); - p_desc->send_wr[wr_idx].local_ds[ds_idx].lkey = p_port->ib_mgr.lkey; - ++ds_idx; - } - - seg_len = ( next_sge > ( p_port->p_adapter->params.payload_mtu - wr_size ) )? - ( p_port->p_adapter->params.payload_mtu - wr_size ) : next_sge; - - p_desc->send_wr[wr_idx].local_ds[ds_idx].vaddr = next_sgl_addr; - p_desc->send_wr[wr_idx].local_ds[ds_idx].length = seg_len; - p_desc->send_wr[wr_idx].local_ds[ds_idx].lkey = p_port->ib_mgr.lkey; - ++ds_idx; - - wr_size += seg_len; - total_ip_len -= seg_len; - - if( wr_size >= p_port->p_adapter->params.payload_mtu || total_ip_len == 0 ) - { /* fix ip hdr for that fragment */ - __update_fragment_ip_hdr( (ip_hdr_t* const)p_buf, (uint16_t)wr_size, - ((uint16_t)(frag_offset >> 3 )), - (BOOLEAN)(( total_ip_len > 0 ) || IP_MORE_FRAGMENTS( p_ip_hdr)) ); - p_desc->send_wr[wr_idx].wr.num_ds = ds_idx; - if( total_ip_len > 0 ) - { - ++wr_idx; - frag_offset += (wr_size - ip_hdr_len); - wr_size = 0; - ds_idx = 0; - p_buf += ip_hdr_len; - } - } - next_sge -= seg_len; - if( next_sge > 0 ) - { - next_sgl_addr += seg_len; - } - } - } - p_desc->num_wrs += wr_idx; - - IPOIB_EXIT( IPOIB_DBG_SEND ); - return NDIS_STATUS_SUCCESS; -} -#endif - -static void -__update_fragment_ip_hdr( -IN ip_hdr_t* const p_ip_hdr, -IN uint16_t fragment_size, -IN uint16_t fragment_offset, -IN BOOLEAN more_fragments ) -{ - uint16_t* p_hdr = (uint16_t*)p_ip_hdr; - p_ip_hdr->length = cl_hton16( fragment_size ); // bytes - p_ip_hdr->offset = cl_hton16( fragment_offset ); // 8-byte units - if( more_fragments ) - { - IP_SET_MORE_FRAGMENTS( p_ip_hdr ); - } - else - { - IP_SET_LAST_FRAGMENT( p_ip_hdr ); - } - p_ip_hdr->chksum = 0; - p_ip_hdr->chksum = ipchksum( p_hdr, IP_HEADER_LENGTH(p_ip_hdr) ); -} - -static void -__copy_ip_options( -IN uint8_t* p_buf, -IN uint8_t* p_options, -IN uint32_t options_len, -IN BOOLEAN copy_all ) -{ - uint32_t option_length; - uint32_t total_length = 0; - uint32_t copied_length = 0; - uint8_t* p_src = p_options; - uint8_t* p_dst = p_buf; - - if( p_options == NULL || options_len == 0 ) - return; - if( copy_all ) - { - cl_memcpy( p_dst, p_src, options_len ); - return; - } - do - { - if( ( *p_src ) == 0 ) // end of options list - { - total_length++; - break; - } - if( ( *p_src ) == 0x1 ) // no op - { - p_src++; - total_length++; - continue; - } - /*from RFC791: - * This option may be used between options, for example, to align - * the beginning of a subsequent option on a 32 bit boundary. - */ - if( copied_length && (copied_length % 4) ) - { - uint32_t align = 4 - (copied_length % 4); - cl_memset( p_dst, 0x1, (size_t)align ); - p_dst += align; - copied_length += align; - } - option_length = *(p_src + 1); - - if( *p_src & 0x80 ) - { - cl_memcpy( p_dst, p_src, option_length ); - p_dst += option_length; - copied_length += option_length; - } - total_length += option_length; - p_src += option_length; - - }while( total_length < options_len ); - - CL_ASSERT( total_length == options_len ); - CL_ASSERT( copied_length <= 40 ); - - /* padding the rest */ - if( options_len > copied_length ) - { - cl_memclr( p_dst, ( options_len - copied_length ) ); - } - return; -} diff --git a/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_port.cpp b/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_port.cpp new file mode 100644 index 00000000..f6d7a25a --- /dev/null +++ b/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_port.cpp @@ -0,0 +1,8119 @@ +/* + * Copyright (c) 2005 SilverStorm Technologies. All rights reserved. + * Copyright (c) 2006 Mellanox Technologies. All rights reserved. + * Portions Copyright (c) 2008 Microsoft 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: ipoib_port.c 4506 2009-06-23 14:40:54Z xalex $ + */ + + + +#include "ipoib_endpoint.h" +#include "ipoib_port.h" +#include "ipoib_adapter.h" +#include "ipoib_debug.h" +#if defined(EVENT_TRACING) +#ifdef offsetof +#undef offsetof +#endif +#include "ipoib_port.tmh" +#endif +#include + +#include "wdm.h" +#include + + + +ib_gid_t bcast_mgid_template = { + 0xff, /* multicast field */ + 0x12, /* scope (to be filled in) */ + 0x40, 0x1b, /* IPv4 signature */ + 0xff, 0xff, /* 16 bits of P_Key (to be filled in) */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 48 bits of zeros */ + 0xff, 0xff, 0xff, 0xff, /* 32 bit IPv4 broadcast address */ +}; + + +#ifdef _DEBUG_ +/* Handy pointer for debug use. */ +ipoib_port_t *gp_ipoib_port; +#endif + +static void __port_mcast_garbage_dpc(KDPC *p_gc_dpc,void *context,void *s_arg1, void *s_arg2); +static void __port_do_mcast_garbage(ipoib_port_t* const p_port ); + + +static void __recv_cb_dpc(KDPC *p_gc_dpc,void *context,void *s_arg1, void *s_arg2); + + +/****************************************************************************** +* +* Declarations +* +******************************************************************************/ +static void +__port_construct( + IN ipoib_port_t* const p_port ); + +static ib_api_status_t +__port_init( + IN ipoib_port_t* const p_port, + IN ipoib_adapter_t* const p_adapter, + IN ib_pnp_port_rec_t* const p_pnp_rec ); + +static void +__port_destroying( + IN cl_obj_t* const p_obj ); + +static void +__port_cleanup( + IN cl_obj_t* const p_obj ); + +static void +__port_free( + IN cl_obj_t* const p_obj ); + +static ib_api_status_t +__port_query_ca_attrs( + IN ipoib_port_t* const p_port, + IN ib_ca_attr_t** pp_ca_attrs ); + +static void +__srq_async_event_cb( +IN ib_async_event_rec_t *p_event_rec ); + +/****************************************************************************** +* +* IB resource manager operations +* +******************************************************************************/ +static void +__ib_mgr_construct( + IN ipoib_port_t* const p_port ); + +static ib_api_status_t +__ib_mgr_init( + IN ipoib_port_t* const p_port ); + +static void +__ib_mgr_destroy( + IN ipoib_port_t* const p_port ); + +static void +__qp_event( + IN ib_async_event_rec_t *p_event_rec ); + +static void +__cq_event( + IN ib_async_event_rec_t *p_event_rec ); + +static ib_api_status_t +__ib_mgr_activate( + IN ipoib_port_t* const p_port ); + +/****************************************************************************** +* +* Buffer manager operations. +* +******************************************************************************/ +static void +__buf_mgr_construct( + IN ipoib_port_t* const p_port ); + +static ib_api_status_t +__buf_mgr_init( + IN ipoib_port_t* const p_port ); + +static void +__buf_mgr_destroy( + IN ipoib_port_t* const p_port ); + +static cl_status_t +__recv_ctor( + IN void* const p_object, + IN void* context, + OUT cl_pool_item_t** const pp_pool_item ); + +#if !IPOIB_INLINE_RECV +static void +__recv_dtor( + IN const cl_pool_item_t* const p_pool_item, + IN void *context ); +#endif /* IPOIB_INLINE_RECV */ + +static inline ipoib_send_desc_t* +__buf_mgr_get_send( + IN ipoib_port_t* const p_port ); + +static inline void +__buf_mgr_put_send( + IN ipoib_port_t* const p_port, + IN ipoib_send_desc_t* const p_desc ); + +static inline ipoib_recv_desc_t* +__buf_mgr_get_recv( + IN ipoib_port_t* const p_port ); + +static inline void +__buf_mgr_put_recv( + IN ipoib_port_t* const p_port, + IN ipoib_recv_desc_t* const p_desc, + IN NET_BUFFER_LIST* const p_net_buffer_list OPTIONAL ); + +static inline void +__buf_mgr_put_recv_list( + IN ipoib_port_t* const p_port, + IN cl_qlist_t* const p_list ); + +//NDIS60 +static inline NET_BUFFER_LIST* +__buf_mgr_get_ndis_pkt( + IN ipoib_port_t* const p_port, + IN ipoib_recv_desc_t* const p_desc ); + + +/****************************************************************************** +* +* Receive manager operations. +* +******************************************************************************/ +static void +__recv_mgr_construct( + IN ipoib_port_t* const p_port ); + +static ib_api_status_t +__recv_mgr_init( + IN ipoib_port_t* const p_port ); + +static void +__recv_mgr_destroy( + IN ipoib_port_t* const p_port ); + +/* Posts receive buffers to the receive queue. */ +int32_t +__recv_mgr_repost( + IN ipoib_port_t* const p_port ); + +static void +__recv_cb( + IN const ib_cq_handle_t h_cq, + IN void *cq_context ); + +static void +__recv_get_endpts( + IN ipoib_port_t* const p_port, + IN ipoib_recv_desc_t* const p_desc, + IN ib_wc_t* const p_wc, + OUT ipoib_endpt_t** const pp_src, + OUT ipoib_endpt_t** const pp_dst ); + +static int32_t +__recv_mgr_filter( + IN ipoib_port_t* const p_port, + IN ib_wc_t* const p_done_wc_list, + OUT cl_qlist_t* const p_done_list, + OUT cl_qlist_t* const p_bad_list ); + +static ib_api_status_t +__recv_gen( + IN const ipoib_pkt_t* const p_ipoib, + OUT eth_pkt_t* const p_eth, + IN ipoib_endpt_t* const p_src, + IN ipoib_endpt_t* const p_dst ); + +static ib_api_status_t +__recv_dhcp( + IN ipoib_port_t* const p_port, + IN const ipoib_pkt_t* const p_ipoib, + OUT eth_pkt_t* const p_eth, + IN ipoib_endpt_t* const p_src, + IN ipoib_endpt_t* const p_dst ); + +static ib_api_status_t +__recv_arp( + IN ipoib_port_t* const p_port, + IN ib_wc_t* const p_wc, + IN const ipoib_pkt_t* const p_ipoib, + OUT eth_pkt_t* const p_eth, + IN ipoib_endpt_t** const p_src, + IN ipoib_endpt_t* const p_dst ); + +static ib_api_status_t +__recv_mgr_prepare_pkt( + IN ipoib_port_t* const p_port, + IN ipoib_recv_desc_t* const p_desc, + OUT NET_BUFFER_LIST** const pp_net_buffer_list ); + +static uint32_t +__recv_mgr_build_pkt_array( + IN ipoib_port_t* const p_port, + IN int32_t shortage, + OUT cl_qlist_t* const p_done_list, + OUT int32_t* const p_discarded ); + +/****************************************************************************** +* +* Send manager operations. +* +******************************************************************************/ +static void +__send_mgr_construct( + IN ipoib_port_t* const p_port ); + +static void +__send_mgr_destroy( + IN ipoib_port_t* const p_port ); + +static NDIS_STATUS +__send_gen( + IN ipoib_port_t* const p_port, + IN ipoib_send_desc_t* const p_desc, + IN SCATTER_GATHER_LIST *p_sgl, + IN INT lso_data_index); + +static NDIS_STATUS +__send_mgr_filter_ip( + IN ipoib_port_t* const p_port, + IN const eth_hdr_t* const p_eth_hdr, + IN MDL* p_mdl, + IN size_t buf_len, + IN SCATTER_GATHER_LIST *p_sgl, + IN OUT ipoib_send_desc_t* const p_desc ); + +static NDIS_STATUS +__send_mgr_filter_igmp_v2( + IN ipoib_port_t* const p_port, + IN const ip_hdr_t* const p_ip_hdr, + IN size_t iph_options_size, + IN MDL* p_mdl, + IN size_t buf_len ); + +static NDIS_STATUS +__send_mgr_filter_udp( + IN ipoib_port_t* const p_port, + IN const ip_hdr_t* const p_ip_hdr, + IN MDL* p_mdl, + IN size_t buf_len, + IN SCATTER_GATHER_LIST *p_sgl, + IN OUT ipoib_send_desc_t* const p_desc ); + +static NDIS_STATUS +__send_mgr_filter_dhcp( + IN ipoib_port_t* const p_port, + IN const udp_hdr_t* const p_udp_hdr, + IN MDL* p_mdl, + IN size_t buf_len, + IN OUT ipoib_send_desc_t* const p_desc ); + +static NDIS_STATUS +__send_mgr_filter_arp( + IN ipoib_port_t* const p_port, + IN const eth_hdr_t* const p_eth_hdr, + IN MDL* p_mdl, + IN size_t buf_len, + IN OUT ipoib_send_desc_t* const p_desc ); + +static void +__process_failed_send( + IN ipoib_port_t* const p_port, + IN ipoib_send_desc_t* const p_desc, + IN const NDIS_STATUS status, + IN ULONG send_complete_flags ); + +static inline NDIS_STATUS +__send_mgr_queue( + IN ipoib_port_t* const p_port, + IN eth_hdr_t* const p_eth_hdr, + OUT ipoib_endpt_t** const pp_endpt ); + +static NDIS_STATUS +__build_send_desc( + IN ipoib_port_t* const p_port, + IN eth_hdr_t* const p_eth_hdr, + IN MDL* const p_mdl, + IN const size_t mdl_len, + IN SCATTER_GATHER_LIST *p_sgl, + IN OUT ipoib_send_desc_t* const p_desc ); + + +static void +__send_cb( + IN const ib_cq_handle_t h_cq, + IN void *cq_context ); + +static NDIS_STATUS +GetLsoHeaderSize( + IN PNET_BUFFER pNetBuffer, + IN LsoData *pLsoData, + OUT UINT *IndexOfData, + IN ipoib_hdr_t *ipoib_hdr ); + + +static NDIS_STATUS +__build_lso_desc( + IN ipoib_port_t* const p_port, + IN OUT ipoib_send_desc_t* const p_desc, + IN ULONG mss, + IN SCATTER_GATHER_LIST *p_sgl, + IN int32_t hdr_idx, + IN PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO p_lso_info ); + +static NDIS_STATUS +__send_fragments( + IN ipoib_port_t* const p_port, + IN ipoib_send_desc_t* const p_desc, + IN eth_hdr_t* const p_eth_hdr, + IN ip_hdr_t* const p_ip_hdr, + IN uint32_t buf_len, + IN NDIS_BUFFER* p_ndis_buf ); + +//TODO CM Restore +#if 0 +static void +__update_fragment_ip_hdr( +IN ip_hdr_t* const p_ip_hdr, +IN uint16_t fragment_size, +IN uint16_t fragment_offset, +IN BOOLEAN more_fragments ); + +static void +__copy_ip_options( +IN uint8_t* p_buf, +IN uint8_t* p_options, +IN uint32_t options_len, +IN BOOLEAN copy_all ); +#endif +/****************************************************************************** +* +* Endpoint manager operations +* +******************************************************************************/ +static void +__endpt_mgr_construct( + IN ipoib_port_t* const p_port ); + +static ib_api_status_t +__endpt_mgr_init( + IN ipoib_port_t* const p_port ); + +static void +__endpt_mgr_destroy( + IN ipoib_port_t* const p_port ); + +/****f* IPoIB/__endpt_mgr_remove_all +* NAME +* __endpt_mgr_remove_all +* +* DESCRIPTION +* Removes all enpoints from the port, dereferencing them to initiate +* destruction. +* +* SYNOPSIS +*/ +static void +__endpt_mgr_remove_all( + IN ipoib_port_t* const p_port ); +/* +********/ + +static void +__endpt_mgr_remove( + IN ipoib_port_t* const p_port, + IN ipoib_endpt_t* const p_endpt ); + +static void +__endpt_mgr_reset_all( + IN ipoib_port_t* const p_port ); + +static inline NDIS_STATUS +__endpt_mgr_ref( + IN ipoib_port_t* const p_port, + IN const mac_addr_t mac, + OUT ipoib_endpt_t** const pp_endpt ); + +static inline NDIS_STATUS +__endpt_mgr_get_gid_qpn( + IN ipoib_port_t* const p_port, + IN const mac_addr_t mac, + OUT ib_gid_t* const p_gid, + OUT UNALIGNED net32_t* const p_qpn ); + +static inline ipoib_endpt_t* +__endpt_mgr_get_by_gid( + IN ipoib_port_t* const p_port, + IN const ib_gid_t* const p_gid ); + +static inline ipoib_endpt_t* +__endpt_mgr_get_by_lid( + IN ipoib_port_t* const p_port, + IN const net16_t lid ); + +static inline ib_api_status_t +__endpt_mgr_insert_locked( + IN ipoib_port_t* const p_port, + IN const mac_addr_t mac, + IN ipoib_endpt_t* const p_endpt ); + +static inline ib_api_status_t +__endpt_mgr_insert( + IN ipoib_port_t* const p_port, + IN const mac_addr_t mac, + IN ipoib_endpt_t* const p_endpt ); + +static ib_api_status_t +__endpt_mgr_add_local( + IN ipoib_port_t* const p_port, + IN ib_port_info_t* const p_port_info ); + +static ib_api_status_t +__endpt_mgr_add_bcast( + IN ipoib_port_t* const p_port, + IN ib_mcast_rec_t *p_mcast_rec ); + +/****************************************************************************** +* +* MCast operations. +* +******************************************************************************/ +static ib_api_status_t +__port_get_bcast( + IN ipoib_port_t* const p_port ); + +static ib_api_status_t +__port_join_bcast( + IN ipoib_port_t* const p_port, + IN ib_member_rec_t* const p_member_rec ); + +static ib_api_status_t +__port_create_bcast( + IN ipoib_port_t* const p_port ); + + + +static void +__bcast_get_cb( + IN ib_query_rec_t *p_query_rec ); + + +static void +__bcast_cb( + IN ib_mcast_rec_t *p_mcast_rec ); + + +static void +__mcast_cb( + IN ib_mcast_rec_t *p_mcast_rec ); + +void +__leave_error_mcast_cb( + IN void *context ); + + +static intn_t +__gid_cmp( + IN const void* const p_key1, + IN const void* const p_key2 ) +{ + return cl_memcmp( p_key1, p_key2, sizeof(ib_gid_t) ); +} + + +inline void ipoib_port_ref( ipoib_port_t * p_port, int type ) +{ + cl_obj_ref( &p_port->obj ); +#if DBG + cl_atomic_inc( &p_port->ref[type % ref_mask] ); + if ((p_port->obj.ref_cnt % 20)==0) + IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OBJ, + ("ref type %d ref_cnt %d\n", type, p_port->obj.ref_cnt) ); + //TODO remove + //ASSERT (p_port->obj.ref_cnt < 100); +#else + UNREFERENCED_PARAMETER(type); +#endif +} + + +inline void ipoib_port_deref(ipoib_port_t * p_port, int type) +{ +#if DBG + cl_atomic_dec( &p_port->ref[type % ref_mask] ); + if ((p_port->obj.ref_cnt % 20) == 0) + IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OBJ, + ("deref type %d ref_cnt %d\n", type, p_port->obj.ref_cnt) ); +#else + UNREFERENCED_PARAMETER(type); +#endif + cl_obj_deref( &p_port->obj ); + +} + +/* function returns pointer to payload that is going after IP header. +* asssuming that payload and IP header are in the same buffer +*/ +static void* GetIpPayloadPtr(const ip_hdr_t* const p_ip_hdr) +{ + return (void*)((uint8_t*)p_ip_hdr + IP_HEADER_LENGTH(p_ip_hdr)); +} + +/****************************************************************************** +* +* Implementation +* +******************************************************************************/ +ib_api_status_t +ipoib_create_port( + IN ipoib_adapter_t* const p_adapter, + IN ib_pnp_port_rec_t* const p_pnp_rec, + OUT ipoib_port_t** const pp_port ) +{ + ib_api_status_t status; + ipoib_port_t *p_port; + + IPOIB_ENTER( IPOIB_DBG_INIT ); + + CL_ASSERT( !p_adapter->p_port ); + + p_port = (ipoib_port_t *) cl_zalloc( sizeof(ipoib_port_t) + + (sizeof(ipoib_hdr_t) * (p_adapter->params.sq_depth - 1)) ); + if( !p_port ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed to allocate ipoib_port_t (%d bytes)\n", + sizeof(ipoib_port_t)) ); + return IB_INSUFFICIENT_MEMORY; + } + +#ifdef _DEBUG_ + gp_ipoib_port = p_port; +#endif + + __port_construct( p_port ); + + status = __port_init( p_port, p_adapter, p_pnp_rec ); + if( status != IB_SUCCESS ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ipoib_port_init returned %s.\n", + p_adapter->p_ifc->get_err_str( status )) ); + __port_cleanup( &p_port->obj ); + __port_free( &p_port->obj ); + return status; + } + + *pp_port = p_port; + IPOIB_EXIT( IPOIB_DBG_INIT ); + return IB_SUCCESS; +} + + +void +ipoib_port_destroy( + IN ipoib_port_t* const p_port ) +{ + IPOIB_ENTER( IPOIB_DBG_INIT ); + + CL_ASSERT( p_port ); + CL_ASSERT( p_port->p_adapter ); + CL_ASSERT( !p_port->p_adapter->p_port ); + + cl_obj_destroy( &p_port->obj ); + + IPOIB_EXIT( IPOIB_DBG_INIT ); +} + + +static void +__port_construct( + IN ipoib_port_t* const p_port ) +{ + IPOIB_ENTER( IPOIB_DBG_INIT ); + + p_port->state = IB_QPS_RESET; + + cl_obj_construct( &p_port->obj, IPOIB_OBJ_PORT ); + cl_spinlock_construct( &p_port->send_lock ); + cl_spinlock_construct( &p_port->recv_lock ); + __ib_mgr_construct( p_port ); + __buf_mgr_construct( p_port ); + + __recv_mgr_construct( p_port ); + __send_mgr_construct( p_port ); + + __endpt_mgr_construct( p_port ); + + KeInitializeEvent( &p_port->sa_event, NotificationEvent, TRUE ); + KeInitializeEvent( &p_port->leave_mcast_event, NotificationEvent, TRUE ); + + IPOIB_EXIT( IPOIB_DBG_INIT ); +} + + +static ib_api_status_t +__port_init( + IN ipoib_port_t* const p_port, + IN ipoib_adapter_t* const p_adapter, + IN ib_pnp_port_rec_t* const p_pnp_rec ) +{ + cl_status_t cl_status; + ib_api_status_t status; + + IPOIB_ENTER( IPOIB_DBG_INIT ); + + p_port->port_num = p_pnp_rec->p_port_attr->port_num; + p_port->p_adapter = p_adapter; + + cl_status = cl_spinlock_init( &p_port->send_lock ); + if( cl_status != CL_SUCCESS ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("cl_spinlock_init returned %#x\n", cl_status) ); + return IB_ERROR; + } + + cl_status = cl_spinlock_init( &p_port->recv_lock ); + if( cl_status != CL_SUCCESS ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("cl_spinlock_init returned %#x\n", cl_status) ); + return IB_ERROR; + } + + /* Initialize the IB resource manager. */ + status = __ib_mgr_init( p_port ); + if( status != IB_SUCCESS ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("__ib_mgr_init returned %s\n", + p_adapter->p_ifc->get_err_str( status )) ); + return status; + } + + /* Initialize the buffer manager. */ + status = __buf_mgr_init( p_port ); + if( status != IB_SUCCESS ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("__buf_mgr_init returned %s\n", + p_adapter->p_ifc->get_err_str( status )) ); + return status; + } + + /* Initialize the receive manager. */ + status = __recv_mgr_init( p_port ); + if( status != IB_SUCCESS ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("__recv_mgr_init returned %s\n", + p_adapter->p_ifc->get_err_str( status )) ); + return status; + } + + /* Initialize the endpoint manager. */ + status = __endpt_mgr_init( p_port ); + if( status != IB_SUCCESS ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("__endpt_mgr_init returned %s\n", + p_adapter->p_ifc->get_err_str( status )) ); + return status; + } + + KeInitializeDpc(&p_port->recv_dpc,(PKDEFERRED_ROUTINE)__recv_cb_dpc,p_port); + + + /* Initialize multicast garbage collector timer and DPC object */ + KeInitializeDpc(&p_port->gc_dpc,(PKDEFERRED_ROUTINE)__port_mcast_garbage_dpc,p_port); + KeInitializeTimerEx(&p_port->gc_timer,SynchronizationTimer); + + /* We only ever destroy from the PnP callback thread. */ + cl_status = cl_obj_init( &p_port->obj, CL_DESTROY_SYNC, + __port_destroying, __port_cleanup, __port_free ); + +#if DBG + cl_atomic_inc( &p_port->ref[ref_init] ); + IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OBJ, + ("ref type %d ref_cnt %d\n", ref_init, p_port->obj.ref_cnt) ); +#endif + + if( cl_status != CL_SUCCESS ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("cl_obj_init returned %#x\n", cl_status) ); + return IB_ERROR; + } + + cl_status = cl_obj_insert_rel( &p_port->rel, &p_adapter->obj, &p_port->obj ); + if( cl_status != CL_SUCCESS ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("cl_obj_insert_rel returned %#x\n", cl_status) ); + cl_obj_destroy( &p_port->obj ); + return IB_ERROR; + } + +#if DBG + cl_atomic_inc( &p_port->ref[ref_init] ); + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_OBJ, + ("ref type %d ref_cnt %d\n", ref_init, p_port->obj.ref_cnt) ); +#endif + + IPOIB_EXIT( IPOIB_DBG_INIT ); + return IB_SUCCESS; +} + + +static void +__port_destroying( + IN cl_obj_t* const p_obj ) +{ + ipoib_port_t *p_port; + + IPOIB_ENTER( IPOIB_DBG_INIT ); + + CL_ASSERT( p_obj ); + + p_port = PARENT_STRUCT( p_obj, ipoib_port_t, obj ); + + ipoib_port_down( p_port ); + + __endpt_mgr_remove_all( p_port ); + +#if 0 + if( p_port->p_adapter->params.cm_enabled ) + { + endpt_cm_buf_mgr_destroy( p_port ); + ipoib_port_srq_destroy( p_port ); + p_port->endpt_mgr.thread_is_done = 1; + cl_event_signal( &p_port->endpt_mgr.event ); + } +#endif + ASSERT(FALSE); + //TODO NDIS6.0 + ipoib_port_resume( p_port, FALSE ); + + IPOIB_EXIT( IPOIB_DBG_INIT ); +} + + +static void +__port_cleanup( + IN cl_obj_t* const p_obj ) +{ + ipoib_port_t *p_port; + + IPOIB_ENTER( IPOIB_DBG_INIT ); + + CL_ASSERT( p_obj ); + + p_port = PARENT_STRUCT( p_obj, ipoib_port_t, obj ); + + /* Wait for all sends and receives to get flushed. */ + while( p_port->send_mgr.depth || p_port->recv_mgr.depth ) + cl_thread_suspend( 0 ); + + /* Destroy the send and receive managers before closing the CA. */ + __ib_mgr_destroy( p_port ); + + IPOIB_EXIT( IPOIB_DBG_INIT ); +} + + +static void +__port_free( + IN cl_obj_t* const p_obj ) +{ + ipoib_port_t *p_port; + + IPOIB_ENTER( IPOIB_DBG_INIT ); + + CL_ASSERT( p_obj ); + + p_port = PARENT_STRUCT( p_obj, ipoib_port_t, obj ); + + KeCancelTimer(&p_port->gc_timer); + KeFlushQueuedDpcs(); + __endpt_mgr_destroy( p_port ); + __recv_mgr_destroy( p_port ); + __send_mgr_destroy( p_port ); + __buf_mgr_destroy( p_port ); + + cl_spinlock_destroy( &p_port->send_lock ); + cl_spinlock_destroy( &p_port->recv_lock ); + + cl_obj_deinit( p_obj ); + if( p_port->p_ca_attrs ) + { + cl_free ( p_port->p_ca_attrs ); + } + cl_free( p_port ); + + IPOIB_EXIT( IPOIB_DBG_INIT ); +} + + + +/****************************************************************************** +* +* IB resource manager implementation. +* +******************************************************************************/ +static void +__ib_mgr_construct( + IN ipoib_port_t* const p_port ) +{ + IPOIB_ENTER( IPOIB_DBG_INIT ); + + cl_memclr( &p_port->ib_mgr, sizeof(ipoib_ib_mgr_t) ); + + IPOIB_EXIT( IPOIB_DBG_INIT ); +} + + +static ib_api_status_t +__ib_mgr_init( + IN ipoib_port_t* const p_port ) +{ + ib_api_status_t status; + ib_cq_create_t cq_create; + ib_qp_create_t qp_create; + ib_phys_create_t phys_create; + ib_phys_range_t phys_range; + uint64_t vaddr; + net32_t rkey; + ib_qp_attr_t qp_attr; + + IPOIB_ENTER( IPOIB_DBG_INIT ); + + /* Open the CA. */ + status = p_port->p_adapter->p_ifc->open_ca( + p_port->p_adapter->h_al, p_port->p_adapter->guids.ca_guid, + NULL, p_port, &p_port->ib_mgr.h_ca ); + if( status != IB_SUCCESS ) + { + NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, + EVENT_IPOIB_OPEN_CA, 1, status ); + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ib_open_ca returned %s\n", + p_port->p_adapter->p_ifc->get_err_str( status )) ); + return status; + } + + status = __port_query_ca_attrs( p_port, &p_port->p_ca_attrs ); + if( status != IB_SUCCESS ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Query CA attributes failed\n" ) ); + return status; + } +#if 0 + if( p_port->p_adapter->params.cm_enabled ) + { + uint32_t payload_mtu = __port_attr_to_mtu_size( + p_port->p_ca_attrs->p_port_attr[p_port->port_num - 1].mtu ) + - sizeof(ipoib_hdr_t); + /* adjust ipoib UD payload MTU to actual port MTU size. */ + p_port->p_adapter->params.payload_mtu = + max( DEFAULT_PAYLOAD_MTU, payload_mtu ); + p_port->p_adapter->params.xfer_block_size = + (sizeof(eth_hdr_t) + p_port->p_adapter->params.payload_mtu); + } +#endif +#if IPOIB_USE_DMA + /* init DMA only once while running MiniportInitialize */ + if ( !p_port->p_adapter->reset ) + { + ULONG max_phys_mapping; + if( p_port->p_adapter->params.cm_enabled ) + { + max_phys_mapping = p_port->p_adapter->params.cm_xfer_block_size; + } + else if( p_port->p_adapter->params.lso ) + { + max_phys_mapping = LARGE_SEND_OFFLOAD_SIZE; + } + else + { + max_phys_mapping = p_port->p_adapter->params.xfer_block_size; + } + /*if( NdisMInitializeScatterGatherDma( p_port->p_adapter->h_adapter, + TRUE, max_phys_mapping )!= NDIS_STATUS_SUCCESS ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("NdisMInitializeScatterGatherDma failed\n" ) ); + return IB_INSUFFICIENT_RESOURCES; + }*/ + } +#endif + + /* Allocate the PD. */ + status = p_port->p_adapter->p_ifc->alloc_pd( + p_port->ib_mgr.h_ca, IB_PDT_UD, p_port, &p_port->ib_mgr.h_pd ); + if( status != IB_SUCCESS ) + { + NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, + EVENT_IPOIB_ALLOC_PD, 1, status ); + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ib_alloc_pd returned %s\n", + p_port->p_adapter->p_ifc->get_err_str( status )) ); + return status; + } + + /* Allocate receive CQ. */ + cq_create.size = p_port->p_adapter->params.rq_depth; + cq_create.pfn_comp_cb = __recv_cb; + cq_create.h_wait_obj = NULL; + + status = p_port->p_adapter->p_ifc->create_cq( + p_port->ib_mgr.h_ca, &cq_create, p_port, + __cq_event, &p_port->ib_mgr.h_recv_cq ); + if( status != IB_SUCCESS ) + { + NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, + EVENT_IPOIB_CREATE_RECV_CQ, 1, status ); + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ib_create_cq returned %s.\n", + p_port->p_adapter->p_ifc->get_err_str( status )) ); + return status; + } + + /* Allocate send CQ. */ + cq_create.size = p_port->p_adapter->params.sq_depth; + cq_create.pfn_comp_cb = __send_cb; + + status = p_port->p_adapter->p_ifc->create_cq( + p_port->ib_mgr.h_ca, &cq_create, p_port, + __cq_event, &p_port->ib_mgr.h_send_cq ); + if( status != IB_SUCCESS ) + { + NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, + EVENT_IPOIB_CREATE_SEND_CQ, 1, status ); + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ib_create_cq returned %s.\n", + p_port->p_adapter->p_ifc->get_err_str( status )) ); + return status; + } + + /* Allocate the QP. */ + cl_memclr( &qp_create, sizeof(qp_create) ); + qp_create.qp_type = IB_QPT_UNRELIABLE_DGRM; + qp_create.rq_depth = p_port->p_adapter->params.rq_depth; + qp_create.rq_sge = 2; /* To support buffers spanning pages. */ + qp_create.h_rq_cq = p_port->ib_mgr.h_recv_cq; + qp_create.sq_depth = p_port->p_adapter->params.sq_depth; + +#define UD_QP_USED_SGE 3 + qp_create.sq_sge = MAX_SEND_SGE < p_port->p_ca_attrs->max_sges ? + MAX_SEND_SGE : ( p_port->p_ca_attrs->max_sges - UD_QP_USED_SGE ); + if ( !p_port->p_ca_attrs->ipoib_csum ) + { + /* checksum is not supported by device + user must specify BYPASS to explicitly cancel checksum calculation */ + if (p_port->p_adapter->params.send_chksum_offload == CSUM_ENABLED) + p_port->p_adapter->params.send_chksum_offload = CSUM_DISABLED; + if (p_port->p_adapter->params.recv_chksum_offload == CSUM_ENABLED) + p_port->p_adapter->params.recv_chksum_offload = CSUM_DISABLED; + } + + qp_create.h_sq_cq = p_port->ib_mgr.h_send_cq; + qp_create.sq_signaled = FALSE; + status = p_port->p_adapter->p_ifc->create_qp( + p_port->ib_mgr.h_pd, &qp_create, p_port, + __qp_event, &p_port->ib_mgr.h_qp ); + if( status != IB_SUCCESS ) + { + NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, + EVENT_IPOIB_CREATE_QP, 1, status ); + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ib_create_qp returned %s\n", + p_port->p_adapter->p_ifc->get_err_str( status )) ); + return status; + } + /* Query the QP so we can get our QPN. */ + status = p_port->p_adapter->p_ifc->query_qp( + p_port->ib_mgr.h_qp, &qp_attr ); + if( status != IB_SUCCESS ) + { + NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, + EVENT_IPOIB_QUERY_QP, 1, status ); + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ib_query_qp returned %s\n", + p_port->p_adapter->p_ifc->get_err_str( status )) ); + return status; + } + p_port->ib_mgr.qpn = qp_attr.num; + + /* Register all of physical memory */ + phys_create.length = MEM_REG_SIZE; + phys_create.num_ranges = 1; + phys_create.range_array = &phys_range; + phys_create.buf_offset = 0; + phys_create.hca_page_size = PAGE_SIZE; + phys_create.access_ctrl = IB_AC_LOCAL_WRITE; + phys_range.base_addr = 0; + phys_range.size = MEM_REG_SIZE; + vaddr = 0; + status = p_port->p_adapter->p_ifc->reg_phys( + p_port->ib_mgr.h_pd, &phys_create, &vaddr, + &p_port->ib_mgr.lkey, &rkey, &p_port->ib_mgr.h_mr ); + if( status != IB_SUCCESS ) + { + NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, + EVENT_IPOIB_REG_PHYS, 1, status ); + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ib_reg_phys returned %s\n", + p_port->p_adapter->p_ifc->get_err_str( status )) ); + return status; + } + + status = ipoib_port_srq_init( p_port ); + if( status != IB_SUCCESS ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ipoib_port_srq_init failed %s\n", + p_port->p_adapter->p_ifc->get_err_str( status )) ); + /* disable further CM initialization */ + p_port->p_adapter->params.cm_enabled = FALSE; + + NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, + EVENT_IPOIB_CONNECTED_MODE_ERR, 1, 0xbadc0de1 ); + + } +//CM +#if 0 + if( p_port->p_adapter->params.cm_enabled ) + { + status = endpt_cm_buf_mgr_init( p_port ); + if( status != IB_SUCCESS ) + { + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("CM Init buf mgr failed status %#x\n", status ) ); + ipoib_port_srq_destroy( p_port ); + p_port->p_adapter->params.cm_enabled = FALSE; + + NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, + EVENT_IPOIB_CONNECTED_MODE_ERR, 1, 0xbadc0de2 ); + } + else + { + if ( p_port->p_adapter->params.send_chksum_offload ) + p_port->p_adapter->params.send_chksum_offload = CSUM_DISABLED; + } + } +#endif + IPOIB_EXIT( IPOIB_DBG_INIT ); + return IB_SUCCESS; +} + +static void +__srq_async_event_cb( +IN ib_async_event_rec_t *p_event_rec ) +{ + ipoib_port_t* p_port = + (ipoib_port_t *)p_event_rec->context; + + switch( p_event_rec->code ) + { + case IB_AE_SRQ_LIMIT_REACHED: + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("SRQ ASYNC EVENT CODE %d: %s\n", + p_event_rec->code, "IB_AE_SRQ_LIMIT_REACHED" ) ); + break; + case IB_AE_SRQ_CATAS_ERROR: + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("SRQ ASYNC EVENT CODE %d: %s\n", + p_event_rec->code, "IB_AE_SRQ_CATAS_ERROR" ) ); + /*SRQ is in err state, must reinitialize */ + p_port->p_adapter->hung = TRUE; + break; + case IB_AE_SRQ_QP_LAST_WQE_REACHED: + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("SRQ ASYNC EVENT CODE %d: %s\n", + p_event_rec->code, "IB_AE_SRQ_QP_LAST_WQE_REACHED" ) ); + /*SRQ is in err state, must reinitialize */ + p_port->p_adapter->hung = TRUE; + break; + default: + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ASYNC EVENT CODE ARRIVED %d(%#x)\n", + p_event_rec->code, p_event_rec->code ) ); + } +} + +ib_api_status_t +ipoib_port_srq_init( + IN ipoib_port_t* const p_port ) +{ + ib_api_status_t ib_status; + ib_srq_handle_t h_srq; + ib_srq_attr_t srq_attr; + + IPOIB_ENTER( IPOIB_DBG_INIT ); + + if( !p_port->p_adapter->params.cm_enabled ) + return IB_SUCCESS; + + srq_attr.max_sge = min( 2, p_port->p_ca_attrs->max_srq_sges ); + srq_attr.srq_limit = 10; + srq_attr.max_wr = + min( (uint32_t)p_port->p_adapter->params.rq_depth * 8, + p_port->p_ca_attrs->max_srq_wrs/2 ); + + ib_status = p_port->p_adapter->p_ifc->create_srq( + p_port->ib_mgr.h_pd, + &srq_attr, + p_port, + __srq_async_event_cb, + &h_srq ); + if( ib_status != IB_SUCCESS ) + { + NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, + EVENT_IPOIB_CREATE_QP, 1, ib_status ); + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ib_create_srq failed status %s\n", + p_port->p_adapter->p_ifc->get_err_str( ib_status )) ); + return ib_status; + } + p_port->ib_mgr.h_srq = h_srq; + + IPOIB_EXIT( IPOIB_DBG_INIT ); + + return ib_status; +} + +/* __port_query_ca_attrs() + * returns a pointer to allocated memory. + * must be released by caller. + */ +static ib_api_status_t +__port_query_ca_attrs( + IN ipoib_port_t* const p_port, + IN ib_ca_attr_t** pp_ca_attrs ) +{ + ib_api_status_t ib_status; + uint32_t attr_size; + ib_ca_attr_t* p_ca_attrs; + + *pp_ca_attrs = NULL; + + ib_status = + p_port->p_adapter->p_ifc->query_ca( p_port->ib_mgr.h_ca, NULL , &attr_size ); + if( ib_status != IB_INSUFFICIENT_MEMORY ) + { + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ib_query_ca failed status %s\n", + p_port->p_adapter->p_ifc->get_err_str( ib_status )) ); + goto done; + } + CL_ASSERT( attr_size ); + + p_ca_attrs = (ib_ca_attr_t *) cl_zalloc( attr_size ); + if ( p_ca_attrs == NULL ) + { + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Allocate %d bytes failed for CA Attributes\n", attr_size )); + ib_status = IB_INSUFFICIENT_MEMORY; + goto done; + } + + ib_status = + p_port->p_adapter->p_ifc->query_ca( p_port->ib_mgr.h_ca, p_ca_attrs , &attr_size ); + if ( ib_status != IB_SUCCESS ) + { + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("CA attributes query failed\n") ); + cl_free ( p_ca_attrs ); + goto done; + } + + *pp_ca_attrs = p_ca_attrs; +done: + return ib_status; +} + +void +ipoib_port_srq_destroy( + IN ipoib_port_t* const p_port ) +{ + ib_api_status_t status; + + if( p_port->ib_mgr.h_srq ) + { + status = + p_port->p_adapter->p_ifc->destroy_srq( p_port->ib_mgr.h_srq, NULL ); + CL_ASSERT( status == IB_SUCCESS ); + p_port->ib_mgr.h_srq = NULL; + } +} + +static void +__ib_mgr_destroy( + IN ipoib_port_t* const p_port ) +{ + ib_api_status_t status; + + IPOIB_ENTER( IPOIB_DBG_INIT ); + + if( p_port->ib_mgr.h_ca ) + { + status = + p_port->p_adapter->p_ifc->close_ca( p_port->ib_mgr.h_ca, NULL ); + CL_ASSERT( status == IB_SUCCESS ); + p_port->ib_mgr.h_ca = NULL; + } + + IPOIB_EXIT( IPOIB_DBG_INIT ); +} + + + +/****************************************************************************** +* +* Buffer manager implementation. +* +******************************************************************************/ +static void +__buf_mgr_construct( + IN ipoib_port_t* const p_port ) +{ + IPOIB_ENTER( IPOIB_DBG_INIT ); + + cl_qpool_construct( &p_port->buf_mgr.recv_pool ); + + p_port->buf_mgr.h_packet_pool = NULL; + p_port->buf_mgr.h_buffer_pool = NULL; + + NdisInitializeNPagedLookasideList( &p_port->buf_mgr.send_buf_list, + NULL, NULL, 0, MAX_XFER_BLOCK_SIZE, 'bipi', 0 ); + + p_port->buf_mgr.h_send_pkt_pool = NULL; + p_port->buf_mgr.h_send_buf_pool = NULL; + + IPOIB_EXIT( IPOIB_DBG_INIT ); +} + + +static ib_api_status_t +__buf_mgr_init( + IN ipoib_port_t* const p_port ) +{ + cl_status_t cl_status; + ipoib_params_t *p_params; + NET_BUFFER_LIST_POOL_PARAMETERS pool_parameters; + IPOIB_ENTER(IPOIB_DBG_INIT ); + + CL_ASSERT( p_port ); + CL_ASSERT( p_port->p_adapter ); + + p_params = &p_port->p_adapter->params; + + /* Allocate the receive descriptor pool */ + cl_status = cl_qpool_init( &p_port->buf_mgr.recv_pool, + p_params->rq_depth * p_params->recv_pool_ratio, +#if IPOIB_INLINE_RECV + 0, 0, sizeof(ipoib_recv_desc_t), __recv_ctor, NULL, p_port ); +#else /* IPOIB_INLINE_RECV */ + 0, 0, sizeof(ipoib_recv_desc_t), __recv_ctor, __recv_dtor, p_port ); +#endif /* IPOIB_INLINE_RECV */ + if( cl_status != CL_SUCCESS ) + { + NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, + EVENT_IPOIB_RECV_POOL, 1, cl_status ); + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("cl_qpool_init for recvs returned %#x\n", + cl_status) ); + return IB_INSUFFICIENT_MEMORY; + } + + /* Allocate the NET BUFFER list pools for receive indication. */ + NdisZeroMemory(&pool_parameters, sizeof(NET_BUFFER_LIST_POOL_PARAMETERS)); + pool_parameters.Header.Type = NDIS_OBJECT_TYPE_DEFAULT; + pool_parameters.Header.Revision = NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1; + pool_parameters.Header.Size = sizeof(pool_parameters); + pool_parameters.ProtocolId = 0; + pool_parameters.ContextSize = 0; + pool_parameters.fAllocateNetBuffer = TRUE; + pool_parameters.PoolTag = 'CRPI'; + + p_port->buf_mgr.h_packet_pool = NdisAllocateNetBufferListPool( + p_port->p_adapter->h_adapter, + &pool_parameters); + + if( !p_port->buf_mgr.h_packet_pool ) + { + NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, + EVENT_IPOIB_RECV_PKT_POOL, 1, NDIS_STATUS_RESOURCES ); + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("NdisAllocatePacketPool returned %08X\n", (UINT)NDIS_STATUS_RESOURCES) ); + return IB_INSUFFICIENT_RESOURCES; + } +/* + NdisAllocateBufferPool( &ndis_status, &p_port->buf_mgr.h_buffer_pool, + p_params->rq_depth ); + if( ndis_status != NDIS_STATUS_SUCCESS ) + { + NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, + EVENT_IPOIB_RECV_BUF_POOL, 1, ndis_status ); + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("NdisAllocateBufferPool returned %08X\n", ndis_status) ); + return IB_INSUFFICIENT_RESOURCES; + } +*/ + /* Allocate the NET buffer list pool for send formatting. */ + pool_parameters.PoolTag = 'XTPI'; + + p_port->buf_mgr.h_send_pkt_pool = NdisAllocateNetBufferListPool( + p_port->p_adapter->h_adapter, + &pool_parameters); + if( !p_port->buf_mgr.h_send_pkt_pool) + { + NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, + EVENT_IPOIB_SEND_PKT_POOL, 1, NDIS_STATUS_RESOURCES ); + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("NdisAllocatePacketPool returned %08X\n", (UINT)NDIS_STATUS_RESOURCES) ); + return IB_INSUFFICIENT_RESOURCES; + } +/* + NdisAllocateBufferPool( &ndis_status, + &p_port->buf_mgr.h_send_buf_pool, 1 ); + if( ndis_status != NDIS_STATUS_SUCCESS ) + { + NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, + EVENT_IPOIB_SEND_BUF_POOL, 1, ndis_status ); + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("NdisAllocateBufferPool returned %08X\n", ndis_status) ); + return IB_INSUFFICIENT_RESOURCES; + } +*/ + IPOIB_EXIT( IPOIB_DBG_INIT ); + return IB_SUCCESS; +} + + +static void +__buf_mgr_destroy( + IN ipoib_port_t* const p_port ) +{ + IPOIB_ENTER(IPOIB_DBG_INIT ); + + CL_ASSERT( p_port ); + + /* Destroy the send packet and buffer pools. + if( p_port->buf_mgr.h_send_buf_pool ) + NdisFreeBufferPool( p_port->buf_mgr.h_send_buf_pool );*/ + if( p_port->buf_mgr.h_send_pkt_pool ) + NdisFreeNetBufferListPool ( p_port->buf_mgr.h_send_pkt_pool ); + + /* Destroy the receive packet and buffer pools. + if( p_port->buf_mgr.h_buffer_pool ) + NdisFreeBufferPool( p_port->buf_mgr.h_buffer_pool );*/ + if( p_port->buf_mgr.h_packet_pool ) + NdisFreeNetBufferListPool ( p_port->buf_mgr.h_packet_pool ); + + /* Free the receive and send descriptors. */ + cl_qpool_destroy( &p_port->buf_mgr.recv_pool ); + + /* Free the lookaside list of scratch buffers. */ + NdisDeleteNPagedLookasideList( &p_port->buf_mgr.send_buf_list ); + + IPOIB_EXIT( IPOIB_DBG_INIT ); +} + + +static cl_status_t +__recv_ctor( + IN void* const p_object, + IN void* context, + OUT cl_pool_item_t** const pp_pool_item ) +{ + ipoib_recv_desc_t *p_desc; + ipoib_port_t *p_port; + +#if IPOIB_INLINE_RECV + uint32_t ds0_len; +#endif + + IPOIB_ENTER( IPOIB_DBG_ALLOC ); + + CL_ASSERT( p_object ); + CL_ASSERT( context ); + + p_desc = (ipoib_recv_desc_t*)p_object; + p_port = (ipoib_port_t*)context; + + /* Setup the work request. */ + p_desc->wr.ds_array = p_desc->local_ds; + p_desc->wr.wr_id = (uintn_t)p_desc; + +#if IPOIB_INLINE_RECV + /* Sanity check on the receive buffer layout */ + CL_ASSERT( (void*)&p_desc->buf.eth.pkt.type == + (void*)&p_desc->buf.ib.pkt.type ); + CL_ASSERT( sizeof(recv_buf_t) == sizeof(ipoib_pkt_t) + sizeof(ib_grh_t) ); + + /* Setup the local data segment. */ + p_desc->local_ds[0].vaddr = cl_get_physaddr( &p_desc->buf ); + p_desc->local_ds[0].lkey = p_port->ib_mgr.lkey; + ds0_len = + PAGE_SIZE - ((uint32_t)p_desc->local_ds[0].vaddr & (PAGE_SIZE - 1)); + if( ds0_len >= sizeof(recv_buf_t) ) + { + /* The whole buffer is within a page. */ + p_desc->local_ds[0].length = ds0_len; + p_desc->wr.num_ds = 1; + } + else + { + /* The buffer crosses page boundaries. */ + p_desc->local_ds[0].length = ds0_len; + p_desc->local_ds[1].vaddr = cl_get_physaddr( + ((uint8_t*)&p_desc->buf) + ds0_len ); + p_desc->local_ds[1].lkey = p_port->ib_mgr.lkey; + p_desc->local_ds[1].length = sizeof(recv_buf_t) - ds0_len; + p_desc->wr.num_ds = 2; + } +#else /* IPOIB_INLINE_RECV */ + /* Allocate the receive buffer. */ + p_desc->p_buf = (recv_buf_t*)cl_zalloc( sizeof(recv_buf_t) ); + if( !p_desc->p_buf ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed to allocate receive buffer.\n") ); + return CL_INSUFFICIENT_MEMORY; + } + + /* Sanity check on the receive buffer layout */ + CL_ASSERT( (void*)&p_desc->p_buf->eth.pkt.type == + (void*)&p_desc->p_buf->ib.pkt.type ); + + /* Setup the local data segment. */ + p_desc->local_ds[0].vaddr = cl_get_physaddr( p_desc->p_buf ); + p_desc->local_ds[0].length = sizeof(ipoib_pkt_t) + sizeof(ib_grh_t); + p_desc->local_ds[0].lkey = p_port->ib_mgr.lkey; + p_desc->wr.num_ds = 1; +#endif /* IPOIB_INLINE_RECV */ + + *pp_pool_item = &p_desc->item; + + IPOIB_EXIT( IPOIB_DBG_ALLOC ); + return CL_SUCCESS; +} + + +#if !IPOIB_INLINE_RECV +static void +__recv_dtor( + IN const cl_pool_item_t* const p_pool_item, + IN void *context ) +{ + ipoib_recv_desc_t *p_desc; + + IPOIB_ENTER( IPOIB_DBG_ALLOC ); + + UNUSED_PARAM( context ); + + p_desc = PARENT_STRUCT( p_pool_item, ipoib_recv_desc_t, item ); + + if( p_desc->p_buf ) + cl_free( p_desc->p_buf ); + + IPOIB_EXIT( IPOIB_DBG_ALLOC ); +} +#endif + + +static inline ipoib_recv_desc_t* +__buf_mgr_get_recv( + IN ipoib_port_t* const p_port ) +{ + ipoib_recv_desc_t *p_desc; + IPOIB_ENTER( IPOIB_DBG_RECV ); + p_desc = (ipoib_recv_desc_t*)cl_qpool_get( &p_port->buf_mgr.recv_pool ); + /* Reference the port object for the send. */ + if( p_desc ) + { + ipoib_port_ref( p_port, ref_get_recv ); + CL_ASSERT( p_desc->wr.wr_id == (uintn_t)p_desc ); +#if IPOIB_INLINE_RECV + CL_ASSERT( p_desc->local_ds[0].vaddr == + cl_get_physaddr( &p_desc->buf ) ); +#else /* IPOIB_INLINE_RECV */ + CL_ASSERT( p_desc->local_ds[0].vaddr == + cl_get_physaddr( p_desc->p_buf ) ); + CL_ASSERT( p_desc->local_ds[0].length == + (sizeof(ipoib_pkt_t) + sizeof(ib_grh_t)) ); +#endif /* IPOIB_INLINE_RECV */ + CL_ASSERT( p_desc->local_ds[0].lkey == p_port->ib_mgr.lkey ); + } + IPOIB_EXIT( IPOIB_DBG_RECV ); + return p_desc; +} + + +//NDIS60 +static inline void +__buf_mgr_put_recv( + IN ipoib_port_t* const p_port, + IN ipoib_recv_desc_t* const p_desc, + IN NET_BUFFER_LIST* const p_net_buffer_list OPTIONAL ) +{ + NET_BUFFER *p_buf = NULL; + MDL *p_mdl = NULL; + IPOIB_ENTER(IPOIB_DBG_RECV ); + + if( p_net_buffer_list ) + { + NET_BUFFER_LIST_NEXT_NBL(p_net_buffer_list) = NULL; + p_buf = NET_BUFFER_LIST_FIRST_NB(p_net_buffer_list); + CL_ASSERT( p_buf ); + p_mdl = NET_BUFFER_FIRST_MDL(p_buf); + CL_ASSERT( p_mdl ); + NdisFreeMdl(p_mdl); + NdisFreeNetBufferList(p_net_buffer_list); + } + + /* Return the descriptor to its pools. */ + cl_qpool_put( &p_port->buf_mgr.recv_pool, &p_desc->item ); + + /* + * Dereference the port object since the receive is no longer outstanding. + */ + ipoib_port_deref( p_port, ref_get_recv ); + IPOIB_EXIT( IPOIB_DBG_RECV ); +} + + +static inline void +__buf_mgr_put_recv_list( + IN ipoib_port_t* const p_port, + IN cl_qlist_t* const p_list ) +{ + //IPOIB_ENTER( IPOIB_DBG_RECV ); + cl_qpool_put_list( &p_port->buf_mgr.recv_pool, p_list ); + //IPOIB_EXIT( IPOIB_DBG_RECV ); +} + + +static inline NET_BUFFER_LIST* +__buf_mgr_get_ndis_pkt( + IN ipoib_port_t* const p_port, + IN ipoib_recv_desc_t* const p_desc ) +{ + NET_BUFFER_LIST *p_net_buffer_list; + MDL *p_mdl; + + IPOIB_ENTER( IPOIB_DBG_RECV ); + + p_mdl = NdisAllocateMdl(p_port->p_adapter->h_adapter, + &p_desc->buf.eth.pkt, + p_desc->len ); + if( !p_mdl ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed to allocate MDL\n") ); + return NULL; + } + + p_net_buffer_list = NdisAllocateNetBufferAndNetBufferList( + p_port->buf_mgr.h_packet_pool, + 0, + 0, + p_mdl, + 0, + 0); + + if( !p_net_buffer_list ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed to allocate NET_BUFFER_LIST\n") ); + NdisFreeMdl(p_mdl); + return NULL; + } + + NET_BUFFER_LIST_NEXT_NBL(p_net_buffer_list) = NULL; + IPOIB_PORT_FROM_PACKET( p_net_buffer_list ) = p_port; + IPOIB_RECV_FROM_PACKET( p_net_buffer_list ) = p_desc; + p_net_buffer_list->SourceHandle = p_port->p_adapter->h_adapter; + + IPOIB_EXIT( IPOIB_DBG_RECV ); + return p_net_buffer_list; +} + + +/****************************************************************************** +* +* Receive manager implementation. +* +******************************************************************************/ +static void +__recv_mgr_construct( + IN ipoib_port_t* const p_port ) +{ + IPOIB_ENTER( IPOIB_DBG_INIT ); + + cl_qlist_init( &p_port->recv_mgr.done_list ); + + p_port->recv_mgr.recv_pkt_array = NULL; + + IPOIB_EXIT( IPOIB_DBG_INIT ); +} + + +static ib_api_status_t +__recv_mgr_init( + IN ipoib_port_t* const p_port ) +{ + IPOIB_ENTER( IPOIB_DBG_INIT ); + + /* Allocate the NDIS_PACKET pointer array for indicating receives. */ + p_port->recv_mgr.recv_pkt_array = (NET_BUFFER_LIST **)cl_malloc( + sizeof(NET_BUFFER_LIST*) * p_port->p_adapter->params.rq_depth ); + if( !p_port->recv_mgr.recv_pkt_array ) + { + NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, + EVENT_IPOIB_RECV_PKT_ARRAY, 0 ); + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("cl_malloc for PNDIS_PACKET array failed.\n") ); + return IB_INSUFFICIENT_MEMORY; + } + + IPOIB_EXIT( IPOIB_DBG_INIT ); + return IB_SUCCESS; +} + + +static void +__recv_mgr_destroy( + IN ipoib_port_t* const p_port ) +{ + IPOIB_ENTER( IPOIB_DBG_INIT ); + + CL_ASSERT( cl_is_qlist_empty( &p_port->recv_mgr.done_list ) ); + CL_ASSERT( !p_port->recv_mgr.depth ); + + if( p_port->recv_mgr.recv_pkt_array ) + cl_free( p_port->recv_mgr.recv_pkt_array ); + + IPOIB_EXIT( IPOIB_DBG_INIT ); +} + + +/* + * Posts receive buffers to the receive queue and returns the number + * of receives needed to bring the RQ to its low water mark. Note + * that the value is signed, and can go negative. All tests must + * be for > 0. + */ +int32_t +__recv_mgr_repost( + IN ipoib_port_t* const p_port ) +{ + ipoib_recv_desc_t *p_head = NULL, *p_tail = NULL, *p_next; + ib_api_status_t status; + ib_recv_wr_t *p_failed; + PERF_DECLARE( GetRecv ); + PERF_DECLARE( PostRecv ); + + IPOIB_ENTER( IPOIB_DBG_RECV ); + + CL_ASSERT( p_port ); + cl_obj_lock( &p_port->obj ); + if( p_port->state != IB_QPS_RTS ) + { + cl_obj_unlock( &p_port->obj ); + IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_RECV, + ("Port in invalid state. Not reposting.\n") ); + return 0; + } + ipoib_port_ref( p_port, ref_repost ); + cl_obj_unlock( &p_port->obj ); + + while( p_port->recv_mgr.depth < p_port->p_adapter->params.rq_depth ) + { + /* Pull receives out of the pool and chain them up. */ + cl_perf_start( GetRecv ); + p_next = __buf_mgr_get_recv( p_port ); + cl_perf_stop( &p_port->p_adapter->perf, GetRecv ); + if( !p_next ) + { + IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_RECV, + ("Out of receive descriptors! recv queue depth 0x%x\n",p_port->recv_mgr.depth) ); + break; + } + + if( !p_tail ) + { + p_tail = p_next; + p_next->wr.p_next = NULL; + } + else + { + p_next->wr.p_next = &p_head->wr; + } + + p_head = p_next; + + p_port->recv_mgr.depth++; + } + + if( p_head ) + { + cl_perf_start( PostRecv ); + status = p_port->p_adapter->p_ifc->post_recv( + p_port->ib_mgr.h_qp, &p_head->wr, &p_failed ); + cl_perf_stop( &p_port->p_adapter->perf, PostRecv ); + + if( status != IB_SUCCESS ) + { + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ip_post_recv returned %s\n", + p_port->p_adapter->p_ifc->get_err_str( status )) ); + /* return the descriptors to the pool */ + while( p_failed ) + { + p_head = PARENT_STRUCT( p_failed, ipoib_recv_desc_t, wr ); + p_failed = p_failed->p_next; + + __buf_mgr_put_recv( p_port, p_head, NULL ); + p_port->recv_mgr.depth--; + } + } + } + + ipoib_port_deref( p_port, ref_repost ); + IPOIB_EXIT( IPOIB_DBG_RECV ); + return p_port->p_adapter->params.rq_low_watermark - p_port->recv_mgr.depth; +} + +void +ipoib_return_net_buffer_list( + IN NDIS_HANDLE adapter_context, + IN NET_BUFFER_LIST *p_net_buffer_lists, + IN ULONG return_flags) +{ +// cl_list_item_t *p_item; + ipoib_port_t *p_port; + ipoib_recv_desc_t *p_desc; + NET_BUFFER_LIST *cur_net_buffer_list,*next_net_buffer_list; +// ib_api_status_t status = IB_NOT_DONE; +// int32_t shortage; +// ULONG complete_flags = 0; + PERF_DECLARE( ReturnPacket ); + PERF_DECLARE( ReturnPutRecv ); + PERF_DECLARE( ReturnRepostRecv ); + PERF_DECLARE( ReturnPreparePkt ); + PERF_DECLARE( ReturnNdisIndicate ); + + IPOIB_ENTER( IPOIB_DBG_RECV ); + + UNUSED_PARAM( return_flags ); + + p_port = ((ipoib_adapter_t*)adapter_context)->p_port; + CL_ASSERT( p_net_buffer_lists ); + + cl_perf_start( ReturnPacket ); + cl_spinlock_acquire( &p_port->recv_lock ); + for (cur_net_buffer_list = p_net_buffer_lists; + cur_net_buffer_list != NULL; + cur_net_buffer_list = next_net_buffer_list) + { + next_net_buffer_list = NET_BUFFER_LIST_NEXT_NBL(cur_net_buffer_list); + + /* Get the port and descriptor from the packet. */ + CL_ASSERT(p_port == IPOIB_PORT_FROM_PACKET( cur_net_buffer_list )); + p_desc = IPOIB_RECV_FROM_PACKET( cur_net_buffer_list ); + + + //TODO: NDIS60, rewrite this block + /* Get descriptor from the packet. */ +#if 0 + if( p_desc->type == PKT_TYPE_CM_UCAST ) + { + NDIS_BUFFER *p_buf; + + /* Unchain the NDIS buffer. */ + NdisUnchainBufferAtFront( p_packet, &p_buf ); + CL_ASSERT( p_buf ); + /* Return the NDIS packet and NDIS buffer to their pools. */ + NdisDprFreePacketNonInterlocked( p_packet ); + NdisFreeBuffer( p_buf ); + + endpt_cm_buf_mgr_put_recv( &p_port->cm_buf_mgr, (ipoib_cm_desc_t *)p_desc ); + status = endpt_cm_post_recv( p_port ); + if( status != IB_SUCCESS ) + { + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Post Recv QP failed\n" ) ); + } + cl_spinlock_release( &p_port->recv_lock ); + return; + } +#endif + + cl_perf_start( ReturnPutRecv ); + __buf_mgr_put_recv( p_port, p_desc, cur_net_buffer_list ); + cl_perf_stop( &p_port->p_adapter->perf, ReturnPutRecv ); + } +#if 0 + /* Repost buffers. */ + cl_perf_start( ReturnRepostRecv ); + shortage = __recv_mgr_repost( p_port ); + cl_perf_stop( &p_port->p_adapter->perf, ReturnRepostRecv ); + + for( p_item = cl_qlist_remove_head( &p_port->recv_mgr.done_list ); + p_item != cl_qlist_end( &p_port->recv_mgr.done_list ); + p_item = cl_qlist_remove_head( &p_port->recv_mgr.done_list ) ) + { + p_desc = (ipoib_recv_desc_t*)p_item; + + cl_perf_start( ReturnPreparePkt ); + status = __recv_mgr_prepare_pkt( p_port, p_desc, &cur_net_buffer_list ); + cl_perf_stop( &p_port->p_adapter->perf, ReturnPreparePkt ); + if( status == IB_SUCCESS ) + { + if( shortage > 0 ) + NET_BUFFER_LIST_STATUS( cur_net_buffer_list) = NDIS_STATUS_RESOURCES; + else + NET_BUFFER_LIST_STATUS( cur_net_buffer_list) = NDIS_STATUS_SUCCESS; + + cl_spinlock_release( &p_port->recv_lock ); + NET_BUFFER_LIST_NEXT_NBL(cur_net_buffer_list) = NULL; + cl_perf_start( ReturnNdisIndicate ); + NdisMRecvIndicate( p_port->p_adapter->h_adapter, + cur_net_buffer_list, complete_flags ); + cl_perf_stop( &p_port->p_adapter->perf, ReturnNdisIndicate ); + cl_spinlock_acquire( &p_port->recv_lock ); + + if( shortage > 0 ) + { + cl_perf_start( ReturnPutRecv ); + __buf_mgr_put_recv( p_port, p_desc, cur_net_buffer_list ); + cl_perf_stop( &p_port->p_adapter->perf, ReturnPutRecv ); + + /* Repost buffers. */ + cl_perf_start( ReturnRepostRecv ); + shortage = __recv_mgr_repost( p_port ); + cl_perf_stop( &p_port->p_adapter->perf, ReturnRepostRecv ); + } + } + else if( status != IB_NOT_DONE ) + { + IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_RECV, + ("__recv_mgr_prepare_pkt returned %s\n", + p_port->p_adapter->p_ifc->get_err_str( status )) ); + /* Return the item to the head of the list. */ + cl_qlist_insert_head( &p_port->recv_mgr.done_list, p_item ); + break; + } + } + #endif + cl_spinlock_release( &p_port->recv_lock ); + cl_perf_stop( &p_port->p_adapter->perf, ReturnPacket ); + + IPOIB_EXIT( IPOIB_DBG_RECV ); +} + +static void __recv_cb_dpc(KDPC *p_gc_dpc,void *context,void * s_arg1 , void * s_arg2) +{ + + ipoib_port_t *p_port = (ipoib_port_t *) context; + + UNREFERENCED_PARAMETER(p_gc_dpc); + UNREFERENCED_PARAMETER(s_arg1); + UNREFERENCED_PARAMETER(s_arg2); + + + __recv_cb(NULL, p_port); + ipoib_port_deref( p_port, ref_recv_cb ); + + +} + + +static void +__recv_cb( + IN const ib_cq_handle_t h_cq, + IN void *cq_context ) +{ + ipoib_port_t *p_port; + ib_api_status_t status; + ib_wc_t wc[MAX_RECV_WC], *p_free, *p_wc; + int32_t pkt_cnt, recv_cnt = 0, shortage, discarded; + cl_qlist_t done_list, bad_list; + size_t i; + ULONG recv_complete_flags = 0; + + PERF_DECLARE( RecvCompBundle ); + PERF_DECLARE( RecvCb ); + PERF_DECLARE( PollRecv ); + PERF_DECLARE( RepostRecv ); + PERF_DECLARE( FilterRecv ); + PERF_DECLARE( BuildPktArray ); + PERF_DECLARE( RecvNdisIndicate ); + PERF_DECLARE( RearmRecv ); + PERF_DECLARE( PutRecvList ); + + IPOIB_ENTER( IPOIB_DBG_RECV ); + + cl_perf_clr( RecvCompBundle ); + + cl_perf_start( RecvCb ); +//return ; + UNUSED_PARAM( h_cq ); + + NDIS_SET_SEND_COMPLETE_FLAG(recv_complete_flags, NDIS_RECEIVE_FLAGS_DISPATCH_LEVEL ); + + p_port = (ipoib_port_t*)cq_context; + + cl_qlist_init( &done_list ); + cl_qlist_init( &bad_list ); + + ipoib_port_ref( p_port, ref_recv_cb ); + for( i = 0; i < MAX_RECV_WC; i++ ) + wc[i].p_next = &wc[i + 1]; + wc[MAX_RECV_WC - 1].p_next = NULL; + + /* + * We'll be accessing the endpoint map so take a reference + * on it to prevent modifications. + */ + cl_obj_lock( &p_port->obj ); + cl_atomic_inc( &p_port->endpt_rdr ); + cl_obj_unlock( &p_port->obj ); + + do + { + /* If we get here, then the list of WCs is intact. */ + p_free = wc; + + cl_perf_start( PollRecv ); + status = p_port->p_adapter->p_ifc->poll_cq( + p_port->ib_mgr.h_recv_cq, &p_free, &p_wc ); + cl_perf_stop( &p_port->p_adapter->perf, PollRecv ); + CL_ASSERT( status == IB_SUCCESS || status == IB_NOT_FOUND ); + + /* Look at the payload now and filter ARP and DHCP packets. */ + cl_perf_start( FilterRecv ); + recv_cnt += __recv_mgr_filter( p_port, p_wc, &done_list, &bad_list ); + cl_perf_stop( &p_port->p_adapter->perf, FilterRecv ); + + } while( (!p_free) && (recv_cnt < 128)); + + /* We're done looking at the endpoint map, release the reference. */ + cl_atomic_dec( &p_port->endpt_rdr ); + + cl_perf_log( &p_port->p_adapter->perf, RecvCompBundle, recv_cnt ); + + cl_spinlock_acquire( &p_port->recv_lock ); + + /* Update our posted depth. */ + p_port->recv_mgr.depth -= recv_cnt; + + /* Return any discarded receives to the pool */ + cl_perf_start( PutRecvList ); + __buf_mgr_put_recv_list( p_port, &bad_list ); + cl_perf_stop( &p_port->p_adapter->perf, PutRecvList ); + + do + { + int32_t cnt; + /* Repost ASAP so we don't starve the RQ. */ + cl_perf_start( RepostRecv ); + shortage = __recv_mgr_repost( p_port ); + cl_perf_stop( &p_port->p_adapter->perf, RepostRecv ); + + cl_perf_start( BuildPktArray ); + /* Notify NDIS of any and all possible receive buffers. */ + pkt_cnt = __recv_mgr_build_pkt_array( + p_port, shortage, &done_list, &discarded ); + cl_perf_stop( &p_port->p_adapter->perf, BuildPktArray ); + + /* Only indicate receives if we actually had any. */ + if( discarded && shortage > 0 ) + { + /* We may have thrown away packets, and have a shortage */ + cl_perf_start( RepostRecv ); + __recv_mgr_repost( p_port ); + cl_perf_stop( &p_port->p_adapter->perf, RepostRecv ); + } + + if( !pkt_cnt ) + break; + + cl_spinlock_release( &p_port->recv_lock ); + for( cnt = 0; cnt < pkt_cnt -1; cnt++) + { + NET_BUFFER_LIST_NEXT_NBL(p_port->recv_mgr.recv_pkt_array[cnt]) = + p_port->recv_mgr.recv_pkt_array[cnt + 1]; + } + cl_perf_start( RecvNdisIndicate ); +#ifndef NDIS_DEFAULT_PORT_NUMBER +#define NDIS_DEFAULT_PORT_NUMBER 0 +#endif + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Indicate NDIS with %d received NBs\n", + pkt_cnt) ); + NdisMIndicateReceiveNetBufferLists( + p_port->p_adapter->h_adapter, + p_port->recv_mgr.recv_pkt_array[0], + NDIS_DEFAULT_PORT_NUMBER, + pkt_cnt, + recv_complete_flags); + + cl_perf_stop( &p_port->p_adapter->perf, RecvNdisIndicate ); + + /* + * Cap the number of receives to put back to what we just indicated + * with NDIS_STATUS_RESOURCES. + */ + if( shortage > 0 ) + { + if( pkt_cnt < shortage ) + shortage = pkt_cnt; + + /* Return all but the last packet to the pool. */ + cl_spinlock_acquire( &p_port->recv_lock ); + while( shortage-- > 1 ) + { + __buf_mgr_put_recv( p_port, + (ipoib_recv_desc_t *)IPOIB_RECV_FROM_PACKET( p_port->recv_mgr.recv_pkt_array[shortage] ), + p_port->recv_mgr.recv_pkt_array[shortage] ); + } + cl_spinlock_release( &p_port->recv_lock ); + + /* + * Return the last packet as if NDIS returned it, so that we repost + * and report any other pending receives. + */ + ipoib_return_net_buffer_list( NULL, p_port->recv_mgr.recv_pkt_array[0],recv_complete_flags ); + } + cl_spinlock_acquire( &p_port->recv_lock ); + + } while( pkt_cnt ); + cl_spinlock_release( &p_port->recv_lock ); + + if (p_free ) { + /* + * Rearm after filtering to prevent contention on the enpoint maps + * and eliminate the possibility of having a call to + * __endpt_mgr_insert find a duplicate. + */ + cl_perf_start( RearmRecv ); + status = p_port->p_adapter->p_ifc->rearm_cq( + p_port->ib_mgr.h_recv_cq, FALSE ); + cl_perf_stop( &p_port->p_adapter->perf, RearmRecv ); + CL_ASSERT( status == IB_SUCCESS ); + + ipoib_port_deref( p_port, ref_recv_cb ); + } else { + // Please note the reference is still up + KeInsertQueueDpc(&p_port->recv_dpc, NULL, NULL); + } + + cl_perf_stop( &p_port->p_adapter->perf, RecvCb ); + + IPOIB_EXIT( IPOIB_DBG_RECV ); +} + + +static void +__recv_get_endpts( + IN ipoib_port_t* const p_port, + IN ipoib_recv_desc_t* const p_desc, + IN ib_wc_t* const p_wc, + OUT ipoib_endpt_t** const pp_src, + OUT ipoib_endpt_t** const pp_dst ) +{ + ib_api_status_t status; + mac_addr_t mac; + PERF_DECLARE( GetEndptByGid ); + PERF_DECLARE( GetEndptByLid ); + PERF_DECLARE( EndptInsert ); + + IPOIB_ENTER( IPOIB_DBG_RECV ); + + /* Setup our shortcut pointers based on whether GRH is valid. */ + if( p_wc->recv.ud.recv_opt & IB_RECV_OPT_GRH_VALID ) + { + /* Lookup the source endpoints based on GID. */ + cl_perf_start( GetEndptByGid ); + *pp_src = +#if IPOIB_INLINE_RECV + __endpt_mgr_get_by_gid( p_port, &p_desc->buf.ib.grh.src_gid ); +#else /* IPOIB_INLINE_RECV */ + __endpt_mgr_get_by_gid( p_port, &p_desc->p_buf->ib.grh.src_gid ); +#endif /* IPOIB_INLINE_RECV */ + cl_perf_stop( &p_port->p_adapter->perf, GetEndptByGid ); + + /* + * Lookup the destination endpoint based on GID. + * This is used along with the packet filter to determine + * whether to report this to NDIS. + */ + cl_perf_start( GetEndptByGid ); + *pp_dst = +#if IPOIB_INLINE_RECV + __endpt_mgr_get_by_gid( p_port, &p_desc->buf.ib.grh.dest_gid ); +#else /* IPOIB_INLINE_RECV */ + __endpt_mgr_get_by_gid( p_port, &p_desc->p_buf->ib.grh.dest_gid ); +#endif /* IPOIB_INLINE_RECV */ + cl_perf_stop( &p_port->p_adapter->perf, GetEndptByGid ); + + /* + * Create the source endpoint if it does not exist. Note that we + * can only do this for globally routed traffic since we need the + * information from the GRH to generate the MAC. + */ + if( !*pp_src ) + { + status = ipoib_mac_from_guid( +#if IPOIB_INLINE_RECV + p_desc->buf.ib.grh.src_gid.unicast.interface_id, p_port->p_adapter->params.guid_mask, &mac ); +#else /* IPOIB_INLINE_RECV */ + p_desc->p_buf->ib.grh.src_gid.unicast.interface_id, p_port->p_adapter->params.guid_mask, &mac ); +#endif /* IPOIB_INLINE_RECV */ + if( status != IB_SUCCESS ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ipoib_mac_from_guid returned %s\n", + p_port->p_adapter->p_ifc->get_err_str( status )) ); + return; + } + + /* Create the endpoint. */ +#if IPOIB_INLINE_RECV + *pp_src = ipoib_endpt_create( &p_desc->buf.ib.grh.src_gid, +#else /* IPOIB_INLINE_RECV */ + *pp_src = ipoib_endpt_create( &p_desc->p_buf->ib.grh.src_gid, +#endif /* IPOIB_INLINE_RECV */ + p_wc->recv.ud.remote_lid, p_wc->recv.ud.remote_qp ); + if( !*pp_src ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ipoib_endpt_create failed\n") ); + return; + } + cl_perf_start( EndptInsert ); + cl_obj_lock( &p_port->obj ); + status = __endpt_mgr_insert( p_port, mac, *pp_src ); + if( status != IB_SUCCESS ) + { + cl_obj_unlock( &p_port->obj ); + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("__endpt_mgr_insert returned %s\n", + p_port->p_adapter->p_ifc->get_err_str( status )) ); + *pp_src = NULL; + return; + } + cl_obj_unlock( &p_port->obj ); + cl_perf_stop( &p_port->p_adapter->perf, EndptInsert ); + } + } + else + { + /* + * Lookup the remote endpoint based on LID. Note that only + * unicast traffic can be LID routed. + */ + cl_perf_start( GetEndptByLid ); + *pp_src = __endpt_mgr_get_by_lid( p_port, p_wc->recv.ud.remote_lid ); + cl_perf_stop( &p_port->p_adapter->perf, GetEndptByLid ); + *pp_dst = p_port->p_local_endpt; + CL_ASSERT( *pp_dst ); + } + + if( *pp_src && !ipoib_is_voltaire_router_gid( &(*pp_src)->dgid ) && + (*pp_src)->qpn != p_wc->recv.ud.remote_qp ) + { + /* Update the QPN for the endpoint. */ + IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_RECV, + ("Updating QPN for MAC: %02X-%02X-%02X-%02X-%02X-%02X\n", + (*pp_src )->mac.addr[0], (*pp_src )->mac.addr[1], + (*pp_src )->mac.addr[2], (*pp_src )->mac.addr[3], + (*pp_src )->mac.addr[4], (*pp_src )->mac.addr[5]) ); +// (*pp_src)->qpn = p_wc->recv.ud.remote_qp; + } + + if( *pp_src && *pp_dst ) + { + IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_RECV, + ("Recv:\n" + "\tsrc MAC: %02X-%02X-%02X-%02X-%02X-%02X\n" + "\tdst MAC: %02X-%02X-%02X-%02X-%02X-%02X\n", + (*pp_src )->mac.addr[0], (*pp_src )->mac.addr[1], + (*pp_src )->mac.addr[2], (*pp_src )->mac.addr[3], + (*pp_src )->mac.addr[4], (*pp_src )->mac.addr[5], + (*pp_dst )->mac.addr[0], (*pp_dst )->mac.addr[1], + (*pp_dst )->mac.addr[2], (*pp_dst )->mac.addr[3], + (*pp_dst )->mac.addr[4], (*pp_dst )->mac.addr[5]) ); + } + + IPOIB_EXIT( IPOIB_DBG_RECV ); +} + + +static int32_t +__recv_mgr_filter( + IN ipoib_port_t* const p_port, + IN ib_wc_t* const p_done_wc_list, + OUT cl_qlist_t* const p_done_list, + OUT cl_qlist_t* const p_bad_list ) +{ + ipoib_recv_desc_t *p_desc; + ib_wc_t *p_wc; + ipoib_pkt_t *p_ipoib; + eth_pkt_t *p_eth; + ipoib_endpt_t *p_src, *p_dst; + ib_api_status_t status; + uint32_t len; + int32_t recv_cnt = 0; + PERF_DECLARE( GetRecvEndpts ); + PERF_DECLARE( RecvGen ); + PERF_DECLARE( RecvTcp ); + PERF_DECLARE( RecvUdp ); + PERF_DECLARE( RecvDhcp ); + PERF_DECLARE( RecvArp ); + + IPOIB_ENTER( IPOIB_DBG_RECV ); + + for( p_wc = p_done_wc_list; p_wc; p_wc = p_wc->p_next ) + { + CL_ASSERT( p_wc->status != IB_WCS_SUCCESS || p_wc->wc_type == IB_WC_RECV ); + p_desc = (ipoib_recv_desc_t*)(uintn_t)p_wc->wr_id; + recv_cnt++; + + if( p_wc->status != IB_WCS_SUCCESS ) + { + if( p_wc->status != IB_WCS_WR_FLUSHED_ERR ) + { + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed completion %s (vendor specific %#x)\n", + p_port->p_adapter->p_ifc->get_wc_status_str( p_wc->status ), + (int)p_wc->vendor_specific) ); + ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_ERROR, 0, 0 ); + } + else + { + IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_RECV, + ("Flushed completion %s\n", + p_port->p_adapter->p_ifc->get_wc_status_str( p_wc->status )) ); + ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_DROPPED, 0, 0 ); + } + cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item ); + /* Dereference the port object on behalf of the failed receive. */ + ipoib_port_deref( p_port, ref_failed_recv_wc ); + continue; + } + + len = p_wc->length - sizeof(ib_grh_t); + + if( len < sizeof(ipoib_hdr_t) ) + { + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Received ETH packet < min size\n") ); + ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_ERROR, 0, 0 ); + cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item ); + ipoib_port_deref( p_port, ref_recv_inv_len ); + continue; + } + + if((len - sizeof(ipoib_hdr_t)) > p_port->p_adapter->params.payload_mtu) + { + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Received ETH packet len %d > payload MTU (%d)\n", + (len - sizeof(ipoib_hdr_t)), + p_port->p_adapter->params.payload_mtu) ); + ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_ERROR, 0, 0 ); + cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item ); + ipoib_port_deref( p_port, ref_recv_inv_len ); + continue; + + } + /* Successful completion. Get the receive information. */ + p_desc->ndis_csum.Value = ( ( p_wc->recv.ud.recv_opt & IB_RECV_OPT_CSUM_MASK ) >> 8 ); + p_desc->len = len + 14 - 4 ; + cl_perf_start( GetRecvEndpts ); + __recv_get_endpts( p_port, p_desc, p_wc, &p_src, &p_dst ); + cl_perf_stop( &p_port->p_adapter->perf, GetRecvEndpts ); + +#if IPOIB_INLINE_RECV + p_ipoib = &p_desc->buf.ib.pkt; + p_eth = &p_desc->buf.eth.pkt; +#else /* IPOIB_INLINE_RECV */ + p_ipoib = &p_desc->p_buf->ib.pkt; + p_eth = &p_desc->p_buf->eth.pkt; +#endif /*IPOIB_INLINE_RECV */ + + if( p_src ) + { + /* Don't report loopback traffic - we requested SW loopback. */ + if( !cl_memcmp( &p_port->p_adapter->params.conf_mac, + &p_src->mac, sizeof(p_port->p_adapter->params.conf_mac) ) ) + { + /* + * "This is not the packet you're looking for" - don't update + * receive statistics, the packet never happened. + */ + cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item ); + /* Dereference the port object on behalf of the failed recv. */ + ipoib_port_deref( p_port, ref_recv_loopback ); + continue; + } + } + + switch( p_ipoib->hdr.type ) + { + case ETH_PROT_TYPE_IP: + if( len < (sizeof(ipoib_hdr_t) + sizeof(ip_hdr_t)) ) + { + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Received IP packet < min size\n") ); + status = IB_INVALID_SETTING; + break; + } + + if( p_ipoib->type.ip.hdr.offset || + p_ipoib->type.ip.hdr.prot != IP_PROT_UDP ) + { + /* Unfiltered. Setup the ethernet header and report. */ + cl_perf_start( RecvTcp ); + status = __recv_gen( p_ipoib, p_eth, p_src, p_dst ); + cl_perf_stop( &p_port->p_adapter->perf, RecvTcp ); + break; + } + + /* First packet of a UDP transfer. */ + if( len < + (sizeof(ipoib_hdr_t) + sizeof(ip_hdr_t) + sizeof(udp_hdr_t)) ) + { + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Received UDP packet < min size\n") ); + status = IB_INVALID_SETTING; + break; + } + + /* Check if DHCP conversion is required. */ + if( (p_ipoib->type.ip.prot.udp.hdr.dst_port == DHCP_PORT_SERVER && + p_ipoib->type.ip.prot.udp.hdr.src_port == DHCP_PORT_CLIENT) || + (p_ipoib->type.ip.prot.udp.hdr.dst_port == DHCP_PORT_CLIENT && + p_ipoib->type.ip.prot.udp.hdr.src_port == DHCP_PORT_SERVER) ) + { + if( len < (sizeof(ipoib_hdr_t) + sizeof(ip_hdr_t) + + sizeof(udp_hdr_t) + DHCP_MIN_SIZE) ) + { + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Received DHCP < min size\n") ); + status = IB_INVALID_SETTING; + break; + } + if ((p_ipoib->type.ip.hdr.ver_hl & 0x0f) != 5 ) { + // If there are IP options in this message, we are in trouble in any case + status = IB_INVALID_SETTING; + break; + } + /* UDP packet with BOOTP ports in src/dst port numbers. */ + cl_perf_start( RecvDhcp ); + status = __recv_dhcp( p_port, p_ipoib, p_eth, p_src, p_dst ); + cl_perf_stop( &p_port->p_adapter->perf, RecvDhcp ); + } + else + { + /* Unfiltered. Setup the ethernet header and report. */ + cl_perf_start( RecvUdp ); + status = __recv_gen( p_ipoib, p_eth, p_src, p_dst ); + cl_perf_stop( &p_port->p_adapter->perf, RecvUdp ); + } + break; + + case ETH_PROT_TYPE_ARP: + if( len < (sizeof(ipoib_hdr_t) + sizeof(ipoib_arp_pkt_t)) ) + { + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Received ARP < min size\n") ); + status = IB_INVALID_SETTING; + break; + } + cl_perf_start( RecvArp ); + status = __recv_arp( p_port, p_wc, p_ipoib, p_eth, &p_src, p_dst ); + cl_perf_stop( &p_port->p_adapter->perf, RecvArp ); + len = sizeof(ipoib_hdr_t) + sizeof(arp_pkt_t); + break; + + default: + /* Unfiltered. Setup the ethernet header and report. */ + cl_perf_start( RecvGen ); + status = __recv_gen( p_ipoib, p_eth, p_src, p_dst ); + cl_perf_stop( &p_port->p_adapter->perf, RecvGen ); + } + + if( status != IB_SUCCESS ) + { + /* Update stats. */ + ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_ERROR, 0, 0 ); + cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item ); + /* Dereference the port object on behalf of the failed receive. */ + ipoib_port_deref( p_port, ref_recv_filter ); + } + else + { + ip_stat_sel_t ip_stat; + p_desc->len = + len + sizeof(eth_hdr_t) - sizeof(ipoib_hdr_t); + if( p_dst->h_mcast) + { + if( p_dst->dgid.multicast.raw_group_id[10] == 0xFF && + p_dst->dgid.multicast.raw_group_id[11] == 0xFF && + p_dst->dgid.multicast.raw_group_id[12] == 0xFF && + p_dst->dgid.multicast.raw_group_id[13] == 0xFF ) + { + p_desc->type = PKT_TYPE_BCAST; + ip_stat = IP_STAT_BCAST_BYTES; + } + else + { + p_desc->type = PKT_TYPE_MCAST; + ip_stat = IP_STAT_MCAST_BYTES; + } + } + else + { + p_desc->type = PKT_TYPE_UCAST; + ip_stat = IP_STAT_UCAST_BYTES; + + } + cl_qlist_insert_tail( p_done_list, &p_desc->item.list_item ); + ipoib_inc_recv_stat( p_port->p_adapter, ip_stat, len, 1 ); + } + } + + IPOIB_EXIT( IPOIB_DBG_RECV ); + return recv_cnt; +} + + +static ib_api_status_t +__recv_gen( + IN const ipoib_pkt_t* const p_ipoib, + OUT eth_pkt_t* const p_eth, + IN ipoib_endpt_t* const p_src, + IN ipoib_endpt_t* const p_dst ) +{ + IPOIB_ENTER( IPOIB_DBG_RECV ); + + if( !p_src || !p_dst ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Received packet with no matching endpoints.\n") ); + return IB_NOT_DONE; + } + + /* + * Fill in the ethernet header. Note that doing so will overwrite + * the IPoIB header, so start by moving the information from the IPoIB + * header. + */ + p_eth->hdr.type = p_ipoib->hdr.type; + p_eth->hdr.src = p_src->mac; + p_eth->hdr.dst = p_dst->mac; + + if ( p_eth->hdr.dst.addr[0] == 1 && + p_eth->hdr.type == ETH_PROT_TYPE_IP && + p_eth->hdr.dst.addr[2] == 0x5E) + { + p_eth->hdr.dst.addr[1] = 0; + p_eth->hdr.dst.addr[3] = p_eth->hdr.dst.addr[3] & 0x7f; + } + if (p_dst->h_mcast) + p_dst->is_in_use = TRUE; + + IPOIB_EXIT( IPOIB_DBG_RECV ); + return IB_SUCCESS; +} + + +static ib_api_status_t +__recv_dhcp( + IN ipoib_port_t* const p_port, + IN const ipoib_pkt_t* const p_ipoib, + OUT eth_pkt_t* const p_eth, + IN ipoib_endpt_t* const p_src, + IN ipoib_endpt_t* const p_dst ) +{ + ib_api_status_t status; + dhcp_pkt_t *p_dhcp; + uint8_t *p_option; + uint8_t *p_cid = NULL; + ib_gid_t gid; + uint8_t msg = 0; + + IPOIB_ENTER( IPOIB_DBG_RECV ); + + UNUSED_PARAM( p_port ); + + /* Create the ethernet header. */ + status = __recv_gen( p_ipoib, p_eth, p_src, p_dst ); + if( status != IB_SUCCESS ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("__recv_gen returned %s.\n", + p_port->p_adapter->p_ifc->get_err_str( status )) ); + return status; + } + + /* Fixup the payload. */ + p_dhcp = &p_eth->type.ip.prot.udp.dhcp; + if( p_dhcp->op != DHCP_REQUEST && p_dhcp->op != DHCP_REPLY ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Invalid DHCP op code.\n") ); + return IB_INVALID_SETTING; + } + + /* + * Find the client identifier option, making sure to skip + * the "magic cookie". + */ + p_option = &p_dhcp->options[0]; + if ( *(uint32_t *)p_option != DHCP_COOKIE ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("DHCP cookie corrupted.\n") ); + return IB_INVALID_PARAMETER; + } + + p_option = &p_dhcp->options[4]; + while( *p_option != DHCP_OPT_END && p_option < &p_dhcp->options[312] ) + { + switch( *p_option ) + { + case DHCP_OPT_PAD: + p_option++; + break; + + case DHCP_OPT_MSG: + msg = p_option[2]; + p_option += 3; + break; + + case DHCP_OPT_CLIENT_ID: + p_cid = p_option; + /* Fall through. */ + + default: + /* + * All other options have a length byte following the option code. + * Offset by the length to get to the next option. + */ + p_option += (p_option[1] + 2); + } + } + + switch( msg ) + { + /* message from client */ + case DHCPDISCOVER: + case DHCPREQUEST: + case DHCPDECLINE: + case DHCPRELEASE: + case DHCPINFORM: + if( !p_cid ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed to find required Client-identifier option.\n") ); + return IB_INVALID_SETTING; + } + if( p_dhcp->htype != DHCP_HW_TYPE_IB ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Invalid hardware address type.\n") ); + return IB_INVALID_SETTING; + } + break; + /* message from DHCP server */ + case DHCPOFFER: + case DHCPACK: + case DHCPNAK: + break; + + default: + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Invalide message type.\n") ); + return IB_INVALID_PARAMETER; + } + p_eth->type.ip.prot.udp.hdr.chksum = 0; + p_dhcp->htype = DHCP_HW_TYPE_ETH; + p_dhcp->hlen = HW_ADDR_LEN; + + if( p_cid ) /* from client */ + { + /* Validate that the length and type of the option is as required. */ + if( p_cid[1] != 21 ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Client-identifier length not 21 as required.\n") ); + return IB_INVALID_SETTING; + } + if( p_cid[2] != DHCP_HW_TYPE_IB ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Client-identifier type is wrong.\n") ); + return IB_INVALID_SETTING; + } + /* + * Copy the GID value from the option so that we can make aligned + * accesses to the contents. + * Recover CID to standard type. + */ + cl_memcpy( &gid, &p_cid[7], sizeof(ib_gid_t) ); + p_cid[1] = HW_ADDR_LEN +1;// CID length + p_cid[2] = DHCP_HW_TYPE_ETH;// CID type + status = ipoib_mac_from_guid( gid.unicast.interface_id, p_port->p_adapter->params.guid_mask, (mac_addr_t*)&p_cid[3] ); + if (status == IB_INVALID_GUID_MASK) + { + IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_ERROR, + ("Invalid GUID mask received, rejecting it") ); + ipoib_create_log(p_port->p_adapter->h_adapter, GUID_MASK_LOG_INDEX, EVENT_IPOIB_WRONG_PARAMETER_WRN); + status = IB_SUCCESS; + } + p_cid[HW_ADDR_LEN + 3] = DHCP_OPT_END; //terminate tag + } + IPOIB_EXIT( IPOIB_DBG_RECV ); + return status; +} + + +static ib_api_status_t +__recv_arp( + IN ipoib_port_t* const p_port, + IN ib_wc_t* const p_wc, + IN const ipoib_pkt_t* const p_ipoib, + OUT eth_pkt_t* const p_eth, + IN ipoib_endpt_t** const pp_src, + IN ipoib_endpt_t* const p_dst ) +{ + ib_api_status_t status; + arp_pkt_t *p_arp; + const ipoib_arp_pkt_t *p_ib_arp; + ib_gid_t gid; + mac_addr_t mac; + ipoib_hw_addr_t null_hw = {0}; + uint8_t cm_capable = 0; + + IPOIB_ENTER( IPOIB_DBG_RECV ); + + if( !p_dst ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Unknown destination endpoint\n") ); + return IB_INVALID_SETTING; + } + + p_ib_arp = &p_ipoib->type.arp; + p_arp = &p_eth->type.arp; + + if( p_ib_arp->hw_type != ARP_HW_TYPE_IB ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ARP hardware type is not IB\n") ); + return IB_INVALID_SETTING; + } + + if( p_ib_arp->hw_size != sizeof(ipoib_hw_addr_t) ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ARP hardware address size is not sizeof(ipoib_hw_addr_t)\n") ); + return IB_INVALID_SETTING; + } + + if( p_ib_arp->prot_type != ETH_PROT_TYPE_IP ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ARP protocal type not IP\n") ); + return IB_INVALID_SETTING; + } + + cm_capable = ipoib_addr_get_flags( &p_ib_arp->src_hw ); + + /* + * If we don't have a source, lookup the endpoint specified in the payload. + */ + if( !*pp_src ) + *pp_src = __endpt_mgr_get_by_gid( p_port, &p_ib_arp->src_hw.gid ); + + /* + * If the endpoint exists for the GID, make sure + * the dlid and qpn match the arp. + */ + if( *pp_src ) + { + if( cl_memcmp( &(*pp_src)->dgid, &p_ib_arp->src_hw.gid, + sizeof(ib_gid_t) ) ) + { + /* + * GIDs for the endpoint are different. The ARP must + * have been proxied. Dereference it. + */ + *pp_src = NULL; + } + else if( (*pp_src)->dlid && + (*pp_src)->dlid != p_wc->recv.ud.remote_lid ) + { + /* Out of date! Destroy the endpoint and replace it. */ + __endpt_mgr_remove( p_port, *pp_src ); + *pp_src = NULL; + } + else if ( ! ((*pp_src)->dlid)) { + /* Out of date! Destroy the endpoint and replace it. */ + __endpt_mgr_remove( p_port, *pp_src ); + *pp_src = NULL; + } + else if( ipoib_is_voltaire_router_gid( &(*pp_src)->dgid ) ) + { + if( (*pp_src)->qpn != ipoib_addr_get_qpn( &p_ib_arp->src_hw ) && + p_wc->recv.ud.remote_qp != ipoib_addr_get_qpn( &p_ib_arp->src_hw ) ) + { + /* Out of date! Destroy the endpoint and replace it. */ + __endpt_mgr_remove( p_port, *pp_src ); + *pp_src = NULL; + } + } + else if( (*pp_src)->qpn != p_wc->recv.ud.remote_qp ) + { + /* Out of date! Destroy the endpoint and replace it. */ + __endpt_mgr_remove( p_port, *pp_src ); + *pp_src = NULL; + } + } + + /* Do we need to create an endpoint for this GID? */ + if( !*pp_src ) + { + /* Copy the src GID to allow aligned access */ + cl_memcpy( &gid, &p_ib_arp->src_hw.gid, sizeof(ib_gid_t) ); + status = ipoib_mac_from_guid( gid.unicast.interface_id, p_port->p_adapter->params.guid_mask, &mac ); + if (status == IB_INVALID_GUID_MASK) + { + IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_ERROR, + ("Invalid GUID mask received, rejecting it") ); + ipoib_create_log(p_port->p_adapter->h_adapter, GUID_MASK_LOG_INDEX, EVENT_IPOIB_WRONG_PARAMETER_WRN); + } + else if( status != IB_SUCCESS ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ipoib_mac_from_guid returned %s\n", + p_port->p_adapter->p_ifc->get_err_str( status )) ); + return status; + } + /* + * Create the endpoint. + */ + *pp_src = ipoib_endpt_create( &p_ib_arp->src_hw.gid, + p_wc->recv.ud.remote_lid, ipoib_addr_get_qpn( &p_ib_arp->src_hw ) ); + + if( !*pp_src ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ipoib_endpt_create failed\n") ); + return status; + } + + cl_obj_lock( &p_port->obj ); + status = __endpt_mgr_insert( p_port, mac, *pp_src ); + if( status != IB_SUCCESS ) + { + cl_obj_unlock( &p_port->obj ); + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("__endpt_mgr_insert return %s \n", + p_port->p_adapter->p_ifc->get_err_str( status )) ); + return status; + } + + cl_obj_unlock( &p_port->obj ); + } + + (*pp_src)->cm_flag = cm_capable; + + CL_ASSERT( !cl_memcmp( + &(*pp_src)->dgid, &p_ib_arp->src_hw.gid, sizeof(ib_gid_t) ) ); + CL_ASSERT( ipoib_is_voltaire_router_gid( &(*pp_src)->dgid ) || + (*pp_src)->qpn == ipoib_addr_get_qpn( &p_ib_arp->src_hw ) ); +#if 0 + if( p_port->p_adapter->params.cm_enabled && + p_ib_arp->op == ARP_OP_REQ && + cm_capable == IPOIB_CM_FLAG_RC ) + { + /* if we've got ARP request and RC flag is set, + save SID for connect REQ to be sent in ARP reply + when requestor's path get resolved */ + if( endpt_cm_get_state( (*pp_src) ) == IPOIB_CM_DISCONNECTED ) + { + (*pp_src)->cm_flag = cm_capable; + ipoib_addr_set_sid( + &(*pp_src)->conn.service_id, + ipoib_addr_get_qpn( &p_ib_arp->src_hw ) ); + } + } +#endif +#if 0 //DBG + if( p_port->p_adapter->params.cm_enabled ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, + (" ARP %s from ENDPT[%p] state %d CM cap: %d QPN: %#x MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", + ((p_ib_arp->op == ARP_OP_REQ )? "REQUEST" : "REPLY"), + *pp_src, endpt_cm_get_state( *pp_src ), + ((cm_capable == IPOIB_CM_FLAG_RC)? 1: 0), + cl_ntoh32( ipoib_addr_get_qpn( &p_ib_arp->src_hw ) ), + (*pp_src)->mac.addr[0], (*pp_src)->mac.addr[1], + (*pp_src)->mac.addr[2], (*pp_src)->mac.addr[3], + (*pp_src)->mac.addr[4], (*pp_src)->mac.addr[5] )); + } +#endif + + /* Now swizzle the data. */ + p_arp->hw_type = ARP_HW_TYPE_ETH; + p_arp->hw_size = sizeof(mac_addr_t); + p_arp->src_hw = (*pp_src)->mac; + p_arp->src_ip = p_ib_arp->src_ip; + + if( cl_memcmp( &p_ib_arp->dst_hw, &null_hw, sizeof(ipoib_hw_addr_t) ) ) + { + if( cl_memcmp( &p_dst->dgid, &p_ib_arp->dst_hw.gid, sizeof(ib_gid_t) ) ) + { + /* + * We received bcast ARP packet that means + * remote port lets everyone know it was changed IP/MAC + * or just activated + */ + + /* Guy: TODO: Check why this check fails in case of Voltaire IPR */ + + if ( !ipoib_is_voltaire_router_gid( &(*pp_src)->dgid ) && + !ib_gid_is_multicast( (const ib_gid_t*)&p_dst->dgid ) ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ARP: is not ARP MCAST\n") ); + return IB_INVALID_SETTING; + } + + p_arp->dst_hw = p_port->p_local_endpt->mac; + p_dst->mac = p_port->p_local_endpt->mac; + /* + * we don't care what receiver ip addr is, + * as long as OS' ARP table is global ??? + */ + p_arp->dst_ip = (net32_t)0; + } + else /* we've got reply to our ARP request */ + { + p_arp->dst_hw = p_dst->mac; + p_arp->dst_ip = p_ib_arp->dst_ip; + CL_ASSERT( p_dst->qpn == ipoib_addr_get_qpn( &p_ib_arp->dst_hw ) ); + } + } + else /* we got ARP reqeust */ + { + cl_memclr( &p_arp->dst_hw, sizeof(mac_addr_t) ); + p_arp->dst_ip = p_ib_arp->dst_ip; + } + + /* + * Create the ethernet header. Note that this is done last so that + * we have a chance to create a new endpoint. + */ + status = __recv_gen( p_ipoib, p_eth, *pp_src, p_dst ); + if( status != IB_SUCCESS ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("__recv_gen returned %s.\n", + p_port->p_adapter->p_ifc->get_err_str( status )) ); + return status; + } + + IPOIB_EXIT( IPOIB_DBG_RECV ); + return IB_SUCCESS; +} + + +static ib_api_status_t +__recv_mgr_prepare_pkt( + IN ipoib_port_t* const p_port, + IN ipoib_recv_desc_t* const p_desc, + OUT NET_BUFFER_LIST** const pp_net_buffer_list ) +{ + NDIS_STATUS status; + uint32_t pkt_filter; + ip_stat_sel_t type; + //NDIS60 + NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO chksum; + //NDIS_TCP_IP_CHECKSUM_PACKET_INFO chksum; + + PERF_DECLARE( GetNdisPkt ); + + IPOIB_ENTER( IPOIB_DBG_RECV ); + + pkt_filter = p_port->p_adapter->packet_filter; + /* Check the packet filter. */ + switch( p_desc->type ) + { + default: + case PKT_TYPE_UCAST: + + if( pkt_filter & NDIS_PACKET_TYPE_PROMISCUOUS || + pkt_filter & NDIS_PACKET_TYPE_ALL_FUNCTIONAL || + pkt_filter & NDIS_PACKET_TYPE_SOURCE_ROUTING || + pkt_filter & NDIS_PACKET_TYPE_DIRECTED ) + { + /* OK to report. */ + type = IP_STAT_UCAST_BYTES; + status = NDIS_STATUS_SUCCESS; + IPOIB_PRINT( TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, + ("Received UCAST PKT.\n")); + } + else + { + type = IP_STAT_DROPPED; + status = NDIS_STATUS_FAILURE; + IPOIB_PRINT( TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, + ("Received UCAST PKT with ERROR !!!!\n")); + } + break; + case PKT_TYPE_BCAST: + if( pkt_filter & NDIS_PACKET_TYPE_PROMISCUOUS || + pkt_filter & NDIS_PACKET_TYPE_BROADCAST ) + { + /* OK to report. */ + type = IP_STAT_BCAST_BYTES; + status = NDIS_STATUS_SUCCESS; + IPOIB_PRINT( TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, + ("Received BCAST PKT.\n")); + } + else + { + type = IP_STAT_DROPPED; + status = NDIS_STATUS_FAILURE; + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Received BCAST PKT with ERROR !!!!\n")); + } + break; + case PKT_TYPE_MCAST: + if( pkt_filter & NDIS_PACKET_TYPE_PROMISCUOUS || + pkt_filter & NDIS_PACKET_TYPE_ALL_MULTICAST || + pkt_filter & NDIS_PACKET_TYPE_MULTICAST ) + { + /* OK to report. */ + type = IP_STAT_MCAST_BYTES; + status = NDIS_STATUS_SUCCESS; + IPOIB_PRINT( TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, + ("Received UCAST PKT.\n")); + } + else + { + type = IP_STAT_DROPPED; + status = NDIS_STATUS_FAILURE; + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Received MCAST PKT with ERROR !!!!\n")); + } + break; + } + + if( status != NDIS_STATUS_SUCCESS ) + { + ipoib_inc_recv_stat( p_port->p_adapter, type, 0, 0 ); + /* Return the receive descriptor to the pool. */ + __buf_mgr_put_recv( p_port, p_desc, NULL ); + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_RECV, + ("Packet filter doesn't match receive. Dropping.\n") ); + /* + * Return IB_NOT_DONE since the packet has been completed, + * but has not consumed an array entry. + */ + return IB_NOT_DONE; + } + + cl_perf_start( GetNdisPkt ); + *pp_net_buffer_list = __buf_mgr_get_ndis_pkt( p_port, p_desc ); + cl_perf_stop( &p_port->p_adapter->perf, GetNdisPkt ); + if( !*pp_net_buffer_list ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("__buf_mgr_get_ndis_pkt failed\n") ); + return IB_INSUFFICIENT_RESOURCES; + } + + chksum.Value = 0; + +{ + PNET_BUFFER NetBuffer = NET_BUFFER_LIST_FIRST_NB(*pp_net_buffer_list); + NET_BUFFER_DATA_LENGTH(NetBuffer) = p_desc->len; +} + + switch( p_port->p_adapter->params.recv_chksum_offload ) + { + default: + CL_ASSERT( FALSE ); + case CSUM_DISABLED: + //NDIS60 + //NDIS_PER_PACKET_INFO_FROM_PACKET( *pp_packet, TcpIpChecksumPacketInfo ) = + //(void*)(uintn_t)chksum.Value; + NET_BUFFER_LIST_INFO(*pp_net_buffer_list, TcpIpChecksumNetBufferListInfo) = + (void*)(uintn_t)chksum.Value; + break; + case CSUM_ENABLED: + /* Get the checksums directly from packet information. */ + /* In this case, no one of cheksum's cat get false value */ + /* If hardware checksum failed or wasn't calculated, NDIS will recalculate it again */ + //NDIS60 + //NDIS_PER_PACKET_INFO_FROM_PACKET( *pp_packet, TcpIpChecksumPacketInfo ) = + NET_BUFFER_LIST_INFO(*pp_net_buffer_list, TcpIpChecksumNetBufferListInfo) = + (void*)(uintn_t)(p_desc->ndis_csum.Value); + break; + case CSUM_BYPASS: + /* Flag the checksums as having been calculated. */ + chksum.Receive.TcpChecksumSucceeded = TRUE; + chksum.Receive.UdpChecksumSucceeded = TRUE; + chksum.Receive.IpChecksumSucceeded = TRUE; + //NDIS60 + //NDIS_PER_PACKET_INFO_FROM_PACKET( *pp_packet, TcpIpChecksumPacketInfo ) = + NET_BUFFER_LIST_INFO(*pp_net_buffer_list, TcpIpChecksumNetBufferListInfo) = + (void*)(uintn_t)chksum.Value; + break; + } + ipoib_inc_recv_stat( p_port->p_adapter, type, p_desc->len, 1 ); + + IPOIB_EXIT( IPOIB_DBG_RECV ); + return IB_SUCCESS; +} + + +static uint32_t +__recv_mgr_build_pkt_array( + IN ipoib_port_t* const p_port, + IN int32_t shortage, + OUT cl_qlist_t* const p_done_list, + OUT int32_t* const p_discarded ) +{ + cl_list_item_t *p_item; + ipoib_recv_desc_t *p_desc; + uint32_t i = 0; + ib_api_status_t status; + PERF_DECLARE( PreparePkt ); + + IPOIB_ENTER( IPOIB_DBG_RECV ); + + *p_discarded = 0; + + /* Move any existing receives to the head to preserve ordering. */ + cl_qlist_insert_list_head( p_done_list, &p_port->recv_mgr.done_list ); + p_item = cl_qlist_remove_head( p_done_list ); + while( p_item != cl_qlist_end( p_done_list ) ) + { + p_desc = (ipoib_recv_desc_t*)p_item; + + cl_perf_start( PreparePkt ); + status = __recv_mgr_prepare_pkt( p_port, p_desc, + &p_port->recv_mgr.recv_pkt_array[i] ); + cl_perf_stop( &p_port->p_adapter->perf, PreparePkt ); + if( status == IB_SUCCESS ) + { + CL_ASSERT( p_port->recv_mgr.recv_pkt_array[i] ); + if( shortage-- > 0 ) + { + NET_BUFFER_LIST_STATUS(p_port->recv_mgr.recv_pkt_array[i])= NDIS_STATUS_RESOURCES; + } + else + { + NET_BUFFER_LIST_STATUS(p_port->recv_mgr.recv_pkt_array[i])= NDIS_STATUS_SUCCESS; + } + i++; + } + else if( status == IB_NOT_DONE ) + { + (*p_discarded)++; + } + else + { + IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_RECV, + ("__recv_mgr_prepare_pkt returned %s\n", + p_port->p_adapter->p_ifc->get_err_str( status )) ); + /* Put all completed receives on the port's done list. */ + cl_qlist_insert_tail( &p_port->recv_mgr.done_list, p_item ); + cl_qlist_insert_list_tail( &p_port->recv_mgr.done_list, p_done_list ); + break; + } + + p_item = cl_qlist_remove_head( p_done_list ); + } + + IPOIB_EXIT( IPOIB_DBG_RECV ); + return i; +} + + + + +/****************************************************************************** +* +* Send manager implementation. +* +******************************************************************************/ +static void +__send_mgr_construct( + IN ipoib_port_t* const p_port ) +{ + IPOIB_ENTER( IPOIB_DBG_SEND ); + p_port->send_mgr.depth = 0; + cl_qlist_init( &p_port->send_mgr.pending_list ); + IPOIB_EXIT( IPOIB_DBG_SEND ); +} + + +static void +__pending_list_destroy( + IN ipoib_port_t* const p_port ) +{ + cl_list_item_t *p_item; + NET_BUFFER_LIST **pp_net_buffer_list, *p_head; + + p_head = NULL; + cl_spinlock_acquire( &p_port->send_lock ); + /* Complete any pending packets. */ + pp_net_buffer_list = &p_head; + for( p_item = cl_qlist_remove_head( &p_port->send_mgr.pending_list ); + p_item != cl_qlist_end( &p_port->send_mgr.pending_list ); + p_item = cl_qlist_remove_head( &p_port->send_mgr.pending_list ) ) + { + *pp_net_buffer_list = IPOIB_PACKET_FROM_LIST_ITEM( p_item ); + NET_BUFFER_LIST_STATUS(*pp_net_buffer_list) = NDIS_STATUS_RESET_IN_PROGRESS; + pp_net_buffer_list = &(NET_BUFFER_LIST_NEXT_NBL(*pp_net_buffer_list)); + } + cl_spinlock_release( &p_port->send_lock ); + if(p_head) + NdisMSendNetBufferListsComplete( + p_port->p_adapter->h_adapter, + p_head, + 0); +} + +static void +__send_mgr_destroy( + IN ipoib_port_t* const p_port ) +{ + IPOIB_ENTER( IPOIB_DBG_SEND ); + __pending_list_destroy(p_port); + + IPOIB_EXIT( IPOIB_DBG_SEND ); +} + + +static NDIS_STATUS +__send_mgr_filter( + IN ipoib_port_t* const p_port, + IN const eth_hdr_t* const p_eth_hdr, + IN MDL* const p_mdl, + IN size_t buf_len, + IN SCATTER_GATHER_LIST *p_sgl, + IN OUT ipoib_send_desc_t* const p_desc ) +{ + NDIS_STATUS status; + + PERF_DECLARE( FilterIp ); + PERF_DECLARE( FilterArp ); + PERF_DECLARE( SendGen ); + + IPOIB_ENTER( IPOIB_DBG_SEND ); + + /* + * We already checked the ethernet header length, so we know it's safe + * to decrement the buf_len without underflowing. + */ + buf_len -= sizeof(eth_hdr_t); + + switch( p_eth_hdr->type ) + { + case ETH_PROT_TYPE_IP: + cl_perf_start( FilterIp ); + status = __send_mgr_filter_ip( + p_port, p_eth_hdr, p_mdl, buf_len, p_sgl, p_desc); + cl_perf_stop( &p_port->p_adapter->perf, FilterIp ); + break; + + case ETH_PROT_TYPE_ARP: + cl_perf_start( FilterArp ); + status = __send_mgr_filter_arp( + p_port, p_eth_hdr, p_mdl, buf_len, p_desc ); + p_desc->send_dir = SEND_UD_QP; + cl_perf_stop( &p_port->p_adapter->perf, FilterArp ); + break; + + default: + /* + * The IPoIB spec doesn't define how to send non IP or ARP packets. + * Just send the payload and hope for the best. + */ + + p_desc->send_dir = SEND_UD_QP; + cl_perf_start( SendGen ); + status = __send_gen( p_port, p_desc, p_sgl, 0 ); + cl_perf_stop( &p_port->p_adapter->perf, SendGen ); + break; + } + + IPOIB_EXIT( IPOIB_DBG_SEND ); + return status; +} + + +static NDIS_STATUS +__send_copy( + IN ipoib_port_t* const p_port, + IN ipoib_send_desc_t* const p_desc ) +{ + NET_BUFFER_LIST *p_net_buffer_list; + NET_BUFFER *p_netbuffer; + MDL *p_mdl; + UINT tot_len = 0; + + IPOIB_ENTER( IPOIB_DBG_SEND ); + + UNREFERENCED_PARAMETER(p_port); + UNREFERENCED_PARAMETER(p_desc); + + p_desc->p_buf = + (send_buf_t *) NdisAllocateFromNPagedLookasideList( &p_port->buf_mgr.send_buf_list ); + if( !p_desc->p_buf ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed to allocate buffer for packet copy.\n") ); + return NDIS_STATUS_RESOURCES; + } + + p_mdl = NdisAllocateMdl(p_port->p_adapter->h_adapter, + p_desc->p_buf, + p_port->p_adapter->params.xfer_block_size ); + if( !p_mdl ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed to allocate MDL\n") ); + return NDIS_STATUS_RESOURCES; + } + + p_net_buffer_list = NdisAllocateNetBufferAndNetBufferList( + p_port->buf_mgr.h_send_buf_pool, + 0, + 0, + p_mdl, + 0, + 0); + + if( !p_net_buffer_list ) + { + NdisFreeMdl(p_mdl); + IPOIB_PRINT_EXIT( TRACE_LEVEL_WARNING, IPOIB_DBG_SEND, + ("Failed to allocate NDIS_PACKET for copy.\n") ); + return NDIS_STATUS_RESOURCES; + } + + for (p_netbuffer = NET_BUFFER_LIST_FIRST_NB(p_net_buffer_list); + p_netbuffer != NULL; + p_netbuffer = NET_BUFFER_NEXT_NB(p_netbuffer)) + { + tot_len +=NET_BUFFER_DATA_LENGTH(p_netbuffer); + } + + /* Setup the work request. */ + p_desc->send_wr[0].local_ds[1].vaddr = cl_get_physaddr( + ((uint8_t*)p_desc->p_buf) + sizeof(eth_hdr_t) ); + p_desc->send_wr[0].local_ds[1].length = tot_len - sizeof(eth_hdr_t); + p_desc->send_wr[0].local_ds[1].lkey = p_port->ib_mgr.lkey; + p_desc->send_wr[0].wr.num_ds = 2; + + /* Free our temp packet now that the data is copied. */ + NdisFreeMdl(p_mdl); + NdisFreeNetBufferList(p_net_buffer_list); + + IPOIB_EXIT( IPOIB_DBG_SEND ); + return NDIS_STATUS_SUCCESS; +} + +static inline NDIS_STATUS +__send_mgr_get_eth_hdr( + IN PNET_BUFFER p_net_buffer, + OUT MDL** const pp_mdl, + OUT eth_hdr_t** const pp_eth_hdr, + OUT UINT* p_mdl_len) +{ + PUCHAR p_head = NULL; + IPOIB_ENTER( IPOIB_DBG_SEND ); + + *pp_mdl = NET_BUFFER_FIRST_MDL(p_net_buffer); + + NdisQueryMdl(*pp_mdl,&p_head,p_mdl_len,NormalPagePriority); + if( ! p_head ) + { + /* Failed to get first buffer. */ + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("NdisQueryMdl failed.\n") ); + return NDIS_STATUS_FAILURE; + } + + if( *p_mdl_len < sizeof(eth_hdr_t) ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("First buffer in packet smaller than eth_hdr_t: %d.\n", + *p_mdl_len) ); + return NDIS_STATUS_BUFFER_TOO_SHORT; + } + + *pp_eth_hdr = (eth_hdr_t*)(p_head + NET_BUFFER_CURRENT_MDL_OFFSET(p_net_buffer)); + + IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_SEND, + ("Ethernet header:\n" + "\tsrc MAC: %02X-%02X-%02X-%02X-%02X-%02X\n" + "\tdst MAC: %02X-%02X-%02X-%02X-%02X-%02X\n" + "\tprotocol type: %04X\n", + (*pp_eth_hdr)->src.addr[0], (*pp_eth_hdr)->src.addr[1], + (*pp_eth_hdr)->src.addr[2], (*pp_eth_hdr)->src.addr[3], + (*pp_eth_hdr)->src.addr[4], (*pp_eth_hdr)->src.addr[5], + (*pp_eth_hdr)->dst.addr[0], (*pp_eth_hdr)->dst.addr[1], + (*pp_eth_hdr)->dst.addr[2], (*pp_eth_hdr)->dst.addr[3], + (*pp_eth_hdr)->dst.addr[4], (*pp_eth_hdr)->dst.addr[5], + cl_ntoh16( (*pp_eth_hdr)->type )) ); + + return NDIS_STATUS_SUCCESS; +} + + +#if !IPOIB_USE_DMA +/* Send using the MDL's page information rather than the SGL. */ +static ib_api_status_t +__send_gen( + IN ipoib_port_t* const p_port, + IN ipoib_send_desc_t* const p_desc ) +{ + uint32_t i, j = 1; + ULONG offset; + MDL *p_mdl; + UINT num_pages, tot_len; + ULONG buf_len; + PPFN_NUMBER page_array; + boolean_t hdr_done = FALSE; + ib_api_status_t status; + PNET_BUFFER p_net_buf; + + IPOIB_ENTER( IPOIB_DBG_SEND ); + p_net_buf = NET_BUFFER_LIST_FIRST_NB(p_desc->p_netbuf_list); + NdisQueryBuffer( p_net_buf, &num_pages, NULL, &p_mdl, + &tot_len ); + + if( !p_mdl ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("No buffers associated with packet.\n") ); + return IB_ERROR; + } + + /* Remember that one of the DS entries is reserved for the IPoIB header. */ + if( num_pages >= MAX_SEND_SGE ) + { + IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_SEND, + ("Too many buffers to fit in WR ds_array. Copying data.\n") ); + status = __send_copy( p_port, p_desc ); + IPOIB_EXIT( IPOIB_DBG_SEND ); + return status; + } + + CL_ASSERT( tot_len > sizeof(eth_hdr_t) ); + CL_ASSERT( tot_len <= p_port->p_adapter->params.xfer_block_size ); + /* + * Assume that the ethernet header is always fully contained + * in the first page of the first MDL. This makes for much + * simpler code. + */ + offset = MmGetMdlByteOffset( p_mdl ) + sizeof(eth_hdr_t); + CL_ASSERT( offset <= PAGE_SIZE ); + + while( tot_len ) + { + buf_len = MmGetMdlByteCount( p_mdl ); + page_array = MmGetMdlPfnArray( p_mdl ); + CL_ASSERT( page_array ); + i = 0; + if( !hdr_done ) + { + CL_ASSERT( buf_len >= sizeof(eth_hdr_t) ); + /* Skip the ethernet header. */ + buf_len -= sizeof(eth_hdr_t); + CL_ASSERT( buf_len <= p_port->p_adapter->params.payload_mtu ); + if( buf_len ) + { + /* The ethernet header is a subset of this MDL. */ + CL_ASSERT( i == 0 ); + if( offset < PAGE_SIZE ) + { + p_desc->send_wr[0].local_ds[j].lkey = p_port->ib_mgr.lkey; + p_desc->send_wr[0].local_ds[j].vaddr = (page_array[i] << PAGE_SHIFT); + /* Add the byte offset since we're on the 1st page. */ + p_desc->send_wr[0].local_ds[j].vaddr += offset; + if( offset + buf_len > PAGE_SIZE ) + { + p_desc->send_wr[0].local_ds[j].length = PAGE_SIZE - offset; + buf_len -= p_desc->send_wr[0].local_ds[j].length; + } + else + { + p_desc->send_wr[0].local_ds[j].length = buf_len; + buf_len = 0; + } + /* This data segment is done. Move to the next. */ + j++; + } + /* This page is done. Move to the next. */ + i++; + } + /* Done handling the ethernet header. */ + hdr_done = TRUE; + } + + /* Finish this MDL */ + while( buf_len ) + { + p_desc->send_wr[0].local_ds[j].lkey = p_port->ib_mgr.lkey; + p_desc->send_wr[0].local_ds[j].vaddr = (page_array[i] << PAGE_SHIFT); + /* Add the first page's offset if we're on the first page. */ + if( i == 0 ) + p_desc->send_wr[0].local_ds[j].vaddr += MmGetMdlByteOffset( p_mdl ); + + if( i == 0 && (MmGetMdlByteOffset( p_mdl ) + buf_len) > PAGE_SIZE ) + { + /* Buffers spans pages. */ + p_desc->send_wr[0].local_ds[j].length = + PAGE_SIZE - MmGetMdlByteOffset( p_mdl ); + buf_len -= p_desc->send_wr[0].local_ds[j].length; + /* This page is done. Move to the next. */ + i++; + } + else + { + /* Last page of the buffer. */ + p_desc->send_wr[0].local_ds[j].length = buf_len; + buf_len = 0; + } + /* This data segment is done. Move to the next. */ + j++; + } + + tot_len -= MmGetMdlByteCount( p_mdl ); + if( !tot_len ) + break; + + NdisGetNextBuffer( p_mdl, &p_mdl ); + if( !p_mdl ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed to get next buffer.\n") ); + return IB_ERROR; + } + } + + /* Set the number of data segments. */ + p_desc->send_wr[0].wr.num_ds = j; + + IPOIB_EXIT( IPOIB_DBG_SEND ); + return IB_SUCCESS; +} + +#else + +#if 0 +void +ipoib_process_sg_list1( + IN PDEVICE_OBJECT pDO, + IN PVOID pIrp, + IN PSCATTER_GATHER_LIST p_sgl, + IN PVOID context + ) +{ + int i; + char temp[200]; + for (i = 0 ; i < 1;i++) + temp[i] = 5; +} +#endif + +void +ipoib_process_sg_list( + IN PDEVICE_OBJECT pDO, + IN PVOID pIrp, + IN PSCATTER_GATHER_LIST p_sgl, + IN PVOID context + ) +{ + NDIS_STATUS status; + ipoib_port_t *p_port; + MDL *p_mdl; + eth_hdr_t *p_eth_hdr; + UINT mdl_len; + static ipoib_send_desc_t *p_desc = NULL; + ib_send_wr_t *p_wr_failed; + NET_BUFFER_LIST *p_net_buffer_list; + NET_BUFFER *p_netbuf; + boolean_t from_queue; + ib_api_status_t ib_status; + ULONG complete_flags = 0; + + IPOIB_ENTER( IPOIB_DBG_SEND ); + + UNREFERENCED_PARAMETER(pDO); + UNREFERENCED_PARAMETER(pIrp); + + PERF_DECLARE( SendCopy ); + PERF_DECLARE( BuildSendDesc ); + PERF_DECLARE( GetEthHdr ); + PERF_DECLARE( QueuePacket ); + PERF_DECLARE( SendMgrQueue ); + PERF_DECLARE( PostSend ); + PERF_DECLARE( ProcessFailedSends ); + PERF_DECLARE( GetEndpt ); + + + p_netbuf = (NET_BUFFER*)context; + p_net_buffer_list = (NET_BUFFER_LIST*)IPOIB_NET_BUFFER_LIST_FROM_NETBUFFER(p_netbuf); + p_port = (ipoib_port_t*)IPOIB_PORT_FROM_PACKET(p_net_buffer_list); + NDIS_SET_SEND_COMPLETE_FLAG(complete_flags, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL); + + + cl_spinlock_acquire( &p_port->send_lock ); + if (p_desc == NULL) { + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_SEND, ("Allocating send_desc First Time\n") ); + p_desc = + (ipoib_send_desc_t *)ExAllocatePoolWithTag(NonPagedPool ,sizeof (ipoib_send_desc_t), 'XMXA'); + } + ASSERT(p_desc); + p_desc->p_netbuf_list = p_net_buffer_list; + p_desc->p_endpt = NULL; + p_desc->p_buf = NULL; + p_desc->num_wrs = 1; + + //IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_SEND, + // ("\n*******\nRECEIVED NB= %x with SG= %x\n********\n", p_netbuf, p_sgl) ); + /* Get the ethernet header so we can find the endpoint. */ + cl_perf_start( GetEthHdr ); + status = __send_mgr_get_eth_hdr( + p_netbuf, &p_mdl, &p_eth_hdr, &mdl_len ); + cl_perf_stop( &p_port->p_adapter->perf, GetEthHdr ); + + if( status != NDIS_STATUS_SUCCESS ) + { + cl_perf_start( ProcessFailedSends ); + /* fail net buffer list */ + __process_failed_send( p_port, p_desc, status, complete_flags); + cl_perf_stop( &p_port->p_adapter->perf, ProcessFailedSends ); + goto send_end; + } + //from_queue = (boolean_t)(IPOIB_FROM_QUEUE(p_netbuf) == (void*)1); + from_queue = (boolean_t)(IPOIB_FROM_QUEUE(p_netbuf) != NULL); + if (from_queue) + { + cl_perf_start( GetEndpt ); + status = __endpt_mgr_ref( p_port, p_eth_hdr->dst, &p_desc->p_endpt ); + cl_perf_stop( &p_port->p_adapter->perf, GetEndpt ); + if( status == NDIS_STATUS_PENDING ) + { + IPOIB_FROM_QUEUE(p_netbuf) = p_sgl; + cl_qlist_insert_head( &p_port->send_mgr.pending_list, + IPOIB_LIST_ITEM_FROM_PACKET( p_desc->p_netbuf_list ) ); + goto send_end; + } + else if( status != NDIS_STATUS_SUCCESS ) + { + ASSERT( status == NDIS_STATUS_NO_ROUTE_TO_DESTINATION ); + + if( ETH_IS_MULTICAST( p_eth_hdr->dst.addr ) ) + { + if( ipoib_port_join_mcast( p_port, p_eth_hdr->dst, + IB_MC_REC_STATE_FULL_MEMBER) == IB_SUCCESS ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_SEND, + ("Multicast Mac - trying to join.\n") ); + IPOIB_FROM_QUEUE(p_netbuf) = p_sgl; + cl_qlist_insert_head( &p_port->send_mgr.pending_list, + IPOIB_LIST_ITEM_FROM_PACKET( p_desc->p_netbuf_list ) ); + goto send_end; + } + } + /* + * Complete the send as if we sent it - WHQL tests don't like the + * sends to fail. + */ + cl_perf_start( ProcessFailedSends ); + __process_failed_send( p_port, p_desc, NDIS_STATUS_SUCCESS,complete_flags ); + cl_perf_stop( &p_port->p_adapter->perf, ProcessFailedSends ); + goto send_end; + } + } + else + { + cl_perf_start( SendMgrQueue ); + if ( ETH_IS_MULTICAST( p_eth_hdr->dst.addr ) && + p_eth_hdr->type == ETH_PROT_TYPE_IP && + !ETH_IS_BROADCAST( p_eth_hdr->dst.addr ) ) + { + ip_hdr_t *p_ip_hdr; + uint8_t *p_tmp; + MDL *p_ip_hdr_mdl; + UINT ip_hdr_mdl_len; + + if(mdl_len >= sizeof(ip_hdr_t) + sizeof(eth_hdr_t)) + { + p_ip_hdr = (ip_hdr_t*)(p_eth_hdr + 1); + } + else + { + NdisGetNextMdl(p_mdl,&p_ip_hdr_mdl); + // Extract the ip hdr + if( !p_ip_hdr_mdl ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed to get IP header buffer.\n") ); + goto mc_end; + } + NdisQueryMdl(p_ip_hdr_mdl,&p_tmp,&ip_hdr_mdl_len,NormalPagePriority); + if( !p_tmp ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed to get IP header.\n") ); + goto mc_end; + } + if( ip_hdr_mdl_len < sizeof(ip_hdr_t) ) + { + /* This buffer is done for. Get the next buffer. */ + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Buffer too small for IP packet.\n") ); + goto mc_end; + } + p_ip_hdr = (ip_hdr_t*)(p_tmp + NET_BUFFER_CURRENT_MDL_OFFSET(p_netbuf)); + p_eth_hdr->dst.addr[1] = ((unsigned char*)&p_ip_hdr->dst_ip)[0] & 0x0f; + p_eth_hdr->dst.addr[3] = ((unsigned char*)&p_ip_hdr->dst_ip)[1]; + } + } +mc_end: + status = __send_mgr_queue( p_port, p_eth_hdr, &p_desc->p_endpt ); + cl_perf_stop( &p_port->p_adapter->perf, SendMgrQueue ); + if( status == NDIS_STATUS_PENDING ) + { + /* Queue net buffer list. */ + cl_perf_start( QueuePacket ); + NET_BUFFER_LIST_NEXT_NBL(p_net_buffer_list) = NULL; + IPOIB_FROM_QUEUE(p_netbuf) = p_sgl; + cl_qlist_insert_tail( &p_port->send_mgr.pending_list, + IPOIB_LIST_ITEM_FROM_PACKET(p_net_buffer_list) ); + cl_perf_stop( &p_port->p_adapter->perf, QueuePacket ); + goto send_end; + } + if( status != NDIS_STATUS_SUCCESS ) + { + ASSERT( status == NDIS_STATUS_NO_ROUTE_TO_DESTINATION ); + /* + * Complete the send as if we sent it - WHQL tests don't like the + * sends to fail. + */ + cl_perf_start( ProcessFailedSends ); + __process_failed_send( p_port, p_desc, NDIS_STATUS_SUCCESS, complete_flags ); + cl_perf_stop( &p_port->p_adapter->perf, ProcessFailedSends ); + goto send_end; + } + } + cl_perf_start( BuildSendDesc ); + status = __build_send_desc( p_port, p_eth_hdr, p_mdl, mdl_len, p_sgl, p_desc ); + cl_perf_stop( &p_port->p_adapter->perf, BuildSendDesc ); + + if( status != NDIS_STATUS_SUCCESS ) + { + cl_perf_start( ProcessFailedSends ); + __process_failed_send( p_port, p_desc, status, complete_flags ); + cl_perf_stop( &p_port->p_adapter->perf, ProcessFailedSends ); + goto send_end; + } + + /* Post the WR. */ + cl_perf_start( PostSend ); + cl_msg_out("sending packet with wr-id =0x%x\n",&p_desc->send_wr[0].wr.wr_id ); + ib_status = p_port->p_adapter->p_ifc->post_send( p_port->ib_mgr.h_qp, &p_desc->send_wr[0].wr, &p_wr_failed ); + cl_perf_stop( &p_port->p_adapter->perf, PostSend ); + if( ib_status != IB_SUCCESS ) + { + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ib_post_send returned %s\n", + p_port->p_adapter->p_ifc->get_err_str( ib_status )) ); + cl_perf_start( ProcessFailedSends ); + __process_failed_send( p_port, p_desc, NDIS_STATUS_FAILURE, complete_flags ); + cl_perf_stop( &p_port->p_adapter->perf, ProcessFailedSends ); + /* Flag the adapter as hung since posting is busted. */ + p_port->p_adapter->hung = TRUE; + } + cl_atomic_inc( &p_port->send_mgr.depth ); + +send_end: + if (status != NDIS_STATUS_SUCCESS) { +// IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_SEND, + // ("Free S/G List: 0x%x.\n", (UINT) (PVOID) p_sgl) ); + /*NdisMFreeNetBufferSGList( + p_port->p_adapter->NdisMiniportDmaHandle, + p_sgl, + p_netbuf);*/ + + } + + + cl_spinlock_release( &p_port->send_lock ); + IPOIB_EXIT( IPOIB_DBG_SEND ); +} + +static NDIS_STATUS +__send_gen( + IN ipoib_port_t* const p_port, + IN ipoib_send_desc_t* const p_desc, + IN SCATTER_GATHER_LIST *p_sgl, + IN INT lso_data_index + ) +{ + NDIS_STATUS status; + uint32_t i, j = 1; + uint32_t offset = sizeof(eth_hdr_t); + PERF_DECLARE( SendCopy ); + + IPOIB_ENTER( IPOIB_DBG_SEND ); + + if( !p_sgl ) + { + ASSERT( p_sgl ); + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed to get SGL from packet.\n") ); + return NDIS_STATUS_FAILURE; + } + + /* Remember that one of the DS entries is reserved for the IPoIB header. */ + if( ( p_sgl->NumberOfElements >= MAX_SEND_SGE || + p_sgl->Elements[0].Length < sizeof(eth_hdr_t)) ) + { + + IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_SEND, + ("Too many buffers %d to fit in WR ds_array[%d] \ + Or buffer[0] length %d < Eth header. Copying data.\n", + p_sgl->NumberOfElements, MAX_SEND_SGE, p_sgl->Elements[0].Length ) ); + status = NDIS_STATUS_RESOURCES; + if( !p_port->p_adapter->params.cm_enabled ) + { + cl_perf_start( SendCopy ); + status = __send_copy( p_port, p_desc ); + cl_perf_stop( &p_port->p_adapter->perf, SendCopy ); + } + IPOIB_EXIT( IPOIB_DBG_SEND ); + return status; + } + + /* + * Skip the ethernet header. It is either the first element, + * or part of it. + */ + i = 0; + if( lso_data_index ) + { /* we have an LSO packet */ + i = lso_data_index; + j = 0; + } + else while( offset ) + { + if( p_sgl->Elements[i].Length <= offset ) + { + offset -= p_sgl->Elements[i++].Length; + } + else + { + p_desc->send_wr[0].local_ds[j].vaddr = + p_sgl->Elements[i].Address.QuadPart + offset; + p_desc->send_wr[0].local_ds[j].length = + p_sgl->Elements[i].Length - offset; + p_desc->send_wr[0].local_ds[j].lkey = p_port->ib_mgr.lkey; + i++; + j++; + break; + } + } + /* Now fill in the rest of the local data segments. */ + while( i < p_sgl->NumberOfElements ) + { + p_desc->send_wr[0].local_ds[j].vaddr = p_sgl->Elements[i].Address.QuadPart; + p_desc->send_wr[0].local_ds[j].length = p_sgl->Elements[i].Length; + p_desc->send_wr[0].local_ds[j].lkey = p_port->ib_mgr.lkey; + i++; + j++; + } + + /* Set the number of data segments. */ + p_desc->send_wr[0].wr.num_ds = j; + + IPOIB_EXIT( IPOIB_DBG_SEND ); + return NDIS_STATUS_SUCCESS; +} +#endif + + +static NDIS_STATUS +__send_mgr_filter_ip( + IN ipoib_port_t* const p_port, + IN const eth_hdr_t* const p_eth_hdr, + IN MDL* p_mdl, + IN size_t buf_len, + IN SCATTER_GATHER_LIST *p_sgl, + IN OUT ipoib_send_desc_t* const p_desc ) +{ + NDIS_STATUS status; + ip_hdr_t *p_ip_hdr; + uint32_t ip_packet_len; + size_t iph_size_in_bytes; + size_t iph_options_size; + + PERF_DECLARE( QueryIp ); + PERF_DECLARE( SendTcp ); + PERF_DECLARE( FilterUdp ); + + IPOIB_ENTER( IPOIB_DBG_SEND ); + + if( !buf_len ) + { + cl_perf_start( QueryIp ); + NdisGetNextMdl ( p_mdl, &p_mdl ); + if( !p_mdl ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed to get IP header buffer.\n") ); + return NDIS_STATUS_FAILURE; + } + + NdisQueryMdl(p_mdl, &p_ip_hdr, &buf_len, NormalPagePriority); + if( !p_ip_hdr ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed to query IP header buffer.\n") ); + return NDIS_STATUS_FAILURE; + } + cl_perf_stop( &p_port->p_adapter->perf, QueryIp ); + } + else + { + p_ip_hdr = (ip_hdr_t*)(p_eth_hdr + 1); + } + if( buf_len < sizeof(ip_hdr_t) ) + { + /* This buffer is done for. Get the next buffer. */ + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Buffer too small for IP packet.\n") ); + return NDIS_STATUS_BUFFER_TOO_SHORT; + } + + switch( p_ip_hdr->prot ) + { + case IP_PROT_UDP: + + cl_perf_start( FilterUdp ); + status = __send_mgr_filter_udp( + p_port, p_ip_hdr, p_mdl, (buf_len - sizeof(ip_hdr_t)), p_sgl, p_desc ); + cl_perf_stop( &p_port->p_adapter->perf, FilterUdp ); + if( status == NDIS_STATUS_PENDING ) + { /* not DHCP packet, keep going */ + if( ETH_IS_MULTICAST( p_eth_hdr->dst.addr ) ) + p_desc->send_dir = SEND_UD_QP; + else + p_desc->send_dir = SEND_RC_QP; + break; + } + return status; + + case IP_PROT_TCP: + p_desc->send_dir = SEND_RC_QP; + break; + case IP_PROT_IGMP: + /* + In igmp packet I saw that iph arrive in 2 NDIS_BUFFERs: + 1. iph + 2. ip options + So to get the IGMP packet we need to skip the ip options NDIS_BUFFER + */ + iph_size_in_bytes = (p_ip_hdr->ver_hl & 0xf) * 4; + iph_options_size = iph_size_in_bytes - buf_len; + buf_len -= sizeof(ip_hdr_t);//without ipheader + + /* + Could be a case that arrived igmp packet not from type IGMPv2 , + but IGMPv1 or IGMPv3. + We anyway pass it to __send_mgr_filter_igmp_v2(). + */ + status = + __send_mgr_filter_igmp_v2( p_port, p_ip_hdr, iph_options_size, p_mdl, buf_len ); + if( status != NDIS_STATUS_SUCCESS ) + return status; + + case IP_PROT_ICMP: + p_desc->send_dir = SEND_UD_QP; + default: + break; + } + + if( !p_port->p_adapter->params.cm_enabled ) + { + p_desc->send_dir = SEND_UD_QP; + goto send_gen; + } + else if( endpt_cm_get_state( p_desc->p_endpt ) != IPOIB_CM_CONNECTED ) + { + p_desc->send_dir = SEND_UD_QP; + } + if( p_desc->send_dir == SEND_UD_QP ) + { + ip_packet_len = cl_ntoh16( p_ip_hdr->length ); + if( ip_packet_len > p_port->p_adapter->params.payload_mtu ) + { + //TODO: NDIS60 + #if 0 + status = __send_fragments( p_port, p_desc, (eth_hdr_t* const)p_eth_hdr, + (ip_hdr_t* const)p_ip_hdr, (uint32_t)buf_len, p_mdl ); + return status; + #endif + ASSERT(FALSE); + } + } + +send_gen: + cl_perf_start( SendTcp ); + status = __send_gen( p_port, p_desc, p_sgl, 0 ); + cl_perf_stop( &p_port->p_adapter->perf, SendTcp ); + + IPOIB_EXIT( IPOIB_DBG_SEND ); + return status; +} + +static NDIS_STATUS +__send_mgr_filter_igmp_v2( + IN ipoib_port_t* const p_port, + IN const ip_hdr_t* const p_ip_hdr, + IN size_t iph_options_size, + IN MDL* p_mdl, + IN size_t buf_len ) +{ + igmp_v2_hdr_t *p_igmp_v2_hdr = NULL; + NDIS_STATUS endpt_status; + ipoib_endpt_t* p_endpt = NULL; + mac_addr_t fake_mcast_mac; + + IPOIB_ENTER( IPOIB_DBG_SEND ); + + IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_MCAST, + ("buf_len = %d,iph_options_size = %d\n",(int)buf_len,(int)iph_options_size ) ); + + if( !buf_len ) + { + // To get the IGMP packet we need to skip the ip options NDIS_BUFFER (if exists) + while ( iph_options_size ) + { + NdisGetNextMdl( p_mdl, &p_mdl ); + if( !p_mdl ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed to get IGMPv2 header buffer.\n") ); + return NDIS_STATUS_FAILURE; + } + NdisQueryMdl( p_mdl, &p_igmp_v2_hdr, &buf_len, NormalPagePriority ); + if( !p_igmp_v2_hdr ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed to query IGMPv2 header buffer.\n") ); + return NDIS_STATUS_FAILURE; + } + iph_options_size-=buf_len; + } + + NdisGetNextMdl( p_mdl, &p_mdl ); + if( !p_mdl ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed to get IGMPv2 header buffer.\n") ); + return NDIS_STATUS_FAILURE; + } + NdisQueryMdl( p_mdl, &p_igmp_v2_hdr, &buf_len, NormalPagePriority ); + if( !p_igmp_v2_hdr ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed to query IGMPv2 header buffer.\n") ); + return NDIS_STATUS_FAILURE; + } + } + else + { + /* assuming ip header and options are in the same packet */ + p_igmp_v2_hdr = (igmp_v2_hdr_t *) GetIpPayloadPtr(p_ip_hdr); + } + /* Get the IGMP header length. */ + if( buf_len < sizeof(igmp_v2_hdr_t) ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Buffer not large enough for IGMPv2 packet.\n") ); + return NDIS_STATUS_BUFFER_TOO_SHORT; + } + + // build fake mac from igmp packet group address + fake_mcast_mac.addr[0] = 1; + fake_mcast_mac.addr[1] = ((unsigned char*)&p_igmp_v2_hdr->group_address)[0] & 0x0f; + fake_mcast_mac.addr[2] = 0x5E; + fake_mcast_mac.addr[3] = ((unsigned char*)&p_igmp_v2_hdr->group_address)[1]; + fake_mcast_mac.addr[4] = ((unsigned char*)&p_igmp_v2_hdr->group_address)[2]; + fake_mcast_mac.addr[5] = ((unsigned char*)&p_igmp_v2_hdr->group_address)[3]; + + switch ( p_igmp_v2_hdr->type ) + { + case IGMP_V2_MEMBERSHIP_REPORT: + /* + This mean that some body open listener on this group + Change type of mcast endpt to SEND_RECV endpt. So mcast garbage collector + will not delete this mcast endpt. + */ + IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_MCAST, + ("Catched IGMP_V2_MEMBERSHIP_REPORT message\n") ); + endpt_status = __endpt_mgr_ref( p_port, fake_mcast_mac, &p_endpt ); + if ( p_endpt ) + { + cl_obj_lock( &p_port->obj ); + p_endpt->is_mcast_listener = TRUE; + cl_obj_unlock( &p_port->obj ); + ipoib_endpt_deref( p_endpt ); + } + break; + + case IGMP_V2_LEAVE_GROUP: + /* + This mean that somebody CLOSE listener on this group . + Change type of mcast endpt to SEND_ONLY endpt. So mcast + garbage collector will delete this mcast endpt next time. + */ + IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_MCAST, + ("Catched IGMP_V2_LEAVE_GROUP message\n") ); + endpt_status = __endpt_mgr_ref( p_port, fake_mcast_mac, &p_endpt ); + if ( p_endpt ) + { + cl_obj_lock( &p_port->obj ); + p_endpt->is_mcast_listener = FALSE; + p_endpt->is_in_use = FALSE; + cl_obj_unlock( &p_port->obj ); + ipoib_endpt_deref( p_endpt ); + } + + __port_do_mcast_garbage(p_port); + + break; + + default: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_MCAST, + ("Send Unknown IGMP message: 0x%x \n", p_igmp_v2_hdr->type ) ); + break; + } + + IPOIB_EXIT( IPOIB_DBG_SEND ); + return NDIS_STATUS_SUCCESS; +} + +static NDIS_STATUS +__send_mgr_filter_udp( + IN ipoib_port_t* const p_port, + IN const ip_hdr_t* const p_ip_hdr, + IN MDL* p_mdl, + IN size_t buf_len, + IN SCATTER_GATHER_LIST *p_sgl, + IN OUT ipoib_send_desc_t* const p_desc ) +{ + NDIS_STATUS status; + udp_hdr_t *p_udp_hdr; + PERF_DECLARE( QueryUdp ); + PERF_DECLARE( SendUdp ); + PERF_DECLARE( FilterDhcp ); + //TODO NDIS60 remove this param + UNUSED_PARAM(p_sgl); + IPOIB_ENTER( IPOIB_DBG_SEND ); + + if( !buf_len ) + { + cl_perf_start( QueryUdp ); + NdisGetNextMdl( p_mdl, &p_mdl ); + if( !p_mdl ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed to get UDP header buffer.\n") ); + return NDIS_STATUS_FAILURE; + } + NdisQueryMdl( p_mdl, &p_udp_hdr, &buf_len, NormalPagePriority ); + if( !p_udp_hdr ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed to query UDP header buffer.\n") ); + return NDIS_STATUS_FAILURE; + } + cl_perf_stop( &p_port->p_adapter->perf, QueryUdp ); + } + else + { + p_udp_hdr = (udp_hdr_t*)GetIpPayloadPtr(p_ip_hdr); + } + /* Get the UDP header and check the destination port numbers. */ + + if (p_ip_hdr->offset > 0) { + /* This is a fragmented part of UDP packet + * Only first packet will contain UDP header in such case + * So, return if offset > 0 + */ + return NDIS_STATUS_PENDING; + } + + if( buf_len < sizeof(udp_hdr_t) ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Buffer not large enough for UDP packet.\n") ); + return NDIS_STATUS_BUFFER_TOO_SHORT; + } + + if( (p_udp_hdr->src_port != DHCP_PORT_CLIENT || + p_udp_hdr->dst_port != DHCP_PORT_SERVER) && + (p_udp_hdr->src_port != DHCP_PORT_SERVER || + p_udp_hdr->dst_port != DHCP_PORT_CLIENT) ) + { + /* Not a DHCP packet. */ + return NDIS_STATUS_PENDING; + } + + buf_len -= sizeof(udp_hdr_t); + + /* Allocate our scratch buffer. */ + p_desc->p_buf = (send_buf_t*) + ExAllocateFromNPagedLookasideList( &p_port->buf_mgr.send_buf_list ); + if( !p_desc->p_buf ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed to query DHCP packet buffer.\n") ); + return NDIS_STATUS_RESOURCES; + } + /* Copy the IP and UDP headers. */ + cl_memcpy( &p_desc->p_buf->ip.hdr, p_ip_hdr , sizeof(ip_hdr_t) ); + cl_memcpy( + &p_desc->p_buf->ip.prot.udp.hdr, p_udp_hdr, sizeof(udp_hdr_t) ); + + cl_perf_start( FilterDhcp ); + status = __send_mgr_filter_dhcp( + p_port, p_udp_hdr, p_mdl, buf_len, p_desc ); + cl_perf_stop( &p_port->p_adapter->perf, FilterDhcp ); + + IPOIB_EXIT( IPOIB_DBG_SEND ); + return status; +} + +unsigned short ipchksum(unsigned short *ip, int len) +{ + unsigned long sum = 0; + + len >>= 1; + while (len--) { + sum += *(ip++); + if (sum > 0xFFFF) + sum -= 0xFFFF; + } + return (unsigned short)((~sum) & 0x0000FFFF); +} + +static NDIS_STATUS +__send_mgr_filter_dhcp( + IN ipoib_port_t* const p_port, + IN const udp_hdr_t* const p_udp_hdr, + IN NDIS_BUFFER* p_mdl, + IN size_t buf_len, + IN OUT ipoib_send_desc_t* const p_desc ) +{ + dhcp_pkt_t *p_dhcp; + dhcp_pkt_t *p_ib_dhcp; + uint8_t *p_option, *p_cid = NULL; + uint8_t msg = 0; + size_t len; + ib_gid_t gid; + + IPOIB_ENTER( IPOIB_DBG_SEND ); + + if( !buf_len ) + { + NdisGetNextMdl( p_mdl, &p_mdl ); + if( !p_mdl ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed to get DHCP buffer.\n") ); + return NDIS_STATUS_FAILURE; + } + NdisQueryMdl( p_mdl, &p_dhcp, &buf_len, NormalPagePriority ); + if( !p_dhcp ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed to query DHCP buffer.\n") ); + return NDIS_STATUS_FAILURE; + } + } + else + { + p_dhcp = (dhcp_pkt_t*)(p_udp_hdr + 1); + } + + if( buf_len < DHCP_MIN_SIZE ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Buffer not large enough for DHCP packet.\n") ); + return NDIS_STATUS_BUFFER_TOO_SHORT; + } + + p_ib_dhcp = &p_desc->p_buf->ip.prot.udp.dhcp; + cl_memcpy( p_ib_dhcp, p_dhcp, buf_len ); + + /* Now scan through the options looking for the client identifier. */ + p_option = &p_ib_dhcp->options[4]; + while( *p_option != DHCP_OPT_END && p_option < &p_ib_dhcp->options[312] ) + { + switch( *p_option ) + { + case DHCP_OPT_PAD: + p_option++; + break; + + case DHCP_OPT_MSG: + msg = p_option[2]; + p_option += 3; + break; + + case DHCP_OPT_CLIENT_ID: + p_cid = p_option; + /* Fall through. */ + + default: + /* + * All other options have a length byte following the option code. + * Offset by the length to get to the next option. + */ + p_option += (p_option[1] + 2); + } + } + + switch( msg ) + { + /* Client messages */ + case DHCPDISCOVER: + case DHCPREQUEST: + p_ib_dhcp->flags |= DHCP_FLAGS_BROADCAST; + /* Fall through */ + case DHCPDECLINE: + case DHCPRELEASE: + case DHCPINFORM: + /* Fix up the client identifier option */ + if( p_cid ) + { + /* do we need to replace it ? len eq ETH MAC sz 'and' MAC is mine */ + if( p_cid[1] == HW_ADDR_LEN+1 && !cl_memcmp( &p_cid[3], + &p_port->p_adapter->params.conf_mac.addr, HW_ADDR_LEN ) ) + { + /* Make sure there's room to extend it. 23 is the size of + * the CID option for IPoIB. + */ + if( buf_len + 23 - p_cid[1] > sizeof(dhcp_pkt_t) ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Can't convert CID to IPoIB format.\n") ); + return NDIS_STATUS_RESOURCES; + } + /* Move the existing options down, and add a new CID option */ + len = p_option - ( p_cid + p_cid[1] + 2 ); + p_option = p_cid + p_cid[1] + 2; + RtlMoveMemory( p_cid, p_option, len ); + + p_cid += len; + p_cid[0] = DHCP_OPT_CLIENT_ID; + p_cid[1] = 21; + p_cid[2] = DHCP_HW_TYPE_IB; + } + else + { + p_cid[2] = DHCP_HW_TYPE_IB; + } + } + else + { + /* + * Make sure there's room to extend it. 23 is the size of + * the CID option for IPoIB. + */ + if( buf_len + 23 > sizeof(dhcp_pkt_t) ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Can't convert CID to IPoIB format.\n") ); + return NDIS_STATUS_RESOURCES; + } + + p_cid = p_option; + p_option = p_cid + 23; + p_option[0] = DHCP_OPT_END; + p_cid[0] = DHCP_OPT_CLIENT_ID; + p_cid[1] = 21; + p_cid[2] = DHCP_HW_TYPE_IB; + } + + CL_ASSERT( p_cid[1] == 21 ); + p_cid[23]= DHCP_OPT_END; + ib_gid_set_default( &gid, p_port->p_adapter->guids.port_guid.guid ); + cl_memcpy( &p_cid[7], &gid, sizeof(ib_gid_t) ); + cl_memcpy( &p_cid[3], &p_port->ib_mgr.qpn, sizeof(p_port->ib_mgr.qpn) ); + p_ib_dhcp->htype = DHCP_HW_TYPE_IB; + + /* update lengths to include any change we made */ + p_desc->p_buf->ip.hdr.length = cl_ntoh16( sizeof(ip_hdr_t) + sizeof(udp_hdr_t) + sizeof(dhcp_pkt_t) ); + p_desc->p_buf->ip.prot.udp.hdr.length = cl_ntoh16( sizeof(udp_hdr_t) + sizeof(dhcp_pkt_t) ); + + /* update crc in ip header */ + //if( !p_port->p_adapter->params.send_chksum_offload ) + //{ //TODO ? + p_desc->p_buf->ip.hdr.chksum = 0; + p_desc->p_buf->ip.hdr.chksum = ipchksum((unsigned short*) &p_desc->p_buf->ip.hdr, sizeof(ip_hdr_t)); + //} TODO ?? + break; + + /* Server messages. */ + case DHCPOFFER: + case DHCPACK: + case DHCPNAK: + /* don't touch server messages */ + break; + + default: + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Invalide message type.\n") ); + return NDIS_STATUS_INVALID_DATA; + } + /* no chksum for udp */ + p_desc->p_buf->ip.prot.udp.hdr.chksum = 0; + p_desc->send_wr[0].local_ds[1].vaddr = cl_get_physaddr( p_desc->p_buf ); + p_desc->send_wr[0].local_ds[1].length = sizeof(ip_hdr_t) + sizeof(udp_hdr_t) + sizeof(dhcp_pkt_t); + p_desc->send_wr[0].local_ds[1].lkey = p_port->ib_mgr.lkey; + p_desc->send_wr[0].wr.num_ds = 2; + p_desc->send_dir = SEND_UD_QP; + IPOIB_EXIT( IPOIB_DBG_SEND ); + return NDIS_STATUS_SUCCESS; +} + + +static NDIS_STATUS +__send_mgr_filter_arp( + IN ipoib_port_t* const p_port, + IN const eth_hdr_t* const p_eth_hdr, + IN MDL* p_mdl, + IN size_t buf_len, + IN OUT ipoib_send_desc_t* const p_desc ) +{ + arp_pkt_t *p_arp; + ipoib_arp_pkt_t *p_ib_arp; + NDIS_STATUS status; + mac_addr_t null_hw = {0}; + + IPOIB_ENTER( IPOIB_DBG_SEND ); + + if( !buf_len ) + { + NdisGetNextMdl( p_mdl, &p_mdl ); + if( !p_mdl ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed to get ARP buffer.\n") ); + return NDIS_STATUS_FAILURE; + } + NdisQueryMdl( p_mdl, &p_arp, &buf_len, NormalPagePriority ); + if( !p_arp ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed to get query ARP buffer.\n") ); + return NDIS_STATUS_FAILURE; + } + } + else + { + p_arp = (arp_pkt_t*)(p_eth_hdr + 1); + } + + /* Single buffer ARP packet. */ + if( buf_len < sizeof(arp_pkt_t) ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Buffer too short for ARP.\n") ); + return NDIS_STATUS_BUFFER_TOO_SHORT; + } + + if( p_arp->prot_type != ETH_PROT_TYPE_IP ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Unsupported protocol type.\n") ); + return NDIS_STATUS_INVALID_DATA; + } + + /* Allocate our scratch buffer. */ + p_desc->p_buf = (send_buf_t*) + NdisAllocateFromNPagedLookasideList( &p_port->buf_mgr.send_buf_list ); + if( !p_desc->p_buf ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed to query ARP packet buffer.\n") ); + return NDIS_STATUS_RESOURCES; + } + p_ib_arp = (ipoib_arp_pkt_t*)p_desc->p_buf; + + /* Convert the ARP payload. */ + p_ib_arp->hw_type = ARP_HW_TYPE_IB; + p_ib_arp->prot_type = p_arp->prot_type; + p_ib_arp->hw_size = sizeof(ipoib_hw_addr_t); + p_ib_arp->prot_size = p_arp->prot_size; + p_ib_arp->op = p_arp->op; + + ipoib_addr_set_qpn( &p_ib_arp->src_hw, p_port->ib_mgr.qpn ); +#if 0 + + if( p_port->p_adapter->params.cm_enabled ) + { + ipoib_addr_set_flags( &p_ib_arp->src_hw, IPOIB_CM_FLAG_RC ); + } +#endif + + ib_gid_set_default( &p_ib_arp->src_hw.gid, + p_port->p_adapter->guids.port_guid.guid ); + p_ib_arp->src_ip = p_arp->src_ip; + if( cl_memcmp( &p_arp->dst_hw, &null_hw, sizeof(mac_addr_t) ) ) + { + /* Get the endpoint referenced by the dst_hw address. */ + net32_t qpn = 0; + status = __endpt_mgr_get_gid_qpn( p_port, p_arp->dst_hw, + &p_ib_arp->dst_hw.gid, &qpn ); + if( status != NDIS_STATUS_SUCCESS ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed lookup of destination HW address\n") ); + return status; + } + ipoib_addr_set_qpn( &p_ib_arp->dst_hw, qpn ); +#if 0 + if( p_arp->op == ARP_OP_REP && + p_port->p_adapter->params.cm_enabled && + p_desc->p_endpt->cm_flag == IPOIB_CM_FLAG_RC ) + { + cm_state_t cm_state; + cm_state = + ( cm_state_t )InterlockedCompareExchange( (volatile LONG *)&p_desc->p_endpt->conn.state, + IPOIB_CM_CONNECT, IPOIB_CM_DISCONNECTED ); + switch( cm_state ) + { + case IPOIB_CM_DISCONNECTED: + IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, + ("ARP REPLY pending Endpt[%p] QPN %#x MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + p_desc->p_endpt, + cl_ntoh32( ipoib_addr_get_qpn( &p_ib_arp->dst_hw )), + p_desc->p_endpt->mac.addr[0], p_desc->p_endpt->mac.addr[1], + p_desc->p_endpt->mac.addr[2], p_desc->p_endpt->mac.addr[3], + p_desc->p_endpt->mac.addr[4], p_desc->p_endpt->mac.addr[5] ) ); + ipoib_addr_set_sid( &p_desc->p_endpt->conn.service_id, + ipoib_addr_get_qpn( &p_ib_arp->dst_hw ) ); + + NdisFreeToNPagedLookasideList( + &p_port->buf_mgr.send_buf_list, p_desc->p_buf ); + cl_qlist_insert_tail( &p_port->send_mgr.pending_list, + IPOIB_LIST_ITEM_FROM_PACKET( p_desc->p_buf ) ); + NdisInterlockedInsertTailList( &p_port->endpt_mgr.pending_conns, + &p_desc->p_endpt->list_item, + &p_port->endpt_mgr.conn_lock ); + cl_event_signal( &p_port->endpt_mgr.event ); + return NDIS_STATUS_PENDING; + + case IPOIB_CM_CONNECT: + /* queue ARP REP packet until connected */ + NdisFreeToNPagedLookasideList( + &p_port->buf_mgr.send_buf_list, p_desc->p_buf ); + cl_qlist_insert_tail( &p_port->send_mgr.pending_list, + IPOIB_LIST_ITEM_FROM_PACKET( p_desc->p_pkt ) ); + return NDIS_STATUS_PENDING; + default: + break; + } + } +#endif + } + else + { + cl_memclr( &p_ib_arp->dst_hw, sizeof(ipoib_hw_addr_t) ); + } + +#if 0 //DBG + if( p_port->p_adapter->params.cm_enabled ) + { + IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, + (" ARP %s SEND to ENDPT[%p] State: %d flag: %#x, QPN: %#x MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + ( p_ib_arp->op == ARP_OP_REP ? "REP": "REQ"), p_desc->p_endpt, + endpt_cm_get_state( p_desc->p_endpt ), + p_desc->p_endpt->cm_flag, + cl_ntoh32( ipoib_addr_get_qpn( &p_ib_arp->dst_hw )), + p_desc->p_endpt->mac.addr[0], p_desc->p_endpt->mac.addr[1], + p_desc->p_endpt->mac.addr[2], p_desc->p_endpt->mac.addr[3], + p_desc->p_endpt->mac.addr[4], p_desc->p_endpt->mac.addr[5] )); + } +#endif + + p_ib_arp->dst_ip = p_arp->dst_ip; + + p_desc->send_wr[0].local_ds[1].vaddr = cl_get_physaddr( p_ib_arp ); + p_desc->send_wr[0].local_ds[1].length = sizeof(ipoib_arp_pkt_t); + p_desc->send_wr[0].local_ds[1].lkey = p_port->ib_mgr.lkey; + p_desc->send_wr[0].wr.num_ds = 2; + p_desc->send_wr[0].wr.p_next = NULL; + + IPOIB_EXIT( IPOIB_DBG_SEND ); + return NDIS_STATUS_SUCCESS; +} + +static inline NDIS_STATUS +__send_mgr_queue( + IN ipoib_port_t* const p_port, + IN eth_hdr_t* const p_eth_hdr, + OUT ipoib_endpt_t** const pp_endpt ) +{ + NDIS_STATUS status; + + PERF_DECLARE( GetEndpt ); + + IPOIB_ENTER( IPOIB_DBG_SEND ); + + /* Check the send queue and pend the request if not empty. */ + if( cl_qlist_count( &p_port->send_mgr.pending_list ) ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_WARNING, IPOIB_DBG_SEND, + ("Pending list not empty.\n") ); + return NDIS_STATUS_PENDING; + } + + /* Check the send queue and pend the request if not empty. */ + if( p_port->send_mgr.depth == p_port->p_adapter->params.sq_depth ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_WARNING, IPOIB_DBG_SEND, + ("No available WQEs.\n") ); + return NDIS_STATUS_PENDING; + } + + cl_perf_start( GetEndpt ); + status = __endpt_mgr_ref( p_port, p_eth_hdr->dst, pp_endpt ); + cl_perf_stop( &p_port->p_adapter->perf, GetEndpt ); + + if( status == NDIS_STATUS_NO_ROUTE_TO_DESTINATION && + ETH_IS_MULTICAST( p_eth_hdr->dst.addr ) ) + { + if( ipoib_port_join_mcast( p_port, p_eth_hdr->dst, + IB_MC_REC_STATE_FULL_MEMBER) == IB_SUCCESS ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_SEND, + ("Multicast Mac - trying to join.\n") ); + return NDIS_STATUS_PENDING; + } + } + else if ( status == NDIS_STATUS_SUCCESS && + ETH_IS_MULTICAST( p_eth_hdr->dst.addr ) && + !ETH_IS_BROADCAST( p_eth_hdr->dst.addr ) ) + { + CL_ASSERT( (*pp_endpt) ); + CL_ASSERT((*pp_endpt)->h_mcast != NULL); + (*pp_endpt)->is_in_use = TRUE; + } + + IPOIB_EXIT( IPOIB_DBG_SEND ); + return status; +} + + +static NDIS_STATUS +__build_send_desc( + IN ipoib_port_t* const p_port, + IN eth_hdr_t* const p_eth_hdr, + IN MDL* const p_mdl, + IN const size_t mdl_len, + IN SCATTER_GATHER_LIST *p_sgl, + IN OUT ipoib_send_desc_t* const p_desc ) +{ + NDIS_STATUS status; + int32_t hdr_idx; + uint32_t mss = 0; + + PNDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO p_checksum_list_info; + PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO p_lso_info; + PERF_DECLARE( SendMgrFilter ); + + IPOIB_ENTER( IPOIB_DBG_SEND ); + + /* Format the send descriptor. */ + p_checksum_list_info = + (PNDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO) NET_BUFFER_LIST_INFO( p_desc->p_netbuf_list,TcpIpChecksumNetBufferListInfo); + + // Calculate LSO + if( p_port->p_adapter->params.lso ) { + p_lso_info = + (PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO) + NET_BUFFER_LIST_INFO( p_desc->p_netbuf_list, TcpLargeSendNetBufferListInfo ); + ASSERT(p_lso_info); + if (p_lso_info) { + mss = (p_lso_info->LsoV1Transmit.MSS | p_lso_info->LsoV2Transmit.MSS); + } + } + + /* Format the send descriptor. */ + hdr_idx = cl_atomic_inc( &p_port->hdr_idx ); + hdr_idx &= (p_port->p_adapter->params.sq_depth - 1); + ASSERT( hdr_idx < p_port->p_adapter->params.sq_depth ); + p_port->hdr[hdr_idx].type = p_eth_hdr->type; + p_port->hdr[hdr_idx].resv = 0; + + p_desc->send_wr[0].local_ds[0].vaddr = cl_get_physaddr( &p_port->hdr[hdr_idx] ); + p_desc->send_wr[0].local_ds[0].length = sizeof(ipoib_hdr_t); + p_desc->send_wr[0].local_ds[0].lkey = p_port->ib_mgr.lkey; + p_desc->send_wr[0].wr.send_opt = 0; + + + + if (mss) { //We have LSO packet + ASSERT( mss == (p_lso_info->LsoV1Transmit.MSS & p_lso_info->LsoV2Transmit.MSS)); + ASSERT ( (mss & (1<<20)) == mss); + status = __build_lso_desc( p_port, p_desc, mss, p_sgl, hdr_idx, p_lso_info ); + if( status != NDIS_STATUS_SUCCESS ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("__build_lso_desc returned 0x%08X.\n", status) ); + return status; + } + } + + else + { + uint32_t i; + cl_perf_start( SendMgrFilter ); + status = __send_mgr_filter( + p_port, p_eth_hdr, p_mdl, mdl_len,p_sgl, p_desc ); + cl_perf_stop( &p_port->p_adapter->perf, SendMgrFilter ); + if( status != NDIS_STATUS_SUCCESS ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("__send_mgr_filter returned 0x%08X.\n", status) ); + return status; + } + + if( p_desc->send_dir == SEND_UD_QP ) + { + p_desc->send_qp = p_port->ib_mgr.h_qp; // UD QP + for( i = 0; i < p_desc->num_wrs; i++ ) + { + p_desc->send_wr[i].wr.dgrm.ud.remote_qp = p_desc->p_endpt->qpn; + p_desc->send_wr[i].wr.dgrm.ud.remote_qkey = p_port->ib_mgr.bcast_rec.qkey; + p_desc->send_wr[i].wr.dgrm.ud.h_av = p_desc->p_endpt->h_av; + p_desc->send_wr[i].wr.dgrm.ud.pkey_index = p_port->pkey_index; + p_desc->send_wr[i].wr.dgrm.ud.rsvd = NULL; + p_desc->send_wr[i].wr.send_opt = 0; + + if( p_port->p_adapter->params.send_chksum_offload && + ( p_checksum_list_info->Transmit.IsIPv4 || + p_checksum_list_info->Transmit.IsIPv6 )) + { + // Set transimition checksum offloading + if( p_checksum_list_info->Transmit.IpHeaderChecksum ) + { + p_desc->send_wr[i].wr.send_opt |= IB_SEND_OPT_TX_IP_CSUM; + } + if( p_checksum_list_info->Transmit.TcpChecksum ) + { + p_desc->send_wr[i].wr.send_opt |= IB_SEND_OPT_TX_TCP_UDP_CSUM; + } + } + } + } + else // RC QP + { + CL_ASSERT( p_desc->send_dir == SEND_RC_QP ); + p_desc->send_qp = p_desc->p_endpt->conn.h_work_qp; + } + for( i = 0; i < p_desc->num_wrs; i++ ) + { + p_desc->send_wr[i].wr.wr_type = WR_SEND; + p_desc->send_wr[i].wr.wr_id = 0; + p_desc->send_wr[i].wr.ds_array = &p_desc->send_wr[i].local_ds[0]; + if( i ) + { + p_desc->send_wr[i-1].wr.p_next = &p_desc->send_wr[i].wr; + } + } + //TODO p_net_buf or p_buf +// p_desc->send_wr[p_desc->num_wrs - 1].wr.wr_id = (uintn_t)NET_BUFFER_LIST_FIRST_NB(p_desc->p_netbuf_list ); +//???? IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, ("WR_ID was set to NBL 0x%x \n",p_desc->p_netbuf_list )); + p_desc->send_wr[p_desc->num_wrs - 1].wr.wr_id = (uintn_t)p_desc->p_netbuf_list ; + + p_desc->send_wr[p_desc->num_wrs - 1].wr.send_opt |= IB_SEND_OPT_SIGNALED; + p_desc->send_wr[p_desc->num_wrs - 1].wr.p_next = NULL; + } + + /* Store context in our reserved area of the packet. */ + IPOIB_PORT_FROM_PACKET( p_desc->p_netbuf_list ) = p_port; + IPOIB_ENDPT_FROM_PACKET( p_desc->p_netbuf_list ) = p_desc->p_endpt; + IPOIB_SEND_FROM_NETBUFFER( NET_BUFFER_LIST_FIRST_NB(p_desc->p_netbuf_list ))= p_desc->p_buf; + + IPOIB_EXIT( IPOIB_DBG_SEND ); + return NDIS_STATUS_SUCCESS; +} + +static NDIS_STATUS +__build_lso_desc( + IN ipoib_port_t* const p_port, + IN OUT ipoib_send_desc_t* const p_desc, + IN ULONG mss, + IN SCATTER_GATHER_LIST *p_sgl, + IN int32_t hdr_idx, + IN PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO p_lso_info) +{ + NDIS_STATUS status; + LsoData TheLsoData; + UINT IndexOfData = 0; + + PNET_BUFFER FirstBuffer = NET_BUFFER_LIST_FIRST_NB (p_desc->p_netbuf_list); + ULONG PacketLength = NET_BUFFER_DATA_LENGTH(FirstBuffer); + + IPOIB_ENTER( IPOIB_DBG_SEND ); + + + + memset(&TheLsoData, 0, sizeof TheLsoData ); + status = GetLsoHeaderSize( + FirstBuffer, + &TheLsoData, + &IndexOfData, + &p_port->hdr[hdr_idx] ); + + if ((status != NDIS_STATUS_SUCCESS ) || + (TheLsoData.FullBuffers != TheLsoData.UsedBuffers)) + { + ASSERT(FALSE); + + IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, ("<-- Throwing this packet\n")); + + if( status == NDIS_STATUS_SUCCESS ) + { + status = NDIS_STATUS_INVALID_PACKET; + } + return status; + } + ASSERT(TheLsoData.LsoHeaderSize> 0); + // Tell NDIS how much we will send. + //PktExt->NdisPacketInfo[TcpLargeSendPacketInfo] = UlongToPtr(PacketLength); + p_lso_info->LsoV1TransmitComplete.TcpPayload = PacketLength; + + p_desc->send_wr[0].wr.dgrm.ud.mss = mss; + p_desc->send_wr[0].wr.dgrm.ud.header = TheLsoData.LsoBuffers[0].pData; + p_desc->send_wr[0].wr.dgrm.ud.hlen = TheLsoData.LsoHeaderSize ;//lso_header_size; + p_desc->send_wr[0].wr.dgrm.ud.remote_qp = p_desc->p_endpt->qpn; + p_desc->send_wr[0].wr.dgrm.ud.remote_qkey = p_port->ib_mgr.bcast_rec.qkey; + p_desc->send_wr[0].wr.dgrm.ud.h_av = p_desc->p_endpt->h_av; + p_desc->send_wr[0].wr.dgrm.ud.pkey_index = p_port->pkey_index; + p_desc->send_wr[0].wr.dgrm.ud.rsvd = NULL; + + //TODO: Should be NBL or p_desc + p_desc->send_wr[0].wr.wr_id = (uintn_t)p_desc->p_netbuf_list; + p_desc->send_wr[0].wr.ds_array = p_desc->send_wr[0].local_ds; + p_desc->send_wr[0].wr.wr_type = WR_LSO; + p_desc->send_wr[0].wr.send_opt = + (IB_SEND_OPT_TX_IP_CSUM | IB_SEND_OPT_TX_TCP_UDP_CSUM) | IB_SEND_OPT_SIGNALED; + + p_desc->send_wr[0].wr.p_next = NULL; + p_desc->send_qp = p_port->ib_mgr.h_qp; + p_desc->send_dir = SEND_UD_QP; + status = __send_gen(p_port, p_desc, p_sgl, IndexOfData ); + + IPOIB_EXIT( IPOIB_DBG_SEND ); + return status; +} + +static inline void +__process_failed_send( + IN ipoib_port_t* const p_port, + IN ipoib_send_desc_t* const p_desc, + IN const NDIS_STATUS status, + IN ULONG compl_flags) +{ + IPOIB_ENTER( IPOIB_DBG_SEND ); + + /* Complete the packet. */ + NET_BUFFER_LIST_NEXT_NBL(p_desc->p_netbuf_list) = NULL; + NET_BUFFER_LIST_STATUS(p_desc->p_netbuf_list) = status; + NdisMSendNetBufferListsComplete( p_port->p_adapter->h_adapter, + p_desc->p_netbuf_list, compl_flags ); + ipoib_inc_send_stat( p_port->p_adapter, IP_STAT_ERROR, 0 ); + /* Deref the endpoint. */ + if( p_desc->p_endpt ) + ipoib_endpt_deref( p_desc->p_endpt ); + + if( p_desc->p_buf ) + { + NdisFreeToNPagedLookasideList( + &p_port->buf_mgr.send_buf_list, p_desc->p_buf ); + } + + IPOIB_EXIT( IPOIB_DBG_SEND ); +} + +// max number of physical fragmented buffers +#define MAX_PHYS_BUF_FRAG_ELEMENTS 0x29 +#define MP_FRAG_ELEMENT SCATTER_GATHER_ELEMENT +#define PMP_FRAG_ELEMENT PSCATTER_GATHER_ELEMENT + + +typedef struct _MP_FRAG_LIST { + ULONG NumberOfElements; + ULONG_PTR Reserved; + SCATTER_GATHER_ELEMENT Elements[MAX_PHYS_BUF_FRAG_ELEMENTS]; +} MP_FRAG_LIST, *PMP_FRAG_LIST; + + +void +CreateFragList( + ULONG PhysBufCount, + PNET_BUFFER NetBuff, + ULONG PacketLength, + PMP_FRAG_LIST pFragList + ) +{ +// ETH_ENTER(ETH_SND); + + ULONG i = 0; + int j=0; + + UINT buf_len = NET_BUFFER_DATA_LENGTH(NetBuff); + PMDL pMdl = NET_BUFFER_CURRENT_MDL(NetBuff); + + ULONG CurrentMdlDataOffset = NET_BUFFER_CURRENT_MDL_OFFSET(NetBuff); + ASSERT(MmGetMdlByteCount(pMdl) >= CurrentMdlDataOffset); + + + ASSERT(NetBuff != NULL); +#ifdef DBG + ASSERT(PhysBufCount <= MAX_PHYS_BUF_FRAG_ELEMENTS); +#else + UNREFERENCED_PARAMETER(PhysBufCount); +#endif + + ASSERT(buf_len > 0); + UNREFERENCED_PARAMETER(PacketLength); + + +// ETH_PRINT(TRACE_LEVEL_VERBOSE, ETH_SND, "CreateFragList: NetBuff %p, Length =0x%x\n", NetBuff, buf_len); + + while ( (pMdl != NULL) && (buf_len != 0) ) + { + PPFN_NUMBER page_array = MmGetMdlPfnArray(pMdl); + int MdlBufCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(pMdl), MmGetMdlByteCount(pMdl)); + + ULONG offset = MmGetMdlByteOffset(pMdl) + CurrentMdlDataOffset ; + ULONG MdlBytesCount = MmGetMdlByteCount(pMdl) - CurrentMdlDataOffset; + CurrentMdlDataOffset = 0; + + if( MdlBytesCount == 0 ) + { + pMdl = pMdl->Next; + continue; + } + + ASSERT( (buf_len > 0) && (MdlBytesCount > 0) ); + +// ETH_PRINT(TRACE_LEVEL_VERBOSE, ETH_SND, "CreateFragList: pMdl=%p, MdlBytesCount=x%x, MdlBufCount=0x%x\n", pMdl, MdlBytesCount, MdlBufCount); + + if (MdlBytesCount > 0) + { + if( buf_len > MdlBytesCount) + { + buf_len -= MdlBytesCount; + } + else + { + MdlBytesCount = buf_len; + buf_len = 0; + } + // + // In some cases the mdlcount is greater than needed and in the last page + // there is 0 bytes + // + for (j=0; ((j< MdlBufCount) && (MdlBytesCount > 0)); j++) + { + ASSERT(MdlBytesCount > 0); + if (j ==0 ) + { + // + // First page + // + ULONG64 ul64PageNum = page_array[j]; + pFragList->Elements[i].Address.QuadPart = (ul64PageNum << PAGE_SHIFT)+ offset; + if( offset + MdlBytesCount > PAGE_SIZE ) + { + // + // the data slides behind the page boundry + // + ASSERT(PAGE_SIZE > offset); + pFragList->Elements[i].Length = PAGE_SIZE - offset; + MdlBytesCount -= pFragList->Elements[i].Length; + } + else + { + // + // All the data is hold in one page + // + pFragList->Elements[i].Length = MdlBytesCount; + MdlBytesCount = 0; + } + +// ETH_PRINT(TRACE_LEVEL_VERBOSE, ETH_SND, "CreateFragList: j == 0, MdlBytesCount=x%x, i = %d, element.length=0x%x \n", MdlBytesCount, i, pFragList->Elements[i].Length); + } + else + { + if (page_array[j] == (page_array[j-1] + 1)) + { + + ULONG size = min(PAGE_SIZE, MdlBytesCount); + i -= 1; + pFragList->Elements[i].Length += size; + MdlBytesCount -= size; + } + else + { + // + // Not first page. so the data always start at the begining of the page + // + ULONG64 ul64PageNum = page_array[j]; + pFragList->Elements[i].Address.QuadPart = (ul64PageNum << PAGE_SHIFT); + pFragList->Elements[i].Length = min(PAGE_SIZE, MdlBytesCount); + MdlBytesCount -= pFragList->Elements[i].Length; + } + +// ETH_PRINT(TRACE_LEVEL_VERBOSE, ETH_SND, "CreateFragList: j != 0, MdlBytesCount=x%x, i = %d, element.length=0x%x \n", MdlBytesCount, i, pFragList->Elements[i].Length); + } + i++; + ASSERT(i <= MAX_PHYS_BUF_FRAG_ELEMENTS); + } + } + + pMdl = pMdl->Next; + } + + if (buf_len != 0) + { + // + // In some cases the size in MDL isn't equal to the buffer size. In such + // a case we need to add the rest of packet to last chunk + // + ASSERT(i > 0); // To prevent array underflow + pFragList->Elements[i-1].Length += buf_len; +// ETH_PRINT(TRACE_LEVEL_ERROR, ETH_SND, "CreateFragList: buf_len != 0, i = %d, element.length=0x%x \n", i -1, pFragList->Elements[i-1].Length); + } + + ASSERT(i <= PhysBufCount); + pFragList->NumberOfElements = i; + +#ifdef DBG +{ + ULONG size = 0; + for (i = 0; i < pFragList->NumberOfElements; ++i) + { + size += pFragList->Elements[i].Length; + } + ASSERT(size == PacketLength); +} +#endif + +// ETH_EXIT(ETH_SND); +} + + + + +void +ipoib_port_send( + IN ipoib_port_t* const p_port, + IN NET_BUFFER_LIST *p_net_buffer_list, + IN ULONG send_flags) +{ + NDIS_STATUS status; + PNET_BUFFER p_netbuf; + UINT buf_cnt = 0; + //ipoib_send_desc_t *p_desc; + ULONG send_complete_flags = 0; + KIRQL old_irql; + PVOID p_sgl; + + PERF_DECLARE( GetEthHdr ); + PERF_DECLARE( BuildSendDesc ); + PERF_DECLARE( QueuePacket ); + PERF_DECLARE( SendMgrQueue ); + PERF_DECLARE( PostSend ); + PERF_DECLARE( ProcessFailedSends ); + + IPOIB_ENTER( IPOIB_DBG_SEND ); + + if (NDIS_TEST_SEND_AT_DISPATCH_LEVEL(send_flags)) + { + //TODO Tzachid: make an assert here to validate your IRQL + //ASSERT (KeGetCurrentIRQL() == DISPATCH_LEVEL); + NDIS_SET_SEND_COMPLETE_FLAG(send_complete_flags, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL); + } else { + //ASSERT (KeGetCurrentIRQL() == PASSIVE_LEVEL); + } + + cl_obj_lock( &p_port->obj ); + if( p_port->state != IB_QPS_RTS ) + { + + + cl_obj_unlock( &p_port->obj ); + + + NET_BUFFER_LIST_STATUS(p_net_buffer_list) = NDIS_STATUS_FAILURE; + NET_BUFFER_LIST_NEXT_NBL(p_net_buffer_list) = NULL; + ipoib_inc_send_stat( p_port->p_adapter, IP_STAT_DROPPED, 0 ); + + NdisMSendNetBufferListsComplete( + p_port->p_adapter->h_adapter, + p_net_buffer_list, + send_complete_flags); + + return; + } + cl_obj_unlock( &p_port->obj ); + + //IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + // ("Processing netbuffer list: %x\n", p_net_buffer_list)); + for (p_netbuf = NET_BUFFER_LIST_FIRST_NB(p_net_buffer_list); + p_netbuf != NULL; + p_netbuf = NET_BUFFER_NEXT_NB(p_netbuf)) + { + IPOIB_PORT_FROM_PACKET(p_net_buffer_list) = p_port; + IPOIB_NET_BUFFER_LIST_FROM_NETBUFFER(p_netbuf) = p_net_buffer_list; + IPOIB_FROM_QUEUE(p_netbuf) = NULL; + /*p_desc = &p_port->send_mgr.desc; + p_desc->p_buf = p_netbuf; + p_desc->p_endpt = NULL; + p_desc->p_buf = NULL; + p_desc->send_qp = NULL; + p_desc->num_wrs = 1; + p_desc->send_dir = 0;*/ + + old_irql = KeGetCurrentIrql(); + if (old_irql < DISPATCH_LEVEL) + { + KeRaiseIrqlToDpcLevel(); + } + ++buf_cnt; + //IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + // ("[%d] Netbuf = %x\n",buf_cnt, p_netbuf) ); + if (cl_is_item_in_qlist( &p_port->send_mgr.pending_list, + IPOIB_LIST_ITEM_FROM_PACKET( p_net_buffer_list ))) { + p_sgl = IPOIB_FROM_QUEUE(p_netbuf); + //IPOIB_FROM_QUEUE(p_net_buffer) = (void*)1; + ASSERT (p_sgl); + //IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + // ("[%d] FROM_QUEUE Netbuf = %x, found SGL = %x\n",buf_cnt, p_netbuf, p_sgl) ); + status = NDIS_STATUS_SUCCESS; + } else { + +//#if 0 + CHAR *pTemp = (CHAR *) ExAllocatePoolWithTag(NonPagedPool , p_port->p_adapter->sg_list_size, 'abcd'); + CL_ASSERT(pTemp != NULL); + status = NDIS_STATUS_SUCCESS; + p_sgl = pTemp; + CreateFragList(NdisQueryNetBufferPhysicalCount(p_netbuf), p_netbuf, NET_BUFFER_DATA_LENGTH(p_netbuf), (PMP_FRAG_LIST) p_sgl); + IPOIB_FROM_QUEUE(p_netbuf) = NULL; + /*IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("[%d] Allocation from scratch: Netbuf = %x, found SGL = %x, PhysBufCnt=%ld, NB LEN = %ld, sg_list_size=%ld\n", + buf_cnt, p_netbuf, p_sgl,NdisQueryNetBufferPhysicalCount(p_netbuf) , + NET_BUFFER_DATA_LENGTH(p_netbuf),p_port->p_adapter->sg_list_size) ); + */ + ipoib_process_sg_list(NULL, NULL, (PSCATTER_GATHER_LIST)p_sgl, p_netbuf); + status = NDIS_STATUS_SUCCESS; +//#endif +#if 0 + status = NdisMAllocateNetBufferSGList( + p_port->p_adapter->NdisMiniportDmaHandle, + p_netbuf, + p_netbuf, + NDIS_SG_LIST_WRITE_TO_DEVICE, + NULL, + 0); +#endif + } + KeLowerIrql (old_irql); + + if( status != NDIS_STATUS_SUCCESS ) + { + /* fail net buffer list */ + NET_BUFFER_LIST_NEXT_NBL(p_net_buffer_list) = NULL; + NET_BUFFER_LIST_STATUS(p_net_buffer_list) = NDIS_STATUS_RESOURCES; + NdisMSendNetBufferListsComplete( + p_port->p_adapter->h_adapter, + p_net_buffer_list, + send_complete_flags); + break; + } + ASSERT(buf_cnt); + IPOIB_GET_NET_BUFFER_LIST_REF_COUNT(p_net_buffer_list) = (PVOID)(ULONG_PTR)buf_cnt; + } + +} + + +void +ipoib_port_resume( + IN ipoib_port_t* const p_port, + IN boolean_t b_pending ) +{ + NDIS_STATUS status; + cl_list_item_t *p_item; + NET_BUFFER *p_net_buffer; + NET_BUFFER_LIST *p_net_buffer_list; + //ipoib_send_desc_t *p_desc; + KIRQL old_irql; + UINT buf_cnt = 0; + NET_BUFFER_LIST *p_prev_nbl = NULL; + PVOID p_sgl; + static PVOID p_prev_sgl = NULL; + + PERF_DECLARE( GetEndpt ); + PERF_DECLARE( BuildSendDesc ); + PERF_DECLARE( ProcessFailedSends ); + PERF_DECLARE( PostSend ); + + IPOIB_ENTER( IPOIB_DBG_SEND ); + + UNUSED_PARAM(b_pending); + + cl_obj_lock( &p_port->obj ); + if( p_port->state != IB_QPS_RTS ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_WARNING, IPOIB_DBG_SEND, + ("Invalid state - Aborting.\n") ); + cl_obj_unlock( &p_port->obj ); + return; + } + cl_obj_unlock( &p_port->obj ); + +//TODO NDIS60 +////?????????????? cl_spinlock_acquire( &p_port->send_lock ); + + for( p_item = cl_qlist_head( &p_port->send_mgr.pending_list ); + p_item != cl_qlist_end( &p_port->send_mgr.pending_list ); + p_item = cl_qlist_head( &p_port->send_mgr.pending_list ) ) + { + + + /* Check the send queue and pend the request if not empty. */ + if( p_port->send_mgr.depth == p_port->p_adapter->params.sq_depth ) + { + IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_SEND, + ("No available WQEs.\n") ); + break; + } + + p_net_buffer_list = IPOIB_PACKET_FROM_LIST_ITEM( + cl_qlist_remove_head( &p_port->send_mgr.pending_list ) ); + if (p_prev_nbl == p_net_buffer_list) { +// IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + // ("TRYING TO PROCESS ONCE AGAIN, EXITING: %x\n", p_net_buffer_list)); + break; //TODO more sophisticated mechanism to avoid starvation + } + old_irql = KeGetCurrentIrql(); + if (old_irql < DISPATCH_LEVEL) + { + KeRaiseIrqlToDpcLevel(); + } +// IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + // ("Processing netbuffer list from queue: %x\n", (UINT) (PVOID) p_net_buffer_list)); + + for( p_net_buffer = NET_BUFFER_LIST_FIRST_NB(p_net_buffer_list); + p_net_buffer != NULL; + p_net_buffer = NET_BUFFER_NEXT_NB(p_net_buffer), buf_cnt++) + { + + + p_sgl = IPOIB_FROM_QUEUE(p_net_buffer); + //IPOIB_FROM_QUEUE(p_net_buffer) = (void*)1; + ASSERT (p_sgl); + IPOIB_PORT_FROM_PACKET(p_net_buffer_list) = p_port; + IPOIB_NET_BUFFER_LIST_FROM_NETBUFFER(p_net_buffer) = p_net_buffer_list; + /*p_desc = &p_port->send_mgr.desc; + p_desc->p_buf = p_net_buffer; + p_desc->p_endpt = NULL; + p_desc->p_buf = NULL; + p_desc->send_qp = NULL; + p_desc->num_wrs = 1; + p_desc->send_dir = 0;*/ + +// IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + // ("[%d] Netbuf = %x, p_sgl = %x\n",buf_cnt, p_net_buffer, p_sgl) ); + ASSERT(p_sgl); + if (p_sgl != (void*) 1) { + ipoib_process_sg_list(NULL, NULL, (PSCATTER_GATHER_LIST) p_sgl, p_net_buffer); + status = NDIS_STATUS_SUCCESS; + } + else { + ASSERT(FALSE); + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Getting strange flow\n") ); + NdisMFreeNetBufferSGList( + p_port->p_adapter->NdisMiniportDmaHandle, + (PSCATTER_GATHER_LIST)p_sgl, + p_net_buffer ); + status = NdisMAllocateNetBufferSGList( + p_port->p_adapter->NdisMiniportDmaHandle, + p_net_buffer, + p_net_buffer, + NDIS_SG_LIST_WRITE_TO_DEVICE, + NULL, + 0 /*p_port->p_adapter->sg_list_size*/ ); + } + p_prev_sgl = p_sgl; + if( status != NDIS_STATUS_SUCCESS ) + { + /* fail net buffer list */ + NET_BUFFER_LIST_NEXT_NBL(p_net_buffer_list) = NULL; + NET_BUFFER_LIST_STATUS(p_net_buffer_list) = NDIS_STATUS_RESOURCES; + NdisMSendNetBufferListsComplete( + p_port->p_adapter->h_adapter, + p_net_buffer_list, + 0); + break; + } + } + + KeLowerIrql (old_irql); + + + p_prev_nbl = p_net_buffer_list; + + } + IPOIB_EXIT( IPOIB_DBG_SEND ); +} + + + +static void +__send_cb( + IN const ib_cq_handle_t h_cq, + IN void *cq_context ) +{ + ipoib_port_t *p_port; + ib_api_status_t status; + ib_wc_t wc[MAX_SEND_WC], *p_wc, *p_free; + cl_qlist_t done_list; + NET_BUFFER_LIST *p_nbl; + uint32_t length; + ipoib_endpt_t *p_endpt; + send_buf_t *p_send_buf; + ip_stat_sel_t type; + size_t i; + NET_BUFFER *p_netbuffer = NULL; + + PERF_DECLARE( SendCompBundle ); + PERF_DECLARE( SendCb ); + PERF_DECLARE( PollSend ); + PERF_DECLARE( SendComp ); + PERF_DECLARE( FreeSendBuf ); + PERF_DECLARE( RearmSend ); + PERF_DECLARE( PortResume ); + + IPOIB_ENTER( IPOIB_DBG_SEND ); + + cl_perf_clr( SendCompBundle ); + + cl_perf_start( SendCb ); + + UNUSED_PARAM( h_cq ); + + cl_qlist_init( &done_list ); + + p_port = (ipoib_port_t*)cq_context; + + ipoib_port_ref( p_port, ref_send_cb ); + + for( i = 0; i < MAX_SEND_WC; i++ ) + wc[i].p_next = &wc[i + 1]; + wc[MAX_SEND_WC - 1].p_next = NULL; + + do + { + p_free = wc; + cl_perf_start( PollSend ); + status = p_port->p_adapter->p_ifc->poll_cq( p_port->ib_mgr.h_send_cq, &p_free, &p_wc ); + cl_perf_stop( &p_port->p_adapter->perf, PollSend ); + CL_ASSERT( status == IB_SUCCESS || status == IB_NOT_FOUND ); + + while( p_wc ) + { + cl_perf_start( SendComp ); + CL_ASSERT( p_wc->status != IB_WCS_SUCCESS || p_wc->wc_type == IB_WC_SEND ); + p_nbl = (NET_BUFFER_LIST*)(uintn_t)p_wc->wr_id; + //IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_SEND, + //("[1]Successfull send completion for NBL=0x%x .\n", (UINT) (PVOID) p_nbl )); + CL_ASSERT( p_nbl ); + CL_ASSERT( IPOIB_PORT_FROM_PACKET( p_nbl ) == p_port ); + length = 0; + p_endpt = IPOIB_ENDPT_FROM_PACKET( p_nbl ); + p_send_buf = IPOIB_SEND_FROM_NETBUFFER( NET_BUFFER_LIST_FIRST_NB (p_nbl )); + + switch( p_wc->status ) + { + case IB_WCS_SUCCESS: + if( p_endpt->h_mcast ) + { + if( p_endpt->dgid.multicast.raw_group_id[11] == 0xFF && + p_endpt->dgid.multicast.raw_group_id[10] == 0xFF && + p_endpt->dgid.multicast.raw_group_id[12] == 0xFF && + p_endpt->dgid.multicast.raw_group_id[13] == 0xFF ) + { + type = IP_STAT_BCAST_BYTES; + } + else + { + type = IP_STAT_MCAST_BYTES; + } + } + else + { + type = IP_STAT_UCAST_BYTES; + } + for (p_netbuffer = NET_BUFFER_LIST_FIRST_NB(p_nbl); + p_netbuffer != NULL; + p_netbuffer = NET_BUFFER_NEXT_NB(p_netbuffer)) + { + length += NET_BUFFER_DATA_LENGTH(p_netbuffer); + } + ipoib_inc_send_stat( p_port->p_adapter, type, length ); + // IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_SEND, + //("Successfull send completion for NBL=0x%x .\n", (UINT) (PVOID) p_nbl) ); + NET_BUFFER_LIST_STATUS(p_nbl) = NDIS_STATUS_SUCCESS; + IPOIB_DEC_NET_BUFFER_LIST_REF_COUNT(p_nbl); + if (IPOIB_GET_NET_BUFFER_LIST_REF_COUNT(p_nbl) == 0) + NdisMSendNetBufferListsComplete(p_port->p_adapter->h_adapter, + p_nbl, + 0); + break; + + case IB_WCS_WR_FLUSHED_ERR: + IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_SEND, + ("Flushed send completion.\n") ); + ipoib_inc_send_stat( p_port->p_adapter, IP_STAT_DROPPED, 0 ); + NET_BUFFER_LIST_STATUS(p_nbl) = NDIS_STATUS_RESET_IN_PROGRESS; + NdisMSendNetBufferListsComplete(p_port->p_adapter->h_adapter, + p_nbl, + 0); + break; + + default: + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Send failed with %s (vendor specific %#x)\n", + p_port->p_adapter->p_ifc->get_wc_status_str( p_wc->status ), + (int)p_wc->vendor_specific) ); + ipoib_inc_send_stat( p_port->p_adapter, IP_STAT_ERROR, 0 ); + NET_BUFFER_LIST_STATUS(p_nbl) = NDIS_STATUS_FAILURE; + NdisMSendNetBufferListsComplete(p_port->p_adapter->h_adapter, + p_nbl, + 0); + break; + } + cl_perf_stop( &p_port->p_adapter->perf, SendComp ); + /* Dereference the enpoint used for the transfer. */ + ipoib_endpt_deref( p_endpt ); + + if( p_send_buf ) + { + cl_perf_start( FreeSendBuf ); + NdisFreeToNPagedLookasideList( &p_port->buf_mgr.send_buf_list, + p_send_buf ); + cl_perf_stop( &p_port->p_adapter->perf, FreeSendBuf ); + } + + cl_atomic_dec( &p_port->send_mgr.depth ); + + p_wc = p_wc->p_next; + cl_perf_inc( SendCompBundle ); + } + /* If we didn't use up every WC, break out. */ + } while( !p_free ); + + /* Rearm the CQ. */ + cl_perf_start( RearmSend ); + status = p_port->p_adapter->p_ifc->rearm_cq( p_port->ib_mgr.h_send_cq, FALSE ); + cl_perf_stop( &p_port->p_adapter->perf, RearmSend ); + CL_ASSERT( status == IB_SUCCESS ); + + /* Resume any sends awaiting resources. */ + cl_perf_start( PortResume ); + ipoib_port_resume( p_port, TRUE ); + cl_perf_stop( &p_port->p_adapter->perf, PortResume ); + + ipoib_port_deref( p_port, ref_send_cb ); + + cl_perf_stop( &p_port->p_adapter->perf, SendCb ); + cl_perf_update_ctr( &p_port->p_adapter->perf, SendCompBundle ); + + IPOIB_EXIT( IPOIB_DBG_SEND ); +} + + +/****************************************************************************** +* +* Endpoint manager implementation +* +******************************************************************************/ +static void +__endpt_mgr_construct( + IN ipoib_port_t* const p_port ) +{ + IPOIB_ENTER( IPOIB_DBG_INIT ); + cl_qmap_init( &p_port->endpt_mgr.mac_endpts ); + cl_qmap_init( &p_port->endpt_mgr.lid_endpts ); + cl_fmap_init( &p_port->endpt_mgr.gid_endpts, __gid_cmp ); + IPOIB_EXIT( IPOIB_DBG_INIT ); +} + +//TODO Restore CM +#if 0 +static void +__endpt_cm_mgr_thread( +IN void* p_context ); +#endif + +static ib_api_status_t +__endpt_mgr_init( + IN ipoib_port_t* const p_port ) +{ + IPOIB_ENTER( IPOIB_DBG_INIT ); +#if 0 + if( p_port->p_adapter->params.cm_enabled ) + { + cl_fmap_init( &p_port->endpt_mgr.conn_endpts, __gid_cmp ); + + NdisInitializeListHead( &p_port->endpt_mgr.pending_conns ); + NdisAllocateSpinLock( &p_port->endpt_mgr.conn_lock ); + cl_event_init( &p_port->endpt_mgr.event, FALSE ); + + NdisInitializeListHead( &p_port->endpt_mgr.remove_conns ); + NdisAllocateSpinLock( &p_port->endpt_mgr.remove_lock ); + + cl_thread_init( &p_port->endpt_mgr.h_thread, + __endpt_cm_mgr_thread, + ( const void *)p_port, + "CmEndPtMgr" ); + } +#endif + UNUSED_PARAM(p_port); + IPOIB_EXIT( IPOIB_DBG_INIT ); + return IB_SUCCESS; +} + +//TODO CM Restore +#if 0 +static void +__endpt_cm_mgr_thread( +IN void* p_context ) +{ + ib_api_status_t ib_status; + LIST_ENTRY *p_item; + ipoib_endpt_t *p_endpt; + ipoib_port_t *p_port =( ipoib_port_t *)p_context; + + IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, + ("Starting Port [%d] Endpt CM thread \n", p_port->port_num ) ); + + while( !p_port->endpt_mgr.thread_is_done ) + { + cl_event_wait_on( &p_port->endpt_mgr.event, EVENT_NO_TIMEOUT, FALSE ); + + while( ( p_item = NdisInterlockedRemoveHeadList( + &p_port->endpt_mgr.pending_conns, + &p_port->endpt_mgr.conn_lock) ) != NULL ) + { + + p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, list_item ); + if( p_port->endpt_mgr.thread_is_done ) + { + endpt_cm_set_state( p_endpt, IPOIB_CM_DISCONNECTED ); + continue; + } + + IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, + ("Endpt[%p] CONNECT REQ to MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + p_endpt, + p_endpt->mac.addr[0], p_endpt->mac.addr[1], + p_endpt->mac.addr[2], p_endpt->mac.addr[3], + p_endpt->mac.addr[4], p_endpt->mac.addr[5] ) ); + + if( !p_endpt->conn.h_send_qp ) + { + ib_status = endpt_cm_create_qp( p_endpt, &p_endpt->conn.h_send_qp ); + if( ib_status != IB_SUCCESS ) + { + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Endpt [%p ] CM create QP failed status %#x\n", p_endpt, ib_status ) ); + } + else + { + ib_status = ipoib_endpt_connect( p_endpt ); + if( ib_status != IB_SUCCESS && ib_status != IB_PENDING ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Endpt [ %p ] conn REQ failed status %#x\n", p_endpt, ib_status ) ); + } + } + if( ib_status != IB_SUCCESS && ib_status != IB_PENDING ) + { + endpt_cm_set_state( p_endpt, IPOIB_CM_DESTROY ); + endpt_cm_flush_recv( p_port, p_endpt ); + endpt_cm_set_state( p_endpt, IPOIB_CM_DISCONNECTED ); + } + } + + }//while( p_item != NULL ) + + while( ( p_item = NdisInterlockedRemoveHeadList( + &p_port->endpt_mgr.remove_conns, + &p_port->endpt_mgr.remove_lock ) ) != NULL ) + { + p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, list_item ); + + endpt_cm_set_state( p_endpt, IPOIB_CM_DESTROY ); + + IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_INIT, + ("\nDESTROYING Endpt[%p] MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + p_endpt, + p_endpt->mac.addr[0], p_endpt->mac.addr[1], + p_endpt->mac.addr[2], p_endpt->mac.addr[3], + p_endpt->mac.addr[4], p_endpt->mac.addr[5] ) ); + endpt_cm_flush_recv( p_port, p_endpt ); + endpt_cm_set_state( p_endpt, IPOIB_CM_DISCONNECTED ); + cl_obj_destroy( &p_endpt->obj ); + } + } + + p_port->endpt_mgr.thread_is_done++; + NdisFreeSpinLock( &p_port->endpt_mgr.conn_lock ); + + IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, + (" Port [%d] Endpt thread is done\n", p_port->port_num ) ); +} +#endif + +static void +__endpt_mgr_destroy( + IN ipoib_port_t* const p_port ) +{ + IPOIB_ENTER( IPOIB_DBG_INIT ); + CL_ASSERT( cl_is_qmap_empty( &p_port->endpt_mgr.mac_endpts ) ); + CL_ASSERT( cl_is_qmap_empty( &p_port->endpt_mgr.lid_endpts ) ); + CL_ASSERT( cl_is_fmap_empty( &p_port->endpt_mgr.gid_endpts ) ); + UNUSED_PARAM(p_port); +#if 0 + if( p_port->p_adapter->params.cm_enabled ) + { + CL_ASSERT( cl_is_fmap_empty( &p_port->endpt_mgr.conn_endpts ) ); + } +#endif + IPOIB_EXIT( IPOIB_DBG_INIT ); +} + + +static void +__endpt_mgr_remove_all( + IN ipoib_port_t* const p_port ) +{ + IPOIB_ENTER( IPOIB_DBG_ENDPT ); + + cl_obj_lock( &p_port->obj ); + /* Wait for all readers to complete. */ + while( p_port->endpt_rdr ) + ; + /* + * We don't need to initiate destruction - this is called only + * from the __port_destroying function, and destruction cascades + * to all child objects. Just clear all the maps. + */ + cl_qmap_remove_all( &p_port->endpt_mgr.mac_endpts ); + cl_qmap_remove_all( &p_port->endpt_mgr.lid_endpts ); + cl_fmap_remove_all( &p_port->endpt_mgr.gid_endpts ); + cl_obj_unlock( &p_port->obj ); + + IPOIB_EXIT( IPOIB_DBG_ENDPT ); +} + + +static void +__endpt_mgr_reset_all( + IN ipoib_port_t* const p_port ) +{ + cl_map_item_t *p_item; + cl_fmap_item_t *p_fmap_item; + ipoib_endpt_t *p_endpt; + cl_qlist_t mc_list; + cl_qlist_t conn_list; + uint32_t local_exist = 0; + NDIS_LINK_STATE link_state; + NDIS_STATUS_INDICATION status_indication; + + + IPOIB_ENTER( IPOIB_DBG_ENDPT ); + + cl_qlist_init( &mc_list ); + cl_qlist_init( &conn_list ); +//??? cl_obj_lock( &p_port->obj ); + /* Wait for all readers to complete. */ + while( p_port->endpt_rdr ) + ; + +#if 0 + __endpt_mgr_remove_all(p_port); +#else + link_state.Header.Revision = NDIS_LINK_STATE_REVISION_1; + link_state.Header.Type = NDIS_OBJECT_TYPE_DEFAULT; + link_state.Header.Size = sizeof(NDIS_LINK_STATE); + link_state.MediaConnectState = MediaConnectStateDisconnected; + link_state.MediaDuplexState = MediaDuplexStateFull; + link_state.XmitLinkSpeed = link_state.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED; + + IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication, + p_port->p_adapter->h_adapter, + NDIS_STATUS_LINK_STATE, + (PVOID)&link_state, + sizeof(link_state)); + IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, ("Indicate DISCONNECT!\n") ); + NdisMIndicateStatusEx(p_port->p_adapter->h_adapter,&status_indication); + + link_state.MediaConnectState = MediaConnectStateConnected; + IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication, + p_port->p_adapter->h_adapter, + NDIS_STATUS_LINK_STATE, + (PVOID)&link_state, + sizeof(link_state)); + IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, ("Indicate Connect\n") ); + NdisMIndicateStatusEx(p_port->p_adapter->h_adapter,&status_indication); + + + // IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, + // ("Link DOWN!\n") ); + + if( p_port->p_local_endpt ) + { + //TODO: CM RESTORE + //ipoib_port_cancel_listen( p_port, p_port->p_local_endpt ); + + cl_fmap_remove_item( &p_port->endpt_mgr.gid_endpts, + &p_port->p_local_endpt->gid_item ); + cl_qmap_remove_item( &p_port->endpt_mgr.mac_endpts, + &p_port->p_local_endpt->mac_item ); + cl_qmap_remove_item( &p_port->endpt_mgr.lid_endpts, + &p_port->p_local_endpt->lid_item ); + + cl_qlist_insert_head( + &mc_list, &p_port->p_local_endpt->mac_item.pool_item.list_item ); + local_exist = 1; + + p_port->p_local_endpt = NULL; + } + + p_item = cl_qmap_head( &p_port->endpt_mgr.mac_endpts ); + while( p_item != cl_qmap_end( &p_port->endpt_mgr.mac_endpts ) ) + { + p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item ); + p_item = cl_qmap_next( p_item ); + if( p_endpt->h_mcast ) + { + /* + * We destroy MC endpoints since they will get recreated + * when the port comes back up and we rejoin the MC groups. + */ + cl_qmap_remove_item( &p_port->endpt_mgr.mac_endpts, + &p_endpt->mac_item ); + cl_fmap_remove_item( &p_port->endpt_mgr.gid_endpts, + &p_endpt->gid_item ); + + cl_qlist_insert_tail( + &mc_list, &p_endpt->mac_item.pool_item.list_item ); + } + /* destroy connected endpoints if any */ + else if( p_port->p_adapter->params.cm_enabled && + endpt_cm_get_state( p_endpt ) != IPOIB_CM_DISCONNECTED ) + { + p_fmap_item = cl_fmap_get( &p_port->endpt_mgr.conn_endpts, &p_endpt->dgid ); + if( p_fmap_item != cl_fmap_end( &p_port->endpt_mgr.conn_endpts ) ) + { + cl_fmap_remove_item( &p_port->endpt_mgr.conn_endpts, + &p_endpt->conn_item ); + } + cl_qmap_remove_item( &p_port->endpt_mgr.mac_endpts, + &p_endpt->mac_item ); + cl_fmap_remove_item( &p_port->endpt_mgr.gid_endpts, + &p_endpt->gid_item ); + + cl_qlist_insert_tail( + &conn_list, &p_endpt->mac_item.pool_item.list_item ); + } + if( p_endpt->h_av ) + { + /* Destroy the AV for all other endpoints. */ + p_port->p_adapter->p_ifc->destroy_av( p_endpt->h_av ); + p_endpt->h_av = NULL; + } + + if( p_endpt->dlid ) + { + cl_qmap_remove_item( &p_port->endpt_mgr.lid_endpts, + &p_endpt->lid_item ); + IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT, + ("<__endptr_mgr_reset_all: setting p_endpt->dlid to 0\n")); + p_endpt->dlid = 0; + } + + } +#endif +//??? cl_obj_unlock( &p_port->obj ); + + //TODO CM + /*while( cl_qlist_count( &conn_list ) ) + { + endpt_cm_destroy_conn( p_port, + PARENT_STRUCT( cl_qlist_remove_head( &conn_list ), + ipoib_endpt_t, mac_item.pool_item.list_item ) ); + }*/ + + if(cl_qlist_count( &mc_list ) - local_exist) + { + p_port->mcast_cnt = (uint32_t)cl_qlist_count( &mc_list ) - local_exist; + } + else + { + p_port->mcast_cnt = 0; + KeSetEvent( &p_port->leave_mcast_event, EVENT_INCREMENT, FALSE ); + } + + IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,("p_port->mcast_cnt = %d\n", p_port->mcast_cnt - local_exist)); + + /* Destroy all multicast endpoints now that we have released the lock. */ + while( cl_qlist_count( &mc_list ) ) + { + cl_list_item_t *p_item; + p_item = cl_qlist_remove_head( &mc_list ); + p_endpt = PARENT_STRUCT(p_item, ipoib_endpt_t, mac_item.pool_item.list_item); + cl_obj_destroy( &p_endpt->obj); + } + + IPOIB_EXIT( IPOIB_DBG_ENDPT ); +} + + +/* + * Called when updating an endpoint entry in response to an ARP. + * Because receive processing is serialized, and holds a reference + * on the endpoint reader, we wait for all *other* readers to exit before + * removing the item. + */ +static void +__endpt_mgr_remove( + IN ipoib_port_t* const p_port, + IN ipoib_endpt_t* const p_endpt ) +{ +#if 0 //CM + cl_fmap_item_t* p_fmap_item; +#endif + IPOIB_ENTER( IPOIB_DBG_ENDPT ); + + /* This function must be called from the receive path */ + CL_ASSERT(p_port->endpt_rdr > 0); + + cl_obj_lock( &p_port->obj ); + /* Wait for all readers to complete. */ + while( p_port->endpt_rdr > 1 ) + ; + + /* Remove the endpoint from the maps so further requests don't find it. */ + cl_qmap_remove_item( &p_port->endpt_mgr.mac_endpts, &p_endpt->mac_item ); + /* + * The enpoints are *ALWAYS* in both the MAC and GID maps. They are only + * in the LID map if the GID has the same subnet prefix as us. + */ + cl_fmap_remove_item( &p_port->endpt_mgr.gid_endpts, &p_endpt->gid_item ); +#if 0 + + if( p_port->p_adapter->params.cm_enabled ) + { + p_fmap_item = cl_fmap_get( &p_port->endpt_mgr.conn_endpts, &p_endpt->dgid ); + + if( p_fmap_item != cl_fmap_end( &p_port->endpt_mgr.conn_endpts ) ) + { + cl_fmap_remove_item( &p_port->endpt_mgr.conn_endpts, + &p_endpt->conn_item ); + } + } +#endif + if( p_endpt->dlid ) + { + cl_qmap_remove_item( &p_port->endpt_mgr.lid_endpts, + &p_endpt->lid_item ); + } + + cl_obj_unlock( &p_port->obj ); + + //TODO CM + //endpt_cm_destroy_conn( p_port, p_endpt ); + + IPOIB_EXIT( IPOIB_DBG_ENDPT ); +} + + +NTSTATUS +ipoib_mac_to_gid( + IN ipoib_port_t* const p_port, + IN const mac_addr_t mac, + OUT ib_gid_t* p_gid ) +{ + ipoib_endpt_t* p_endpt; + cl_map_item_t *p_item; + uint64_t key = 0; + + IPOIB_ENTER( IPOIB_DBG_ENDPT ); + + cl_memcpy( &key, &mac, sizeof(mac_addr_t) ); + + cl_obj_lock( &p_port->obj ); + + p_item = cl_qmap_get( &p_port->endpt_mgr.mac_endpts, key ); + if( p_item == cl_qmap_end( &p_port->endpt_mgr.mac_endpts ) ) + { + cl_obj_unlock( &p_port->obj ); + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed endpoint lookup.\n") ); + return STATUS_INVALID_PARAMETER; + } + + p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item ); + *p_gid = p_endpt->dgid; + + cl_obj_unlock( &p_port->obj ); + + IPOIB_EXIT( IPOIB_DBG_ENDPT ); + return STATUS_SUCCESS; +} + + +NTSTATUS +ipoib_mac_to_path( + IN ipoib_port_t* const p_port, + IN const mac_addr_t mac, + OUT ib_path_rec_t* p_path ) +{ + ipoib_endpt_t* p_endpt; + cl_map_item_t *p_item; + uint64_t key = 0; + uint8_t sl; + net32_t flow_lbl; + uint8_t hop_limit; + uint8_t pkt_life; + + IPOIB_ENTER( IPOIB_DBG_ENDPT ); + + cl_memcpy( &key, &mac, sizeof(mac_addr_t) ); + + cl_obj_lock( &p_port->obj ); + + if( p_port->p_local_endpt == NULL ) + { + cl_obj_unlock( &p_port->obj ); + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("No local endpoint.\n") ); + return STATUS_INVALID_PARAMETER; + } + + if( mac.addr[0] == 0 && mac.addr[1] == 0 && mac.addr[2] == 0 && + mac.addr[3] == 0 && mac.addr[4] == 0 && mac.addr[5] == 0 ) + { + p_endpt = p_port->p_local_endpt; + } + else + { + p_item = cl_qmap_get( &p_port->endpt_mgr.mac_endpts, key ); + if( p_item == cl_qmap_end( &p_port->endpt_mgr.mac_endpts ) ) + { + cl_obj_unlock( &p_port->obj ); + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed endpoint lookup.\n") ); + return STATUS_INVALID_PARAMETER; + } + + p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item ); + } + + p_path->service_id = 0; + p_path->dgid = p_endpt->dgid; + p_path->sgid = p_port->p_local_endpt->dgid; + p_path->dlid = p_endpt->dlid; + p_path->slid = p_port->p_local_endpt->dlid; + + ib_member_get_sl_flow_hop( + p_port->ib_mgr.bcast_rec.sl_flow_hop, + &sl, + &flow_lbl, + &hop_limit + ); + + if( p_path->slid == p_path->dlid ) + pkt_life = 0; + else + pkt_life = p_port->ib_mgr.bcast_rec.pkt_life; + + ib_path_rec_init_local( + p_path, + &p_endpt->dgid, + &p_port->p_local_endpt->dgid, + p_endpt->dlid, + p_port->p_local_endpt->dlid, + 1, + p_port->ib_mgr.bcast_rec.pkey, + sl, 0, + IB_PATH_SELECTOR_EXACTLY, p_port->ib_mgr.bcast_rec.mtu, + IB_PATH_SELECTOR_EXACTLY, p_port->ib_mgr.bcast_rec.rate, + IB_PATH_SELECTOR_EXACTLY, pkt_life, + 0 ); + + /* Set global routing information. */ + ib_path_rec_set_hop_flow_raw( p_path, hop_limit, flow_lbl, FALSE ); + p_path->tclass = p_port->ib_mgr.bcast_rec.tclass; + + cl_obj_unlock( &p_port->obj ); + + IPOIB_EXIT( IPOIB_DBG_ENDPT ); + return STATUS_SUCCESS; +} + + +static inline NDIS_STATUS +__endpt_mgr_ref( + IN ipoib_port_t* const p_port, + IN const mac_addr_t mac, + OUT ipoib_endpt_t** const pp_endpt ) +{ + NDIS_STATUS status; + cl_map_item_t *p_item; + uint64_t key; + + PERF_DECLARE( EndptQueue ); + + IPOIB_ENTER( IPOIB_DBG_ENDPT ); + + if( !cl_memcmp( &mac, &p_port->p_adapter->params.conf_mac, sizeof(mac) ) ) + { + /* Discard loopback traffic. */ + IPOIB_PRINT(TRACE_LEVEL_WARNING, IPOIB_DBG_ENDPT, + ("Discarding loopback traffic\n") ); + IPOIB_EXIT( IPOIB_DBG_ENDPT ); + return NDIS_STATUS_NO_ROUTE_TO_DESTINATION; + } + + key = 0; + cl_memcpy( &key, &mac, sizeof(mac_addr_t) ); + + cl_obj_lock( &p_port->obj ); + + IPOIB_PRINT( TRACE_LEVEL_VERBOSE, IPOIB_DBG_ENDPT, + ("Look for :\t MAC: %02X-%02X-%02X-%02X-%02X-%02X\n", + mac.addr[0], mac.addr[1], mac.addr[2], + mac.addr[3], mac.addr[4], mac.addr[5]) ); + + p_item = cl_qmap_get( &p_port->endpt_mgr.mac_endpts, key ); + if( p_item == cl_qmap_end( &p_port->endpt_mgr.mac_endpts ) ) + { + cl_obj_unlock( &p_port->obj ); + IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT, + ("Failed endpoint lookup.\n") ); + return NDIS_STATUS_NO_ROUTE_TO_DESTINATION; + } + + *pp_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item ); + ipoib_endpt_ref( *pp_endpt ); + + cl_obj_unlock( &p_port->obj ); + + cl_perf_start( EndptQueue ); + status = ipoib_endpt_queue( *pp_endpt ); + cl_perf_stop( &p_port->p_adapter->perf, EndptQueue ); + if( status != NDIS_STATUS_SUCCESS ) + *pp_endpt = NULL; + + IPOIB_EXIT( IPOIB_DBG_ENDPT ); + return status; +} + + +static inline NDIS_STATUS +__endpt_mgr_get_gid_qpn( + IN ipoib_port_t* const p_port, + IN const mac_addr_t mac, + OUT ib_gid_t* const p_gid, + OUT UNALIGNED net32_t* const p_qpn ) +{ + UNALIGNED + cl_map_item_t *p_item; + ipoib_endpt_t *p_endpt; + uint64_t key; + + IPOIB_ENTER( IPOIB_DBG_ENDPT ); + + cl_obj_lock( &p_port->obj ); + + key = 0; + cl_memcpy( &key, &mac, sizeof(mac_addr_t) ); + p_item = cl_qmap_get( &p_port->endpt_mgr.mac_endpts, key ); + if( p_item == cl_qmap_end( &p_port->endpt_mgr.mac_endpts ) ) + { + cl_obj_unlock( &p_port->obj ); + IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT, + ("Failed endpoint lookup.\n") ); + return NDIS_STATUS_FAILURE; + } + + p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item ); + + *p_gid = p_endpt->dgid; + *p_qpn = p_endpt->qpn; + + cl_obj_unlock( &p_port->obj ); + + IPOIB_EXIT( IPOIB_DBG_ENDPT ); + return NDIS_STATUS_SUCCESS; +} + + +static inline ipoib_endpt_t* +__endpt_mgr_get_by_gid( + IN ipoib_port_t* const p_port, + IN const ib_gid_t* const p_gid ) +{ + cl_fmap_item_t *p_item; + ipoib_endpt_t *p_endpt; + + IPOIB_ENTER( IPOIB_DBG_ENDPT ); + + p_item = cl_fmap_get( &p_port->endpt_mgr.gid_endpts, p_gid ); + if( p_item == cl_fmap_end( &p_port->endpt_mgr.gid_endpts ) ) + p_endpt = NULL; + else + p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, gid_item ); + + IPOIB_EXIT( IPOIB_DBG_ENDPT ); + return p_endpt; +} + + +static ipoib_endpt_t* +__endpt_mgr_get_by_lid( + IN ipoib_port_t* const p_port, + IN const net16_t lid ) +{ + cl_map_item_t *p_item; + ipoib_endpt_t *p_endpt; + + IPOIB_ENTER( IPOIB_DBG_ENDPT ); + + p_item = cl_qmap_get( &p_port->endpt_mgr.lid_endpts, lid ); + if( p_item == cl_qmap_end( &p_port->endpt_mgr.lid_endpts ) ) + p_endpt = NULL; + else + p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, lid_item ); + + IPOIB_EXIT( IPOIB_DBG_ENDPT ); + return p_endpt; +} + + +inline ib_api_status_t +__endpt_mgr_insert_locked( + IN ipoib_port_t* const p_port, + IN const mac_addr_t mac, + IN ipoib_endpt_t* const p_endpt ) +{ + ib_api_status_t status; + + IPOIB_ENTER( IPOIB_DBG_ENDPT ); + + IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT, + ("insert :\t MAC: %02X-%02X-%02X-%02X-%02X-%02X\n", + mac.addr[0], mac.addr[1], mac.addr[2], + mac.addr[3], mac.addr[4], mac.addr[5]) ); + + cl_obj_lock( &p_port->obj ); + while( p_port->endpt_rdr ) + { + cl_obj_unlock( &p_port->obj ); + cl_obj_lock( &p_port->obj ); + } + /* __endpt_mgr_insert expects *one* reference to be held when being called. */ + cl_atomic_inc( &p_port->endpt_rdr ); + status= __endpt_mgr_insert( p_port, mac, p_endpt ); + cl_atomic_dec( &p_port->endpt_rdr ); + cl_obj_unlock( &p_port->obj ); + + return status; +} + + +inline ib_api_status_t +__endpt_mgr_insert( + IN ipoib_port_t* const p_port, + IN const mac_addr_t mac, + IN ipoib_endpt_t* const p_endpt ) +{ + uint64_t key; + cl_status_t cl_status; + cl_map_item_t *p_qitem; + cl_fmap_item_t *p_fitem; + + IPOIB_ENTER( IPOIB_DBG_ENDPT ); + + /* Wait for all accesses to the map to complete. */ + while( p_port->endpt_rdr > 1 ) + ; + + /* Link the endpoint to the port. */ + cl_status = cl_obj_insert_rel_parent_locked( + &p_endpt->rel, &p_port->obj, &p_endpt->obj ); + + if( cl_status != CL_SUCCESS ) + { + cl_obj_destroy( &p_endpt->obj ); + return IB_INVALID_STATE; + } + +#if DBG + cl_atomic_inc( &p_port->ref[ref_endpt_track] ); + IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OBJ, + ("ref type %d ref_cnt %d\n", ref_endpt_track, p_port->obj.ref_cnt) ); +#endif + + p_endpt->mac = mac; + key = 0; + cl_memcpy( &key, &mac, sizeof(mac_addr_t) ); + p_qitem = cl_qmap_insert( + &p_port->endpt_mgr.mac_endpts, key, &p_endpt->mac_item ); + CL_ASSERT( p_qitem == &p_endpt->mac_item ); + p_fitem = cl_fmap_insert( + &p_port->endpt_mgr.gid_endpts, &p_endpt->dgid, &p_endpt->gid_item ); + CL_ASSERT( p_fitem == &p_endpt->gid_item ); + if( p_endpt->dlid ) + { + p_qitem = cl_qmap_insert( + &p_port->endpt_mgr.lid_endpts, p_endpt->dlid, &p_endpt->lid_item ); + CL_ASSERT( p_qitem == &p_endpt->lid_item ); + if (p_qitem != &p_endpt->lid_item) { + // Since we failed to insert into the list, make sure it is not removed + p_endpt->dlid =0; + } + } + + IPOIB_EXIT( IPOIB_DBG_ENDPT ); + return IB_SUCCESS; +} + + +static ib_api_status_t +__endpt_mgr_add_bcast( + IN ipoib_port_t* const p_port, + IN ib_mcast_rec_t *p_mcast_rec ) +{ + ib_api_status_t status; + ipoib_endpt_t *p_endpt; + mac_addr_t bcast_mac; + + IPOIB_ENTER( IPOIB_DBG_INIT ); + + /* + * Cache the broadcast group properties for creating future mcast groups. + */ + p_port->ib_mgr.bcast_rec = *p_mcast_rec->p_member_rec; + + /* Allocate the broadcast endpoint. */ + p_endpt = ipoib_endpt_create( &p_mcast_rec->p_member_rec->mgid, + 0 , CL_HTON32(0x00FFFFFF) ); + if( !p_endpt ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ipoib_endpt_create failed.\n") ); + return IB_INSUFFICIENT_RESOURCES; + } + /* set reference to transport to be used while is not attached to the port */ + p_endpt->is_mcast_listener = TRUE; + p_endpt->p_ifc = p_port->p_adapter->p_ifc; + status = ipoib_endpt_set_mcast( p_endpt, p_port->ib_mgr.h_pd, + p_port->port_num, p_mcast_rec ); + if( status != IB_SUCCESS ) + { + cl_obj_destroy( &p_endpt->obj ); + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ipoib_create_mcast_endpt returned %s\n", + p_port->p_adapter->p_ifc->get_err_str( status )) ); + return status; + } + + /* Add the broadcast endpoint to the endpoint map. */ + cl_memset( &bcast_mac, 0xFF, sizeof(bcast_mac) ); + status = __endpt_mgr_insert_locked( p_port, bcast_mac, p_endpt ); + + IPOIB_EXIT( IPOIB_DBG_INIT ); + return status; +} + + +void +ipoib_port_remove_endpt( + IN ipoib_port_t* const p_port, + IN const mac_addr_t mac ) +{ + cl_map_item_t *p_item; + //TODO CM +// cl_fmap_item_t *p_fmap_item; + ipoib_endpt_t *p_endpt; + uint64_t key; + + IPOIB_ENTER( IPOIB_DBG_ENDPT ); + + key = 0; + cl_memcpy( &key, &mac, sizeof(mac_addr_t) ); + + /* Remove the endpoint from the maps so further requests don't find it. */ + cl_obj_lock( &p_port->obj ); + /* Wait for all readers to finish */ + while( p_port->endpt_rdr ) + ; + p_item = cl_qmap_remove( &p_port->endpt_mgr.mac_endpts, key ); + /* + * Dereference the endpoint. If the ref count goes to zero, it + * will get freed. + */ + if( p_item != cl_qmap_end( &p_port->endpt_mgr.mac_endpts ) ) + { + p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item ); + /* + * The enpoints are *ALWAYS* in both the MAC and GID maps. They are only + * in the LID map if the GID has the same subnet prefix as us. + */ + cl_fmap_remove_item( + &p_port->endpt_mgr.gid_endpts, &p_endpt->gid_item ); +#if 0 + if( p_port->p_adapter->params.cm_enabled ) + { + p_fmap_item = cl_fmap_get( &p_port->endpt_mgr.conn_endpts, &p_endpt->dgid ); + + if( p_fmap_item != cl_fmap_end( &p_port->endpt_mgr.conn_endpts ) ) + { + cl_fmap_remove_item( &p_port->endpt_mgr.conn_endpts, + &p_endpt->conn_item ); + } + } +#endif + + if( p_endpt->dlid ) + { + cl_qmap_remove_item( + &p_port->endpt_mgr.lid_endpts, &p_endpt->lid_item ); + } + + cl_obj_unlock( &p_port->obj ); + //TODO CM + //endpt_cm_destroy_conn( p_port, p_endpt ); + +#if DBG + cl_atomic_dec( &p_port->ref[ref_endpt_track] ); + IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT, + ("ref type %d ref_cnt %d\n", ref_endpt_track, p_port->obj.ref_cnt) ); +#endif + + } + else + { + cl_obj_unlock( &p_port->obj ); + } + + IPOIB_EXIT( IPOIB_DBG_ENDPT ); +} + +/* + * The sequence for port up is as follows: + * 1. The port goes active. This allows the adapter to send SA queries + * and join the broadcast group (and other groups). + * + * 2. The adapter sends an SA query for the broadcast group. + * + * 3. Upon completion of the query, the adapter joins the broadcast group. + */ + + +/* + * Query the SA for the broadcast group. + */ +void +ipoib_port_up( + IN ipoib_port_t* const p_port, + IN const ib_pnp_port_rec_t* const p_pnp_rec ) +{ + ib_port_info_t *p_port_info; + ib_mad_t *mad_in = NULL; + ib_mad_t *mad_out = NULL; + ib_api_status_t status = IB_INSUFFICIENT_MEMORY; + static int cnt = 0; + + IPOIB_ENTER( IPOIB_DBG_INIT ); + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_INIT, + ("[%d] Entering port_up.\n", ++cnt) ); + + cl_obj_lock( &p_port->obj ); + if ( p_port->state == IB_QPS_INIT ) + { + cl_obj_unlock( &p_port->obj ); + status = IB_SUCCESS; + IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, + ("p_port->state = %d - Aborting.\n", p_port->state) ); + goto up_done; + } + else if ( p_port->state == IB_QPS_RTS ) + { + cl_obj_unlock( &p_port->obj ); + cl_obj_lock( &p_port->p_adapter->obj ); + if( p_port->p_adapter->state == IB_PNP_PORT_INIT ) + { + p_port->p_adapter->state = IB_PNP_PORT_ACTIVE; + } + cl_obj_unlock( &p_port->p_adapter->obj ); + status = IB_SUCCESS; + IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, + ("Port init is done. p_port->state = %d.\n", p_port->state ) ); + goto up_done; + } + p_port->state = IB_QPS_INIT; + cl_obj_unlock( &p_port->obj ); + + + /* Wait for all work requests to get flushed. */ + while( p_port->recv_mgr.depth || p_port->send_mgr.depth ) + cl_thread_suspend( 0 ); + + KeResetEvent( &p_port->sa_event ); + + mad_out = (ib_mad_t *) (ib_mad_t*)cl_zalloc(256); + if(! mad_out) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("failed to allocate mad mad_out\n")); + goto up_done; + } + mad_in = (ib_mad_t *) cl_zalloc(256); + if(! mad_in) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("failed to allocate mad mad_in\n")); + goto up_done; + } + + mad_in->attr_id = IB_MAD_ATTR_PORT_INFO; + mad_in->method = IB_MAD_METHOD_GET; + mad_in->base_ver = 1; + mad_in->class_ver =1; + mad_in->mgmt_class = IB_MCLASS_SUBN_LID; + + status = p_port->p_adapter->p_ifc->local_mad( + p_port->ib_mgr.h_ca ,p_port->port_num ,mad_in ,mad_out); + + if( status != IB_SUCCESS ) + { + ipoib_set_inactive( p_port->p_adapter ); + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ib_local_mad returned %s\n", + p_port->p_adapter->p_ifc->get_err_str( status )) ); + goto up_done; + } + + p_port_info = (ib_port_info_t*)(((ib_smp_t*)mad_out)->data); + p_port->base_lid = p_pnp_rec->p_port_attr->lid; + IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, + ("Received port info: link width = %d.\n", + p_port_info->link_width_active) ); + p_port->ib_mgr.rate = + ib_port_info_compute_rate( p_port_info ); + + ipoib_set_rate( p_port->p_adapter, + p_port_info->link_width_active, + ib_port_info_get_link_speed_active( p_port_info ) ); + + status = __port_get_bcast( p_port ); + if (status != IB_SUCCESS) + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + (" __port_get_bcast returned %s\n",p_port->p_adapter->p_ifc->get_err_str( status ))); + +up_done: + if( status != IB_SUCCESS ) + { + if( status != IB_CANCELED ) + { + ipoib_set_inactive( p_port->p_adapter ); + __endpt_mgr_reset_all( p_port ); + } + ASSERT(p_port->state == IB_QPS_INIT || p_port->state == IB_QPS_ERROR); + p_port->state = IB_QPS_ERROR; + KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE ); + } + + if(mad_out) + cl_free(mad_out); + if(mad_in) + cl_free(mad_in); + + IPOIB_EXIT( IPOIB_DBG_INIT ); +} + + +static ib_api_status_t +__endpt_mgr_add_local( + IN ipoib_port_t* const p_port, + IN ib_port_info_t* const p_port_info ) +{ + ib_api_status_t status; + ib_gid_t gid; + ipoib_endpt_t *p_endpt; + ib_av_attr_t av_attr; + + IPOIB_ENTER( IPOIB_DBG_INIT ); + + ib_gid_set_default( &gid, p_port->p_adapter->guids.port_guid.guid ); + p_endpt = ipoib_endpt_create( + &gid, p_port_info->base_lid, p_port->ib_mgr.qpn ); + if( !p_endpt ) + { + p_port->p_adapter->hung = TRUE; + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed to create local endpt\n") ); + return IB_INSUFFICIENT_MEMORY; + } + + cl_memclr( &av_attr, sizeof(ib_av_attr_t) ); + av_attr.port_num = p_port->port_num; + av_attr.sl = 0; + IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT, + (" av_attr.dlid = p_port_info->base_lid = %d\n", cl_ntoh16( p_port_info->base_lid ) )); + av_attr.dlid = p_port_info->base_lid; + av_attr.static_rate = p_port->ib_mgr.rate; + av_attr.path_bits = 0; + status = p_port->p_adapter->p_ifc->create_av( + p_port->ib_mgr.h_pd, &av_attr, &p_endpt->h_av ); + if( status != IB_SUCCESS ) + { + cl_obj_destroy( &p_endpt->obj ); + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ib_create_av for local endpoint returned %s\n", + p_port->p_adapter->p_ifc->get_err_str( status )) ); + return status; + } + + /* __endpt_mgr_insert expects *one* reference to be held. */ + cl_atomic_inc( &p_port->endpt_rdr ); + status = __endpt_mgr_insert( p_port, p_port->p_adapter->params.conf_mac, p_endpt ); + cl_atomic_dec( &p_port->endpt_rdr ); + if( status != IB_SUCCESS ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("__endpt_mgr_insert for local endpoint returned %s\n", + p_port->p_adapter->p_ifc->get_err_str( status )) ); + return status; + } + + p_port->p_local_endpt = p_endpt; + + IPOIB_EXIT( IPOIB_DBG_INIT ); + return status; +} + + + + +static ib_api_status_t +__port_get_bcast( + IN ipoib_port_t* const p_port ) +{ + ib_api_status_t status; + ib_query_req_t query; + ib_user_query_t info; + ib_member_rec_t member_rec; + + IPOIB_ENTER( IPOIB_DBG_INIT ); + + info.method = IB_MAD_METHOD_GETTABLE; + info.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD; + info.attr_size = sizeof(ib_member_rec_t); + info.comp_mask = IB_MCR_COMPMASK_MGID; + info.p_attr = &member_rec; + + /* Query requires only the MGID. */ + cl_memclr( &member_rec, sizeof(ib_member_rec_t) ); + member_rec.mgid = bcast_mgid_template; + + member_rec.mgid.raw[4] = (uint8_t) (p_port->p_adapter->guids.port_guid.pkey >> 8) ; + member_rec.mgid.raw[5] = (uint8_t) p_port->p_adapter->guids.port_guid.pkey; + member_rec.pkey = cl_hton16(p_port->p_adapter->guids.port_guid.pkey); + cl_memclr( &query, sizeof(ib_query_req_t) ); + query.query_type = IB_QUERY_USER_DEFINED; + query.p_query_input = &info; + query.port_guid = p_port->p_adapter->guids.port_guid.guid; + query.timeout_ms = p_port->p_adapter->params.sa_timeout; + query.retry_cnt = p_port->p_adapter->params.sa_retry_cnt; + query.query_context = p_port; + query.pfn_query_cb = __bcast_get_cb; + + /* reference the object for the multicast query. */ + ipoib_port_ref( p_port, ref_get_bcast ); + + status = p_port->p_adapter->p_ifc->query( + p_port->p_adapter->h_al, &query, &p_port->ib_mgr.h_query ); + if( status != IB_SUCCESS ) + { + ipoib_port_deref( p_port, ref_get_bcast ); + ASSERT(FALSE); + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ib_query returned %s\n", + p_port->p_adapter->p_ifc->get_err_str( status )) ); + } + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ib_query returned SUCCESS\n")); + IPOIB_EXIT( IPOIB_DBG_INIT ); + return status; +} + + +/* Callback for the MCMemberRecord Get query for the IPv4 broadcast group. */ +static void +__bcast_get_cb( + IN ib_query_rec_t *p_query_rec ) +{ + ipoib_port_t *p_port; + ib_member_rec_t *p_mc_req; + ib_api_status_t status; + + IPOIB_ENTER( IPOIB_DBG_INIT ); + + p_port = (ipoib_port_t*)p_query_rec->query_context; + + cl_obj_lock( &p_port->obj ); + p_port->ib_mgr.h_query = NULL; + + CL_ASSERT(p_port->state == IB_QPS_INIT || p_port->state == IB_QPS_ERROR); + if( p_port->state != IB_QPS_INIT ) + { + status = IB_CANCELED; + goto done; + } + + status = p_query_rec->status; + + IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, + ("status of request %s\n", + p_port->p_adapter->p_ifc->get_err_str( status )) ); + + switch( status ) + { + case IB_SUCCESS: + if( p_query_rec->result_cnt ) + { + p_mc_req = (ib_member_rec_t*) + ib_get_query_result( p_query_rec->p_result_mad, 0 ); + + /* Join the broadcast group. */ + status = __port_join_bcast( p_port, p_mc_req ); + break; + } + /* Fall through. */ + + case IB_REMOTE_ERROR: + /* SA failed the query. Broadcast group doesn't exist, create it. */ + status = __port_create_bcast( p_port ); + break; + + case IB_CANCELED: + IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, + ("Instance destroying - Aborting.\n") ); + break; + + default: + NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, + EVENT_IPOIB_BCAST_GET, 1, p_query_rec->status ); + } +done: + cl_obj_unlock( &p_port->obj ); + + if( status != IB_SUCCESS ) + { + if( status != IB_CANCELED ) + { + ipoib_set_inactive( p_port->p_adapter ); + __endpt_mgr_reset_all( p_port ); + } + p_port->state = IB_QPS_ERROR; + KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE ); + } + + /* Return the response MAD to AL. */ + if( p_query_rec->p_result_mad ) + p_port->p_adapter->p_ifc->put_mad( p_query_rec->p_result_mad ); + + /* Release the reference taken when issuing the member record query. */ + ipoib_port_deref( p_port, ref_bcast_get_cb ); + + IPOIB_EXIT( IPOIB_DBG_INIT ); +} + + +static ib_api_status_t +__port_join_bcast( + IN ipoib_port_t* const p_port, + IN ib_member_rec_t* const p_member_rec ) +{ + ib_api_status_t status; + ib_mcast_req_t mcast_req; + + IPOIB_ENTER( IPOIB_DBG_INIT ); + + /* Check that the rate is realizable for our port. */ + if( p_port->ib_mgr.rate < (p_member_rec->rate & 0x3F) && + (g_ipoib.bypass_check_bcast_rate == 0)) + { + /* + * The MC group rate is higher than our port's rate. Log an error + * and stop. A port transition will drive the retry. + */ + IPOIB_PRINT(TRACE_LEVEL_WARNING, IPOIB_DBG_INIT, + ("Unrealizable join due to rate mismatch.\n") ); + NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, + EVENT_IPOIB_BCAST_RATE, 2, + (uint32_t)(p_member_rec->rate & 0x3F), + (uint32_t)p_port->ib_mgr.rate ); + return IB_ERROR; + } + + /* Join the broadcast group. */ + cl_memclr( &mcast_req, sizeof(mcast_req) ); + /* Copy the results of the Get to use as parameters. */ + mcast_req.member_rec = *p_member_rec; + /* We specify our port GID for the join operation. */ + mcast_req.member_rec.port_gid.unicast.prefix = IB_DEFAULT_SUBNET_PREFIX; + mcast_req.member_rec.port_gid.unicast.interface_id = + p_port->p_adapter->guids.port_guid.guid; + + mcast_req.mcast_context = p_port; + mcast_req.pfn_mcast_cb = __bcast_cb; + mcast_req.timeout_ms = p_port->p_adapter->params.sa_timeout; + mcast_req.retry_cnt = p_port->p_adapter->params.sa_retry_cnt; + mcast_req.port_guid = p_port->p_adapter->guids.port_guid.guid; + mcast_req.pkey_index = p_port->pkey_index; + + if( ib_member_get_state( mcast_req.member_rec.scope_state ) != + IB_MC_REC_STATE_FULL_MEMBER ) + { + IPOIB_PRINT(TRACE_LEVEL_WARNING, IPOIB_DBG_INIT, + ("Incorrect MC member rec join state in query response.\n") ); + ib_member_set_state( &mcast_req.member_rec.scope_state, + IB_MC_REC_STATE_FULL_MEMBER ); + } + + /* reference the object for the multicast join request. */ + ipoib_port_ref( p_port, ref_join_bcast ); + + status = p_port->p_adapter->p_ifc->join_mcast( + p_port->ib_mgr.h_qp, &mcast_req ); + if( status != IB_SUCCESS ) + { + ipoib_port_deref( p_port, ref_bcast_join_failed ); + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ib_join_mcast returned %s\n", + p_port->p_adapter->p_ifc->get_err_str( status )) ); + } + IPOIB_EXIT( IPOIB_DBG_INIT ); + return status; +} + + +static ib_api_status_t +__port_create_bcast( + IN ipoib_port_t* const p_port ) +{ + ib_api_status_t status; + ib_mcast_req_t mcast_req; + + IPOIB_ENTER( IPOIB_DBG_INIT ); + + /* Join the broadcast group. */ + cl_memclr( &mcast_req, sizeof(mcast_req) ); + mcast_req.create = TRUE; + /* + * Create requires pkey, qkey, SL, flow label, traffic class, joing state + * and port GID. + * + * We specify the MGID since we don't want the SA to generate it for us. + */ + mcast_req.member_rec.mgid = bcast_mgid_template; + mcast_req.member_rec.mgid.raw[4] = (uint8_t) (p_port->p_adapter->guids.port_guid.pkey >> 8); + mcast_req.member_rec.mgid.raw[5] = (uint8_t) p_port->p_adapter->guids.port_guid.pkey; + ib_gid_set_default( &mcast_req.member_rec.port_gid, + p_port->p_adapter->guids.port_guid.guid ); + /* + * IPOIB spec requires that the QKEY have the MSb set so that the QKEY + * from the QP is used rather than the QKEY in the send WR. + */ + mcast_req.member_rec.qkey = + (uint32_t)(uintn_t)p_port | IB_QP_PRIVILEGED_Q_KEY; + mcast_req.member_rec.mtu = + (IB_PATH_SELECTOR_EXACTLY << 6) | IB_MTU_LEN_2048; + + mcast_req.member_rec.pkey = cl_hton16(p_port->p_adapter->guids.port_guid.pkey); + + mcast_req.member_rec.sl_flow_hop = ib_member_set_sl_flow_hop( 0, 0, 0 ); + mcast_req.member_rec.scope_state = + ib_member_set_scope_state( 2, IB_MC_REC_STATE_FULL_MEMBER ); + + mcast_req.mcast_context = p_port; + mcast_req.pfn_mcast_cb = __bcast_cb; + mcast_req.timeout_ms = p_port->p_adapter->params.sa_timeout; + mcast_req.retry_cnt = p_port->p_adapter->params.sa_retry_cnt; + mcast_req.port_guid = p_port->p_adapter->guids.port_guid.guid; + mcast_req.pkey_index = p_port->pkey_index; + + /* reference the object for the multicast join request. */ + ipoib_port_ref( p_port, ref_join_bcast ); + + status = p_port->p_adapter->p_ifc->join_mcast( p_port->ib_mgr.h_qp, &mcast_req ); + if( status != IB_SUCCESS ) + { + ipoib_port_deref( p_port, ref_bcast_create_failed ); + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ib_join_mcast returned %s\n", + p_port->p_adapter->p_ifc->get_err_str( status )) ); + } + IPOIB_EXIT( IPOIB_DBG_INIT ); + return status; +} + + +void +ipoib_port_down( + IN ipoib_port_t* const p_port ) +{ + ib_api_status_t status; + ib_qp_mod_t qp_mod; + + IPOIB_ENTER( IPOIB_DBG_INIT ); + + /* + * Mark our state. This causes all callbacks to abort. + * Note that we hold the receive lock so that we synchronize + * with reposting. We must take the receive lock before the + * object lock since that is the order taken when reposting. + */ + cl_spinlock_acquire( &p_port->recv_lock ); + cl_obj_lock( &p_port->obj ); + p_port->state = IB_QPS_ERROR; + + NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, + EVENT_IPOIB_PORT_DOWN, 0 ); + + if( p_port->ib_mgr.h_query ) + { + p_port->p_adapter->p_ifc->cancel_query( + p_port->p_adapter->h_al, p_port->ib_mgr.h_query ); + p_port->ib_mgr.h_query = NULL; + } + cl_obj_unlock( &p_port->obj ); + cl_spinlock_release( &p_port->recv_lock ); + + KeWaitForSingleObject( + &p_port->sa_event, Executive, KernelMode, FALSE, NULL ); + + /* garbage collector timer is not needed when link is down */ + KeCancelTimer(&p_port->gc_timer); + KeFlushQueuedDpcs(); + + /* + * Put the QP in the error state. This removes the need to + * synchronize with send/receive callbacks. + */ + CL_ASSERT( p_port->ib_mgr.h_qp ); + cl_memclr( &qp_mod, sizeof(ib_qp_mod_t) ); + qp_mod.req_state = IB_QPS_ERROR; + status = p_port->p_adapter->p_ifc->modify_qp( p_port->ib_mgr.h_qp, &qp_mod ); + if( status != IB_SUCCESS ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ib_modify_qp to error state returned %s.\n", + p_port->p_adapter->p_ifc->get_err_str( status )) ); + p_port->p_adapter->hung = TRUE; + return; + } + + KeResetEvent(&p_port->leave_mcast_event); + + /* Reset all endpoints so we don't flush our ARP cache. */ + __endpt_mgr_reset_all( p_port ); + + KeWaitForSingleObject( + &p_port->leave_mcast_event, Executive, KernelMode, FALSE, NULL ); + + __pending_list_destroy(p_port); + + cl_obj_lock( &p_port->p_adapter->obj ); + ipoib_dereg_addrs( p_port->p_adapter ); + cl_obj_unlock( &p_port->p_adapter->obj ); + + IPOIB_EXIT( IPOIB_DBG_INIT ); +} + + +static void +__bcast_cb( + IN ib_mcast_rec_t *p_mcast_rec ) +{ + ipoib_port_t *p_port; + ib_api_status_t status; + LARGE_INTEGER gc_due_time; + + IPOIB_ENTER( IPOIB_DBG_INIT ); + + p_port = (ipoib_port_t*)p_mcast_rec->mcast_context; + + cl_obj_lock( &p_port->obj ); + + ASSERT(p_port->state == IB_QPS_INIT || p_port->state == IB_QPS_ERROR); + if( p_port->state != IB_QPS_INIT ) + { + cl_obj_unlock( &p_port->obj ); + if( p_mcast_rec->status == IB_SUCCESS ) + { + ipoib_port_ref(p_port, ref_leave_mcast); + p_port->p_adapter->p_ifc->leave_mcast( p_mcast_rec->h_mcast, __leave_error_mcast_cb ); + } + KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE ); + ipoib_port_deref( p_port, ref_bcast_inv_state ); + IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, + ("Invalid state - Aborting.\n") ); + return; + } + status = p_mcast_rec->status; + if( status != IB_SUCCESS ) + { + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Multicast join for broadcast group returned %s.\n", + p_port->p_adapter->p_ifc->get_err_str( p_mcast_rec->status )) ); + if( status == IB_REMOTE_ERROR ) + { + /* + * Either: + * - the join failed because the group no longer exists + * - the create failed because the group already exists + * + * Kick off a new Get query to the SA to restart the join process + * from the top. Note that as an optimization, it would be + * possible to distinguish between the join and the create. + * If the join fails, try the create. If the create fails, start + * over with the Get. + */ + /* TODO: Assert is a place holder. Can we ever get here if the + state isn't IB_PNP_PORT_ADD or PORT_DOWN or PORT_INIT? */ + CL_ASSERT( p_port->p_adapter->state == IB_PNP_PORT_ADD || + p_port->p_adapter->state == IB_PNP_PORT_DOWN || + p_port->p_adapter->state == IB_PNP_PORT_INIT ); + if(++p_port->bc_join_retry_cnt < p_port->p_adapter->params.bc_join_retry) + { + status = __port_get_bcast( p_port ); + } + else + { + NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, + EVENT_IPOIB_BCAST_JOIN, 1, p_mcast_rec->status ); + p_port->bc_join_retry_cnt = 0; + } + } + else + { + NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, + EVENT_IPOIB_BCAST_JOIN, 1, p_mcast_rec->status ); + } + + cl_obj_unlock( &p_port->obj ); + if( status != IB_SUCCESS ) + { + ipoib_set_inactive( p_port->p_adapter ); + __endpt_mgr_reset_all( p_port ); + ASSERT(p_port->state == IB_QPS_INIT || p_port->state == IB_QPS_ERROR); + p_port->state = IB_QPS_ERROR; + KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE ); + } + ipoib_port_deref( p_port, ref_bcast_req_failed ); + IPOIB_EXIT( IPOIB_DBG_INIT ); + return; + } + p_port->bc_join_retry_cnt = 0; + + while( p_port->endpt_rdr ) + { + cl_obj_unlock( &p_port->obj ); + cl_obj_lock( &p_port->obj ); + } + + if( !p_port->p_local_endpt ) + { + ib_port_info_t port_info; + cl_memclr(&port_info, sizeof(port_info)); + port_info.base_lid = p_port->base_lid; + status = __endpt_mgr_add_local( p_port, &port_info ); + if( status != IB_SUCCESS ) + { + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("__endpt_mgr_add_local returned %s\n", + p_port->p_adapter->p_ifc->get_err_str( status )) ); + cl_obj_unlock( &p_port->obj ); + goto err; + } + } + + cl_obj_unlock( &p_port->obj ); + + status = __endpt_mgr_add_bcast( p_port, p_mcast_rec ); + if( status != IB_SUCCESS ) + { + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("__endpt_mgr_add_bcast returned %s\n", + p_port->p_adapter->p_ifc->get_err_str( status )) ); + ipoib_port_ref(p_port, ref_leave_mcast); + status = p_port->p_adapter->p_ifc->leave_mcast( p_mcast_rec->h_mcast, __leave_error_mcast_cb ); + CL_ASSERT( status == IB_SUCCESS ); + goto err; + } + + /* Get the QP ready for action. */ + status = __ib_mgr_activate( p_port ); + if( status != IB_SUCCESS ) + { + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("__ib_mgr_activate returned %s\n", + p_port->p_adapter->p_ifc->get_err_str( status )) ); + +err: + /* Flag the adapter as hung. */ + p_port->p_adapter->hung = TRUE; + ASSERT(p_port->state == IB_QPS_INIT || p_port->state == IB_QPS_ERROR); + p_port->state = IB_QPS_ERROR; + KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE ); + ipoib_port_deref( p_port, ref_bcast_error ); + IPOIB_EXIT( IPOIB_DBG_INIT ); + return; + } + + cl_obj_lock( &p_port->obj ); + /* Only change the state if we're still in INIT. */ + ASSERT( p_port->state == IB_QPS_INIT || p_port->state == IB_QPS_ERROR); + if (p_port->state == IB_QPS_INIT) { + p_port->state = IB_QPS_RTS; + } + cl_obj_unlock( &p_port->obj ); + + /* Prepost receives. */ + cl_spinlock_acquire( &p_port->recv_lock ); + __recv_mgr_repost( p_port ); + cl_spinlock_release( &p_port->recv_lock ); + + /* Notify the adapter that we now have an active connection. */ + status = ipoib_set_active( p_port->p_adapter ); + if( status != IB_SUCCESS ) + { + ib_qp_mod_t qp_mod; + ipoib_set_inactive( p_port->p_adapter ); + KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE ); + IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, + ("ipoib_set_active returned %s.\n",p_port->p_adapter->p_ifc->get_err_str( status ))); + cl_spinlock_acquire( &p_port->recv_lock ); + cl_obj_lock( &p_port->obj ); + p_port->state = IB_QPS_ERROR; + if( p_port->ib_mgr.h_query ) + { + p_port->p_adapter->p_ifc->cancel_query( + p_port->p_adapter->h_al, p_port->ib_mgr.h_query ); + p_port->ib_mgr.h_query = NULL; + } + cl_obj_unlock( &p_port->obj ); + cl_spinlock_release( &p_port->recv_lock ); + + CL_ASSERT( p_port->ib_mgr.h_qp ); + cl_memclr( &qp_mod, sizeof(ib_qp_mod_t) ); + qp_mod.req_state = IB_QPS_ERROR; + status = p_port->p_adapter->p_ifc->modify_qp( p_port->ib_mgr.h_qp, &qp_mod ); + __endpt_mgr_reset_all( p_port ); + + ipoib_port_deref( p_port, ref_join_bcast ); + return; + } +#if 0 //CM + if( p_port->p_adapter->params.cm_enabled && + !p_port->p_local_endpt->conn.h_cm_listen ) + { + if( ipoib_port_listen( p_port ) != IB_SUCCESS ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Port CM Listen failed\n" ) ); + /*keep going with UD only */ + p_port->p_adapter->params.cm_enabled = FALSE; + + NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter, + EVENT_IPOIB_CONNECTED_MODE_ERR, 1, 0xbadc0de3 ); + } + } +#endif + /* garbage collector timer is needed when link is active */ + gc_due_time.QuadPart = -(int64_t)(((uint64_t)p_port->p_adapter->params.mc_leave_rescan * 2000000) * 10); + KeSetTimerEx(&p_port->gc_timer,gc_due_time, + (LONG)p_port->p_adapter->params.mc_leave_rescan*1000,&p_port->gc_dpc); + + KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE ); + ipoib_port_deref( p_port, ref_join_bcast ); + IPOIB_EXIT( IPOIB_DBG_INIT ); +} + + +static void +__qp_event( + IN ib_async_event_rec_t *p_event_rec ) +{ + UNUSED_PARAM( p_event_rec ); + CL_ASSERT( p_event_rec->context ); + ((ipoib_port_t*)p_event_rec->context)->p_adapter->hung = TRUE; +} + + +static void +__cq_event( + IN ib_async_event_rec_t *p_event_rec ) +{ + UNUSED_PARAM( p_event_rec ); + CL_ASSERT( p_event_rec->context ); + ((ipoib_port_t*)p_event_rec->context)->p_adapter->hung = TRUE; +} + + +static ib_api_status_t +__ib_mgr_activate( + IN ipoib_port_t* const p_port ) +{ + ib_api_status_t status; + ib_dgrm_info_t dgrm_info; + ib_qp_mod_t qp_mod; + + IPOIB_ENTER( IPOIB_DBG_INIT ); + /* + * Move the QP to RESET. This allows us to reclaim any + * unflushed receives. + */ + cl_memclr( &qp_mod, sizeof(ib_qp_mod_t) ); + qp_mod.req_state = IB_QPS_RESET; + status = p_port->p_adapter->p_ifc->modify_qp( p_port->ib_mgr.h_qp, &qp_mod ); + if( status != IB_SUCCESS ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ib_modify_qp returned %s\n", + p_port->p_adapter->p_ifc->get_err_str( status )) ); + return status; + } + + /* Move the QP to RTS. */ + dgrm_info.port_guid = p_port->p_adapter->guids.port_guid.guid; + dgrm_info.qkey = p_port->ib_mgr.bcast_rec.qkey; + dgrm_info.pkey_index = p_port->pkey_index; + status = p_port->p_adapter->p_ifc->init_dgrm_svc( p_port->ib_mgr.h_qp, &dgrm_info ); + if( status != IB_SUCCESS ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ib_init_dgrm_svc returned %s\n", + p_port->p_adapter->p_ifc->get_err_str( status )) ); + return status; + } + + /* Rearm the CQs. */ + status = p_port->p_adapter->p_ifc->rearm_cq( p_port->ib_mgr.h_recv_cq, FALSE ); + if( status != IB_SUCCESS ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ib_rearm_cq for recv returned %s\n", + p_port->p_adapter->p_ifc->get_err_str( status )) ); + return status; + } + status = p_port->p_adapter->p_ifc->rearm_cq( p_port->ib_mgr.h_send_cq, FALSE ); + if( status != IB_SUCCESS ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ib_rearm_cq for send returned %s\n", + p_port->p_adapter->p_ifc->get_err_str( status )) ); + return status; + } + + IPOIB_EXIT( IPOIB_DBG_INIT ); + return IB_SUCCESS; +} + + +/* Transition to a passive level thread. */ +ib_api_status_t +ipoib_port_join_mcast( + IN ipoib_port_t* const p_port, + IN const mac_addr_t mac, + IN const uint8_t state) +{ + ib_api_status_t status; + ib_mcast_req_t mcast_req; + ipoib_endpt_t *p_endpt; + + IPOIB_ENTER( IPOIB_DBG_MCAST ); + + switch( __endpt_mgr_ref( p_port, mac, &p_endpt ) ) + { + case NDIS_STATUS_NO_ROUTE_TO_DESTINATION: + break; + + case NDIS_STATUS_SUCCESS: + ipoib_endpt_deref( p_endpt ); + /* Fall through */ + + case NDIS_STATUS_PENDING: + return IB_SUCCESS; + } + + /* + * Issue the mcast request, using the parameters of the broadcast group. + * This allows us to do a create request that should always succeed since + * the required parameters are known. + */ + cl_memclr( &mcast_req, sizeof(mcast_req) ); + mcast_req.create = TRUE; + + /* Copy the settings from the broadcast group. */ + mcast_req.member_rec = p_port->ib_mgr.bcast_rec; + /* Clear fields that aren't specified in the join */ + mcast_req.member_rec.mlid = 0; + ib_member_set_state( &mcast_req.member_rec.scope_state,state); + + if( (mac.addr[0] == 1) && (mac.addr[2] == 0x5E )) + { + /* + * Update the address portion of the MGID with the 28 lower bits of the + * IP address. Since we're given a MAC address, we are using + * 24 lower bits of that network-byte-ordered value (assuming MSb + * is zero) and 4 lsb bits of the first byte of IP address. + */ + mcast_req.member_rec.mgid.raw[12] = mac.addr[1]; + mcast_req.member_rec.mgid.raw[13] = mac.addr[3]; + mcast_req.member_rec.mgid.raw[14] = mac.addr[4]; + mcast_req.member_rec.mgid.raw[15] = mac.addr[5]; + } + else + { + /* Handle non IP mutlicast MAC addresses. */ + /* Update the signature to use the lower 2 bytes of the OpenIB OUI. */ + mcast_req.member_rec.mgid.raw[2] = 0x14; + mcast_req.member_rec.mgid.raw[3] = 0x05; + /* Now copy the MAC address into the last 6 bytes of the GID. */ + cl_memcpy( &mcast_req.member_rec.mgid.raw[10], mac.addr, 6 ); + } + + mcast_req.mcast_context = p_port; + mcast_req.pfn_mcast_cb = __mcast_cb; + mcast_req.timeout_ms = p_port->p_adapter->params.sa_timeout; + mcast_req.retry_cnt = p_port->p_adapter->params.sa_retry_cnt; + mcast_req.port_guid = p_port->p_adapter->guids.port_guid.guid; + mcast_req.pkey_index = p_port->pkey_index; + mcast_req.member_rec.pkey = cl_hton16(p_port->p_adapter->guids.port_guid.pkey); + /* + * Create the endpoint and insert it in the port. Since we don't wait for + * the mcast SA operations to complete before returning from the multicast + * list set OID asynchronously, it is possible for the mcast entry to be + * cleared before the SA interaction completes. In this case, when the + * mcast callback is invoked, it would not find the corresponding endpoint + * and would be undone. + */ + p_endpt = ipoib_endpt_create( + &mcast_req.member_rec.mgid, 0, CL_HTON32(0x00FFFFFF) ); + if( !p_endpt ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ipoib_endpt_create failed.\n") ); + return IB_INSUFFICIENT_MEMORY; + } + + status = __endpt_mgr_insert_locked( p_port, mac, p_endpt ); + if( status != IB_SUCCESS ) + { + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("__endpt_mgr_insert_locked returned %s\n", + p_port->p_adapter->p_ifc->get_err_str( status )) ); + return status; + } + + /* reference the object for the multicast join request. */ + ipoib_port_ref( p_port, ref_join_mcast ); + + status = p_port->p_adapter->p_ifc->join_mcast( p_port->ib_mgr.h_qp, &mcast_req ); + if( status != IB_SUCCESS ) + { + ipoib_port_deref( p_port, ref_mcast_join_failed ); + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("ib_join_mcast returned %s\n", + p_port->p_adapter->p_ifc->get_err_str( status )) ); + } + + IPOIB_EXIT( IPOIB_DBG_MCAST ); + return status; +} + + +static void +__mcast_cb( + IN ib_mcast_rec_t *p_mcast_rec ) +{ + ib_api_status_t status; + ipoib_port_t *p_port; + cl_fmap_item_t *p_item; + ipoib_endpt_t *p_endpt; + + IPOIB_ENTER( IPOIB_DBG_MCAST ); + + p_port = (ipoib_port_t*)p_mcast_rec->mcast_context; + + cl_obj_lock( &p_port->obj ); + while( p_port->endpt_rdr ) + { + cl_obj_unlock( &p_port->obj ); + cl_obj_lock( &p_port->obj ); + } + if( p_port->state != IB_QPS_RTS ) + { + cl_obj_unlock( &p_port->obj ); + if( p_mcast_rec->status == IB_SUCCESS ) + + { + ipoib_port_ref(p_port, ref_leave_mcast); + p_port->p_adapter->p_ifc->leave_mcast( p_mcast_rec->h_mcast, __leave_error_mcast_cb ); + } + ipoib_port_deref( p_port, ref_mcast_inv_state ); + IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, + ("Invalid state - Aborting.\n") ); + return; + } + + if( p_mcast_rec->status != IB_SUCCESS ) + { + cl_obj_unlock( &p_port->obj ); + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Multicast join request failed with status %s.\n", + p_port->p_adapter->p_ifc->get_err_str( p_mcast_rec->status )) ); + /* Flag the adapter as hung. */ + p_port->p_adapter->hung =TRUE; + ipoib_port_deref( p_port, ref_mcast_req_failed ); + IPOIB_EXIT( IPOIB_DBG_MCAST ); + return; + } + + p_item = cl_fmap_get( + &p_port->endpt_mgr.gid_endpts, &p_mcast_rec->p_member_rec->mgid ); + if( p_item == cl_fmap_end( &p_port->endpt_mgr.gid_endpts ) ) + { + /* + * The endpoint must have been flushed while the join request + * was outstanding. Just leave the group and return. This + * is not an error. + */ + cl_obj_unlock( &p_port->obj ); + IPOIB_PRINT(TRACE_LEVEL_WARNING, IPOIB_DBG_ERROR, + ("Failed to find endpoint for update.\n") ); + + ipoib_port_ref(p_port, ref_leave_mcast); + p_port->p_adapter->p_ifc->leave_mcast( p_mcast_rec->h_mcast, __leave_error_mcast_cb ); + ipoib_port_deref( p_port, ref_mcast_no_endpt ); + IPOIB_EXIT( IPOIB_DBG_MCAST ); + return; + } + + p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, gid_item ); + p_endpt->p_ifc = p_port->p_adapter->p_ifc; + + /* Setup the endpoint for use. */ + status = ipoib_endpt_set_mcast( + p_endpt, p_port->ib_mgr.h_pd, p_port->port_num, p_mcast_rec ); + if( status != IB_SUCCESS ) + { + cl_obj_unlock( &p_port->obj ); + IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_MCAST, + ("ipoib_endpt_set_mcast returned %s.\n", + p_port->p_adapter->p_ifc->get_err_str( status )) ); + /* Flag the adapter as hung. */ + p_port->p_adapter->hung = TRUE; + ipoib_port_deref( p_port, ref_mcast_av_failed ); + IPOIB_EXIT( IPOIB_DBG_MCAST ); + return; + } + + /* + * The endpoint is already in the GID and MAC maps. + * mast endpoint are not used in the LID map. + */ + CL_ASSERT(p_endpt->dlid == 0); + /* set flag that endpoint is use */ + p_endpt->is_in_use = TRUE; + cl_obj_unlock( &p_port->obj ); + + /* Try to send all pending sends. */ + ipoib_port_resume( p_port , FALSE); + + ipoib_port_deref( p_port, ref_join_mcast ); + + IPOIB_EXIT( IPOIB_DBG_MCAST ); +} + + +void +ipoib_leave_mcast_cb( + IN void *context ) +{ + ipoib_port_t *p_port; + + IPOIB_ENTER( IPOIB_DBG_MCAST ); + + p_port = (ipoib_port_t*)context; + + IPOIB_PRINT( TRACE_LEVEL_VERBOSE, IPOIB_DBG_MCAST,("p_port->mcast_cnt = %d\n", p_port->mcast_cnt)); + + ipoib_port_deref( p_port, ref_leave_mcast); + cl_atomic_dec( &p_port->mcast_cnt); + + if(0 == p_port->mcast_cnt) + { + KeSetEvent( &p_port->leave_mcast_event, EVENT_INCREMENT, FALSE ); + } + + IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_MCAST, + ("Leave mcast callback deref ipoib_port \n") ); + + IPOIB_EXIT( IPOIB_DBG_MCAST ); +} + + + +void +__leave_error_mcast_cb( + IN void *context ) +{ + ipoib_port_t *p_port; + + IPOIB_ENTER( IPOIB_DBG_MCAST ); + + p_port = (ipoib_port_t*)context; + + ipoib_port_deref( p_port, ref_leave_mcast); + IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_MCAST, + ("Leave mcast callback deref ipoib_port \n") ); + + IPOIB_EXIT( IPOIB_DBG_MCAST ); +} + +/*++ +Routine Description: + The routine process the packet and returns LSO information + +Arguments: + pNetBuffer - a pointer to the first net buffer object of the packet + TcpHeaderOffset - offset to the begining of the TCP header in the packet + pLsoData - pointer to LsoData object in which the routine returns the LSO information + pHeaderSize - pointer to ULONG object in which the header size is returned + IndexOfData - + +Return Value: + NDIS_STATUS + +NOTE: + called at DISPATCH level +--*/ + +NDIS_STATUS GetLsoHeaderSize( + IN PNET_BUFFER pNetBuffer, + IN LsoData *pLsoData, + OUT UINT *IndexOfData, + IN ipoib_hdr_t *ipoib_hdr + ) +{ + UINT CurrLength; + PUCHAR pSrc; + PUCHAR pCopiedData = pLsoData->coppied_data; + ip_hdr_t UNALIGNED *IpHdr; + tcp_hdr_t UNALIGNED *TcpHdr; + uint16_t TcpHeaderLen; + uint16_t IpHeaderLen; + uint16_t IpOffset; + INT FullBuffers = 0; + PMDL pMDL; + NDIS_STATUS status = NDIS_STATUS_INVALID_PACKET; + + +#define IP_OFFSET 14; + // + // This Flag indicates the way we gets the headers + // RegularFlow = we get the headers (ETH+IP+TCP) in the same Buffer + // in sequence. + // + boolean_t IsRegularFlow = TRUE; + + const uint16_t ETH_OFFSET = IP_OFFSET; + + pLsoData->LsoHeaderSize = 0; + IpOffset = IP_OFFSET; //(uint16_t)pPort->EncapsulationFormat.EncapsulationHeaderSize; + *IndexOfData = 0; + + pMDL = NET_BUFFER_CURRENT_MDL(pNetBuffer); + NdisQueryMdl(pMDL, &pSrc, &CurrLength, NormalPagePriority); + //NdisQueryBufferSafe( CurrBuffer, &pSrc, &CurrLength, NormalPagePriority ); + if (pSrc == NULL) { + IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, ("Error processing packets\n")); + return status; + } + // We start by looking for the ethernet and the IP + if (CurrLength < ETH_OFFSET) { + IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, ("Error porcessing packets\n")); + return status; + } + //pLsoData->LsoHeaderSize = pLsoData->LsoHeaderSize + ETH_OFFSET; + if (CurrLength == ETH_OFFSET) { + ASSERT(FALSE); + IsRegularFlow = FALSE; + memcpy(pCopiedData, pSrc, ETH_OFFSET); + pCopiedData += ETH_OFFSET; + FullBuffers++; + // First buffer was only ethernet + pNetBuffer = NET_BUFFER_NEXT_NB(pNetBuffer); + NdisQueryMdl(NET_BUFFER_CURRENT_MDL(pNetBuffer), &pSrc, &CurrLength, NormalPagePriority); + if (pSrc == NULL) { + IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, ("Error porcessing packets\n")); + return status; + } + } else { + // This is ETH + IP together (at least) + pLsoData->LsoBuffers[0].pData = pSrc + (ETH_OFFSET - sizeof (ipoib_hdr_t)); + memcpy (pLsoData->LsoBuffers[0].pData, ipoib_hdr, sizeof (ipoib_hdr_t)); + CurrLength -= ETH_OFFSET; + pSrc = pSrc + ETH_OFFSET; + pLsoData->LsoHeaderSize = pLsoData->LsoHeaderSize + sizeof (ipoib_hdr_t); + } + // we should now be having at least the size of ethernet data + if (CurrLength < sizeof (ip_hdr_t)) { + IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, ("Error porcessing packets\n")); + return status; + } + IpHdr = (ip_hdr_t UNALIGNED*)pSrc; + IpHeaderLen = (uint16_t)IP_HEADER_LENGTH(IpHdr); + ASSERT(IpHdr->prot == IP_PROT_TCP); + if (CurrLength < IpHeaderLen) { + IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, ("Error processing packets\n")); + return status; + } + pLsoData->LsoHeaderSize = pLsoData->LsoHeaderSize + IpHeaderLen; + // We now start to find where the TCP header starts + if (CurrLength == IpHeaderLen) { + ASSERT(FALSE); + // two options : + // if(IsRegularFlow = FALSE) ==> ETH and IP seperated in two buffers + // if(IsRegularFlow = TRUE ) ==> ETH and IP in the same buffer + // TCP will start at next buffer + if(IsRegularFlow){ + memcpy(pCopiedData, pSrc-ETH_OFFSET ,ETH_OFFSET+IpHeaderLen); + pCopiedData += (ETH_OFFSET + IpHeaderLen); + } else { + memcpy(pCopiedData, pSrc,IpHeaderLen); + pCopiedData += IpHeaderLen; + } + + FullBuffers++; + IsRegularFlow = FALSE; + //NdisGetNextBuffer( CurrBuffer, &CurrBuffer); + //NdisQueryBufferSafe( CurrBuffer, &pSrc, &CurrLength, NormalPagePriority ); + pNetBuffer = NET_BUFFER_NEXT_NB(pNetBuffer); + NdisQueryMdl(NET_BUFFER_CURRENT_MDL(pNetBuffer), &pSrc, &CurrLength, NormalPagePriority); + if (pSrc == NULL) { + IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, ("Error porcessing packets\n")); + return status; + } + } else { + // if(IsRegularFlow = TRUE ) ==> the ETH and IP and TCP in the same buffer + // if(IsRegularFlow = FLASE ) ==> ETH in one buffer , IP+TCP together in the same buffer + if (IsRegularFlow) { + pLsoData->LsoBuffers[0].Len += IpHeaderLen; + } else { + memcpy(pCopiedData, pSrc, IpHeaderLen); + pCopiedData += IpHeaderLen; + } + + CurrLength -= IpHeaderLen; + pSrc = pSrc + IpHeaderLen; + } + if (CurrLength < sizeof (tcp_hdr_t)) { + IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, ("Error porcessing packets\n")); + return status; + } + // We have finaly found the TCP header + TcpHdr = (tcp_hdr_t UNALIGNED *)pSrc; + TcpHeaderLen = TCP_HEADER_LENGTH(TcpHdr); + + //ASSERT(TcpHeaderLen == 20); + + if (CurrLength < TcpHeaderLen) { + //IPOIB_PRINT(TRACE_LEVEL_VERBOSE, ETH, ("Error porcessing packets\n")); + return status; + } + pLsoData->LsoHeaderSize = pLsoData->LsoHeaderSize + TcpHeaderLen; + if(IsRegularFlow){ + pLsoData->LsoBuffers[0].Len += TcpHeaderLen; + } + else{ + memcpy(pCopiedData, pSrc, TcpHeaderLen); + pCopiedData += TcpHeaderLen; + } + if (CurrLength == TcpHeaderLen) { + FullBuffers++; + pLsoData->UsedBuffers = FullBuffers; + *IndexOfData = FullBuffers ; + } else { + pLsoData->UsedBuffers = FullBuffers + 1; + *IndexOfData = FullBuffers - 1; + } + pLsoData->FullBuffers = FullBuffers; + if (!IsRegularFlow){ + pLsoData->LsoBuffers[0].pData = pLsoData->coppied_data; + pLsoData->LsoBuffers[0].Len = ETH_OFFSET + IpHeaderLen + TcpHeaderLen; + ASSERT(pLsoData->LsoBuffers[0].Len <= LSO_MAX_HEADER); + } + return NDIS_STATUS_SUCCESS; +} + +static void __port_do_mcast_garbage(ipoib_port_t* const p_port) +{ + const mac_addr_t DEFAULT_MCAST_GROUP = {0x01, 0x00, 0x5E, 0x00, 0x00, 0x01}; + /* Do garbage collecting... */ + + cl_map_item_t *p_item; + ipoib_endpt_t *p_endpt; + cl_qlist_t destroy_mc_list; + uint8_t cnt; + const static GC_MAX_LEAVE_NUM = 80; + + cl_qlist_init( &destroy_mc_list ); + + cl_obj_lock( &p_port->obj ); + /* Wait for all readers to finish */ + while( p_port->endpt_rdr ) + { + cl_obj_unlock( &p_port->obj ); + cl_obj_lock( &p_port->obj ); + } + cnt = 0; + p_item = cl_qmap_head( &p_port->endpt_mgr.mac_endpts ); + while( (p_item != cl_qmap_end( &p_port->endpt_mgr.mac_endpts )) && (cnt < GC_MAX_LEAVE_NUM)) + { + p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item ); + p_item = cl_qmap_next( p_item ); + + /* Check if the current endpoint is not a multicast listener */ + + if( p_endpt->h_mcast && + (!p_endpt->is_mcast_listener) && + ( cl_memcmp( &p_endpt->mac, &DEFAULT_MCAST_GROUP, sizeof(mac_addr_t) ) && + (!p_endpt->is_in_use) )) + { + cl_qmap_remove_item( &p_port->endpt_mgr.mac_endpts, + &p_endpt->mac_item ); + cl_fmap_remove_item( &p_port->endpt_mgr.gid_endpts, + &p_endpt->gid_item ); + + if( p_endpt->dlid ) + { + cl_qmap_remove_item( &p_port->endpt_mgr.lid_endpts, + &p_endpt->lid_item ); + p_endpt->dlid = 0; + } + + cl_qlist_insert_tail( + &destroy_mc_list, &p_endpt->mac_item.pool_item.list_item ); + cnt++; + } + else + p_endpt->is_in_use = FALSE; + } + cl_obj_unlock( &p_port->obj ); + + /* Destroy all multicast endpoints now that we have released the lock. */ + while( cl_qlist_count( &destroy_mc_list ) ) + { + p_endpt = PARENT_STRUCT( cl_qlist_remove_head( &destroy_mc_list ), + ipoib_endpt_t, mac_item.pool_item.list_item ); + IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT, + ("mcast garbage collector: destroying endpoint %02x:%02x:%02x:%02x:%02x:%02x \n", + p_endpt->mac.addr[0], + p_endpt->mac.addr[1], + p_endpt->mac.addr[2], + p_endpt->mac.addr[3], + p_endpt->mac.addr[4], + p_endpt->mac.addr[5]) ); + cl_obj_destroy( &p_endpt->obj ); + } +} + +static void __port_mcast_garbage_dpc(KDPC *p_gc_dpc,void *context,void *s_arg1, void *s_arg2) +{ + ipoib_port_t *p_port = (ipoib_port_t *) context; + + UNREFERENCED_PARAMETER(p_gc_dpc); + UNREFERENCED_PARAMETER(s_arg1); + UNREFERENCED_PARAMETER(s_arg2); + + __port_do_mcast_garbage(p_port); +} + +ipoib_endpt_t* +ipoib_endpt_get_by_gid( + IN ipoib_port_t* const p_port, + IN const ib_gid_t* const p_gid ) +{ + return __endpt_mgr_get_by_gid( p_port, p_gid ); +} + +ipoib_endpt_t* +ipoib_endpt_get_by_lid( + IN ipoib_port_t* const p_port, + IN const net16_t lid ) +{ + return __endpt_mgr_get_by_lid( p_port, lid ); +} + +ib_api_status_t +ipoib_recv_dhcp( + IN ipoib_port_t* const p_port, + IN const ipoib_pkt_t* const p_ipoib, + OUT eth_pkt_t* const p_eth, + IN ipoib_endpt_t* const p_src, + IN ipoib_endpt_t* const p_dst ) +{ + return __recv_dhcp( + p_port, p_ipoib, p_eth, p_src,p_dst ); +} + + +void +ipoib_port_cancel_xmit( + IN ipoib_port_t* const p_port, + IN PVOID cancel_id ) +{ + cl_list_item_t *p_item; + PNET_BUFFER_LIST p_nbl; + PVOID nbl_id; + cl_qlist_t cancel_list; + ULONG send_complete_flags = 0; + IPOIB_ENTER( IPOIB_DBG_SEND ); + + cl_qlist_init( &cancel_list ); + + cl_spinlock_acquire( &p_port->send_lock ); + + for( p_item = cl_qlist_head( &p_port->send_mgr.pending_list ); + p_item != cl_qlist_end( &p_port->send_mgr.pending_list ); + p_item = cl_qlist_next( p_item ) ) + { + p_nbl = IPOIB_PACKET_FROM_LIST_ITEM( p_item ); + nbl_id = NDIS_GET_NET_BUFFER_LIST_CANCEL_ID( p_nbl ); + if( nbl_id == cancel_id ) + { + cl_qlist_remove_item( &p_port->send_mgr.pending_list, p_item ); + NET_BUFFER_LIST_STATUS( p_nbl) = NDIS_STATUS_REQUEST_ABORTED ; + cl_qlist_insert_tail( &cancel_list, IPOIB_LIST_ITEM_FROM_PACKET( p_nbl ) ); + } + } + cl_spinlock_release( &p_port->send_lock ); + + if( cl_qlist_count( &cancel_list ) ) + { + while( ( p_item = cl_qlist_remove_head( &cancel_list )) + != cl_qlist_end( &cancel_list )) + { + p_nbl = IPOIB_PACKET_FROM_LIST_ITEM( p_item ); + NET_BUFFER_LIST_STATUS( p_nbl) = NDIS_STATUS_SEND_ABORTED; + send_complete_flags = 0; + if (NDIS_CURRENT_IRQL() == DISPATCH_LEVEL) + { + NDIS_SET_SEND_COMPLETE_FLAG(send_complete_flags, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL); + } + NdisMSendNetBufferListsComplete( p_port->p_adapter->h_adapter, + p_nbl, send_complete_flags ); + } + } + IPOIB_EXIT( IPOIB_DBG_SEND ); +} + +/* +* Put all fragments into separate WR and chain together. +* The last WR will be set to generate CQ Event. +* lookaside buffer is used for ipoib and ip headers attached to each WR. +* Buffer will be released on last WR send completion. +*/ +#if 0 +static NDIS_STATUS +__send_fragments( +IN ipoib_port_t* const p_port, +IN ipoib_send_desc_t* const p_desc, +IN eth_hdr_t* const p_eth_hdr, +IN ip_hdr_t* const p_ip_hdr, +IN uint32_t buf_len, +IN NDIS_BUFFER* p_ndis_buf ) +{ + uint32_t ds_idx = 1; + uint32_t wr_idx = 0; + uint32_t sgl_idx = 2; //skip eth hdr, ip hdr + uint32_t options_len = 0; + uint8_t* p_options = NULL; + uint8_t* p_buf; + uint32_t frag_offset = 0; + uint32_t next_sge; + uint32_t wr_size = 0; + uint32_t ip_hdr_len = IP_HEADER_LENGTH( p_ip_hdr ); + uint32_t total_ip_len = cl_ntoh16( p_ip_hdr->length ); + + SCATTER_GATHER_LIST *p_sgl; + + IPOIB_ENTER( IPOIB_DBG_SEND ); + + if( IP_DONT_FRAGMENT(p_ip_hdr) ) + return NDIS_STATUS_INVALID_PACKET; + + p_sgl = NDIS_PER_PACKET_INFO_FROM_PACKET( p_desc->p_pkt, ScatterGatherListPacketInfo ); + if( !p_sgl ) + { + ASSERT( p_sgl ); + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed to get SGL from packet.\n") ); + return NDIS_STATUS_FAILURE; + } + if( ( p_sgl->NumberOfElements > MAX_SEND_SGE || + p_sgl->Elements[0].Length < sizeof(eth_hdr_t)) ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Too many SG Elements in packet.\n") ); + return NDIS_STATUS_FAILURE; + } + p_buf = (uint8_t *) + ExAllocateFromNPagedLookasideList( &p_port->buf_mgr.send_buf_list ); + if( !p_buf ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed to allocate lookaside buffer.\n") ); + return NDIS_STATUS_RESOURCES; + } + p_desc->p_buf = (send_buf_t*)p_buf; + + if( buf_len < ip_hdr_len ) + { /* ip options in a separate buffer */ + CL_ASSERT( buf_len == sizeof( ip_hdr_t ) ); + NdisGetNextBuffer( p_ndis_buf, &p_ndis_buf ); + if( !p_ndis_buf ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed to get IP options buffer.\n") ); + return NDIS_STATUS_FAILURE; + } + NdisQueryBufferSafe( p_ndis_buf, &p_options, &options_len, NormalPagePriority ); + if( !p_options ) + { + IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, + ("Failed to query IP options buffer address.\n") ); + return NDIS_STATUS_FAILURE; + } + cl_memcpy( p_buf, p_ip_hdr, sizeof( ip_hdr_t ) ); + if( p_options && options_len ) + { + __copy_ip_options( &p_buf[sizeof(ip_hdr_t)], + p_options, options_len, TRUE ); + } + wr_size = buf_len + options_len; + sgl_idx++; + } + else + { /*options probably in the same buffer */ + cl_memcpy( p_buf, p_ip_hdr, buf_len ); + options_len = ip_hdr_len - sizeof( ip_hdr_t ); + if( options_len ) + { + p_options = p_buf + sizeof( ip_hdr_t ); + } + frag_offset += ( buf_len - ip_hdr_len ); + wr_size = buf_len; + } + + p_desc->send_wr[wr_idx].local_ds[ds_idx].vaddr = cl_get_physaddr( p_buf ); + p_desc->send_wr[wr_idx].local_ds[ds_idx].lkey = p_port->ib_mgr.lkey; + p_desc->send_wr[wr_idx].local_ds[ds_idx].length = wr_size; + + /* count how much data can be put into the first WR beside IP header. + * other protocols headers possibly supplied in subsequent buffers. + */ + for( sgl_idx; sgl_idx < p_sgl->NumberOfElements; sgl_idx++ ) + { + next_sge = p_sgl->Elements[sgl_idx].Length; + + /* add sgl if it can fit into the same WR + * Note: so far not going to split large SGE between WRs, + * so first fragment could be a smaller size. + */ + if( next_sge <= ( p_port->p_adapter->params.payload_mtu - wr_size ) ) + { + ++ds_idx; + wr_size += next_sge; + frag_offset += next_sge; + p_desc->send_wr[wr_idx].local_ds[ds_idx].vaddr = + p_sgl->Elements[sgl_idx].Address.QuadPart; + p_desc->send_wr[wr_idx].local_ds[ds_idx].length = next_sge; + p_desc->send_wr[wr_idx].local_ds[ds_idx].lkey = p_port->ib_mgr.lkey; + } + else + { + /* fix ip hdr for the first fragment and move on */ + __update_fragment_ip_hdr( (ip_hdr_t* const)p_buf, + (uint16_t)wr_size, IP_FRAGMENT_OFFSET(p_ip_hdr), TRUE ); + + p_desc->send_wr[wr_idx].wr.num_ds = ds_idx + 1; + p_buf += ip_hdr_len; + p_buf += (( buf_len > ip_hdr_len ) ? ( buf_len - ip_hdr_len ): 0); + frag_offset += ( (IP_FRAGMENT_OFFSET(p_ip_hdr)) << 3 ); + ++wr_idx; + ds_idx = 0; + break; + } + } + total_ip_len -= wr_size; + wr_size = 0; + + for( sgl_idx, wr_idx; sgl_idx < p_sgl->NumberOfElements; sgl_idx++ ) + { + uint32_t seg_len; + uint64_t next_sgl_addr; + + if( wr_idx >= ( MAX_WRS_PER_MSG - 1 ) ) + return NDIS_STATUS_RESOURCES; + + next_sge = p_sgl->Elements[sgl_idx].Length; + next_sgl_addr = p_sgl->Elements[sgl_idx].Address.QuadPart; + + while( next_sge ) + { + if( ds_idx == 0 ) + { /* new ipoib + ip header */ + ((ipoib_hdr_t*)p_buf)->type = p_eth_hdr->type; + ((ipoib_hdr_t*)p_buf)->resv = 0; + p_desc->send_wr[wr_idx].local_ds[ds_idx].vaddr = cl_get_physaddr( p_buf ); + p_desc->send_wr[wr_idx].local_ds[ds_idx].lkey = p_port->ib_mgr.lkey; + p_desc->send_wr[wr_idx].local_ds[ds_idx].length = sizeof( ipoib_hdr_t ); + p_buf += sizeof( ipoib_hdr_t ); + ++ds_idx; + + cl_memcpy( p_buf, p_ip_hdr, sizeof( ip_hdr_t ) ); + if( p_options && options_len ) + { + /* copy ip options if needed */ + __copy_ip_options( &p_buf[sizeof(ip_hdr_t)], + p_options, options_len, FALSE ); + } + wr_size = ip_hdr_len; + } + if( ds_idx == 1 ) + { + p_desc->send_wr[wr_idx].local_ds[ds_idx].length = ip_hdr_len; + p_desc->send_wr[wr_idx].local_ds[ds_idx].vaddr = cl_get_physaddr( p_buf ); + p_desc->send_wr[wr_idx].local_ds[ds_idx].lkey = p_port->ib_mgr.lkey; + ++ds_idx; + } + + seg_len = ( next_sge > ( p_port->p_adapter->params.payload_mtu - wr_size ) )? + ( p_port->p_adapter->params.payload_mtu - wr_size ) : next_sge; + + p_desc->send_wr[wr_idx].local_ds[ds_idx].vaddr = next_sgl_addr; + p_desc->send_wr[wr_idx].local_ds[ds_idx].length = seg_len; + p_desc->send_wr[wr_idx].local_ds[ds_idx].lkey = p_port->ib_mgr.lkey; + ++ds_idx; + + wr_size += seg_len; + total_ip_len -= seg_len; + + if( wr_size >= p_port->p_adapter->params.payload_mtu || total_ip_len == 0 ) + { /* fix ip hdr for that fragment */ + __update_fragment_ip_hdr( (ip_hdr_t* const)p_buf, (uint16_t)wr_size, + ((uint16_t)(frag_offset >> 3 )), + (BOOLEAN)(( total_ip_len > 0 ) || IP_MORE_FRAGMENTS( p_ip_hdr)) ); + p_desc->send_wr[wr_idx].wr.num_ds = ds_idx; + if( total_ip_len > 0 ) + { + ++wr_idx; + frag_offset += (wr_size - ip_hdr_len); + wr_size = 0; + ds_idx = 0; + p_buf += ip_hdr_len; + } + } + next_sge -= seg_len; + if( next_sge > 0 ) + { + next_sgl_addr += seg_len; + } + } + } + p_desc->num_wrs += wr_idx; + + IPOIB_EXIT( IPOIB_DBG_SEND ); + return NDIS_STATUS_SUCCESS; +} + + +static void +__update_fragment_ip_hdr( +IN ip_hdr_t* const p_ip_hdr, +IN uint16_t fragment_size, +IN uint16_t fragment_offset, +IN BOOLEAN more_fragments ) +{ + uint16_t* p_hdr = (uint16_t*)p_ip_hdr; + p_ip_hdr->length = cl_hton16( fragment_size ); // bytes + p_ip_hdr->offset = cl_hton16( fragment_offset ); // 8-byte units + if( more_fragments ) + { + IP_SET_MORE_FRAGMENTS( p_ip_hdr ); + } + else + { + IP_SET_LAST_FRAGMENT( p_ip_hdr ); + } + p_ip_hdr->chksum = 0; + p_ip_hdr->chksum = ipchksum( p_hdr, IP_HEADER_LENGTH(p_ip_hdr) ); +} + +static void +__copy_ip_options( +IN uint8_t* p_buf, +IN uint8_t* p_options, +IN uint32_t options_len, +IN BOOLEAN copy_all ) +{ + uint32_t option_length; + uint32_t total_length = 0; + uint32_t copied_length = 0; + uint8_t* p_src = p_options; + uint8_t* p_dst = p_buf; + + if( p_options == NULL || options_len == 0 ) + return; + if( copy_all ) + { + cl_memcpy( p_dst, p_src, options_len ); + return; + } + do + { + if( ( *p_src ) == 0 ) // end of options list + { + total_length++; + break; + } + if( ( *p_src ) == 0x1 ) // no op + { + p_src++; + total_length++; + continue; + } + /*from RFC791: + * This option may be used between options, for example, to align + * the beginning of a subsequent option on a 32 bit boundary. + */ + if( copied_length && (copied_length % 4) ) + { + uint32_t align = 4 - (copied_length % 4); + cl_memset( p_dst, 0x1, (size_t)align ); + p_dst += align; + copied_length += align; + } + option_length = *(p_src + 1); + + if( *p_src & 0x80 ) + { + cl_memcpy( p_dst, p_src, option_length ); + p_dst += option_length; + copied_length += option_length; + } + total_length += option_length; + p_src += option_length; + + }while( total_length < options_len ); + + CL_ASSERT( total_length == options_len ); + CL_ASSERT( copied_length <= 40 ); + + /* padding the rest */ + if( options_len > copied_length ) + { + cl_memclr( p_dst, ( options_len - copied_length ) ); + } + return; +} +#endif diff --git a/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_port.h b/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_port.h index 602389b5..30090dc0 100644 --- a/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_port.h +++ b/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_port.h @@ -86,8 +86,8 @@ (((send_buf_t**)NET_BUFFER_MINIPORT_RESERVED(P))[2]) -#define IPOIB_GET_NET_BUFFER_LIST_REF_COUNT(_NetBufferList) ((_NetBufferList->FirstNetBuffer)->MiniportReserved[3]) -#define IPOIB_DEC_NET_BUFFER_LIST_REF_COUNT(_NetBufferList) (*(PULONG)&(_NetBufferList->FirstNetBuffer)->MiniportReserved[3])-- +#define IPOIB_GET_NET_BUFFER_LIST_REF_COUNT(_NetBufferList) ((NET_BUFFER_LIST_FIRST_NB(_NetBufferList))->MiniportReserved[3]) +#define IPOIB_DEC_NET_BUFFER_LIST_REF_COUNT(_NetBufferList) (*(PULONG)&(NET_BUFFER_LIST_FIRST_NB(_NetBufferList))->MiniportReserved[3])-- typedef struct _ipoib_ib_mgr @@ -523,7 +523,7 @@ typedef struct _ipoib_endpt_mgr * Map of connected endpts, keyed by remote gid. *********/ - +#pragma warning(disable:4324) // structure padded due to align() typedef struct _ipoib_port { cl_obj_t obj; @@ -573,6 +573,8 @@ typedef struct _ipoib_port ipoib_hdr_t hdr[1]; /* Must be last! */ } ipoib_port_t; +#pragma warning(default:4324) + /* * FIELDS * obj diff --git a/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_xfr_mgr.c b/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_xfr_mgr.c deleted file mode 100644 index ce0650f1..00000000 --- a/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_xfr_mgr.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2008 Mellanox 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: ipoib_xfr_mgr.c 3459 2008-11-12 16:48:21Z tzachid $ - */ - - -#include "ipoib_xfr_mgr.h" -#if defined(EVENT_TRACING) -#ifdef offsetof -#undef offsetof -#endif -#include "ipoib_xfr_mgr.tmh" -#endif - - -const ipoib_guid2mac_translation_t guid2mac_table[] = { - {0x30, 0x48, 0xE7}, - {0x05, 0xAD, 0xE7}, - {0x18, 0x8B, 0xE7}, - {0x1A, 0x4B, 0xE7}, - {0x17, 0x08, 0xE7}, - {0x1E, 0x0B, 0xE7}, - - {0x03, 0xBA, 0xE7}, - {0x05, 0xAD, 0xE7}, - {0x0D, 0x9D, 0xE7}, - {0x11, 0x0A, 0xE7}, - {0x11, 0x85, 0xE7}, - {0x12, 0x79, 0xE7}, - {0x13, 0x21, 0xE7}, - {0x14, 0x38, 0xE7}, - {0x16, 0x35, 0xE7}, - {0x17, 0x08, 0xE7}, - {0x17, 0xA4, 0xE7}, - {0x18, 0x8B, 0xE7}, - {0x18, 0xFE, 0xE7}, - {0x19, 0xBB, 0xE7}, - {0x1A, 0x4B, 0xE7}, - {0x1B, 0x78, 0xE7}, - {0x1E, 0x0B, 0xE7}, - {0x22, 0x64, 0xE7}, - {0x23, 0x7D, 0xE7}, - {0x30, 0x48, 0xE7}, - {0x80, 0x5F, 0xE7}, - - {0x00, 0x00, 0x00}, -}; - diff --git a/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_xfr_mgr.cpp b/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_xfr_mgr.cpp new file mode 100644 index 00000000..ce0650f1 --- /dev/null +++ b/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_xfr_mgr.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2008 Mellanox 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: ipoib_xfr_mgr.c 3459 2008-11-12 16:48:21Z tzachid $ + */ + + +#include "ipoib_xfr_mgr.h" +#if defined(EVENT_TRACING) +#ifdef offsetof +#undef offsetof +#endif +#include "ipoib_xfr_mgr.tmh" +#endif + + +const ipoib_guid2mac_translation_t guid2mac_table[] = { + {0x30, 0x48, 0xE7}, + {0x05, 0xAD, 0xE7}, + {0x18, 0x8B, 0xE7}, + {0x1A, 0x4B, 0xE7}, + {0x17, 0x08, 0xE7}, + {0x1E, 0x0B, 0xE7}, + + {0x03, 0xBA, 0xE7}, + {0x05, 0xAD, 0xE7}, + {0x0D, 0x9D, 0xE7}, + {0x11, 0x0A, 0xE7}, + {0x11, 0x85, 0xE7}, + {0x12, 0x79, 0xE7}, + {0x13, 0x21, 0xE7}, + {0x14, 0x38, 0xE7}, + {0x16, 0x35, 0xE7}, + {0x17, 0x08, 0xE7}, + {0x17, 0xA4, 0xE7}, + {0x18, 0x8B, 0xE7}, + {0x18, 0xFE, 0xE7}, + {0x19, 0xBB, 0xE7}, + {0x1A, 0x4B, 0xE7}, + {0x1B, 0x78, 0xE7}, + {0x1E, 0x0B, 0xE7}, + {0x22, 0x64, 0xE7}, + {0x23, 0x7D, 0xE7}, + {0x30, 0x48, 0xE7}, + {0x80, 0x5F, 0xE7}, + + {0x00, 0x00, 0x00}, +}; +