\r
SOURCES= ipoib_log.mc \\r
ipoib.rc \\r
- ipoib_driver.c \\r
- ipoib_adapter.c \\r
- ipoib_endpoint.c \\r
- ipoib_port.c \\r
- ipoib_ibat.c \\r
-# ipoib_cm.c \\r
- ipoib_xfr_mgr.c\r
+ ipoib_driver.cpp \\r
+ ipoib_adapter.cpp \\r
+ ipoib_endpoint.cpp \\r
+ ipoib_port.cpp \\r
+ ipoib_ibat.cpp \\r
+# ipoib_cm.cpp \\r
+ ipoib_xfr_mgr.cpp\r
\r
INCLUDES=..;..\..\..\inc;..\..\..\inc\kernel;\r
\r
\r
C_DEFINES = $(C_DEFINES) -DEVENT_TRACING\r
\r
-RUN_WPP = $(SOURCES) -km -ext: .c .h .C .H \\r
+RUN_WPP = $(SOURCES) -km -ext: .c .cpp .h .C .CPP .H\\r
-scan:ipoib_debug.h \\r
-func:IPOIB_PRINT(LEVEL,FLAGS,(MSG,...)) \\r
-func:IPOIB_PRINT_EXIT(LEVEL,FLAGS,(MSG,...))\r
+++ /dev/null
-/*\r
- * Copyright (c) 2005 SilverStorm Technologies. All rights reserved.\r
- * Copyright (c) 2006 Mellanox Technologies. All rights reserved.\r
- * Portions Copyright (c) 2008 Microsoft Corporation. All rights reserved.\r
- *\r
- * This software is available to you under the OpenIB.org BSD license\r
- * below:\r
- *\r
- * Redistribution and use in source and binary forms, with or\r
- * without modification, are permitted provided that the following\r
- * conditions are met:\r
- *\r
- * - Redistributions of source code must retain the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer.\r
- *\r
- * - Redistributions in binary form must reproduce the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer in the documentation and/or other materials\r
- * provided with the distribution.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- * SOFTWARE.\r
- *\r
- * $Id: ipoib_adapter.c 4506 2009-06-23 14:40:54Z xalex $\r
- */\r
-\r
-\r
-\r
-#include "ipoib_adapter.h"\r
-#include "ipoib_port.h"\r
-#include "ipoib_driver.h"\r
-#include "ipoib_debug.h"\r
-\r
-#if defined(EVENT_TRACING)\r
-#ifdef offsetof\r
-#undef offsetof\r
-#endif\r
-#include "ipoib_adapter.tmh"\r
-#endif\r
-\r
-\r
-#define ITEM_POOL_START 16\r
-#define ITEM_POOL_GROW 16\r
-\r
-\r
-/* IB Link speeds in 100bps */\r
-#define ONE_X_IN_100BPS 25000000\r
-#define FOUR_X_IN_100BPS 100000000\r
-#define TWELVE_X_IN_100BPS 300000000\r
-\r
-\r
-/* Declarations */\r
-static void\r
-adapter_construct(\r
- IN ipoib_adapter_t* const p_adapter );\r
-\r
-\r
-static ib_api_status_t\r
-adapter_init(\r
- IN ipoib_adapter_t* const p_adapter );\r
-\r
-\r
-static void\r
-__adapter_destroying(\r
- IN cl_obj_t* const p_obj );\r
-\r
-\r
-static void\r
-__adapter_free(\r
- IN cl_obj_t* const p_obj );\r
-\r
-\r
-static ib_api_status_t\r
-__ipoib_pnp_reg(\r
- IN ipoib_adapter_t* const p_adapter,\r
- IN ib_pnp_class_t flags );\r
-\r
-\r
-static void\r
-__ipoib_pnp_dereg(\r
- IN void* context );\r
-\r
-\r
-static void\r
-__ipoib_adapter_reset(\r
- IN void* context);\r
-\r
-\r
-static ib_api_status_t\r
-__ipoib_pnp_cb(\r
- IN ib_pnp_rec_t *p_pnp_rec );\r
-\r
-\r
-void\r
-ipoib_join_mcast(\r
- IN ipoib_adapter_t* const p_adapter );\r
-\r
-\r
-/* Leaves all mcast groups when port goes down. */\r
-static void\r
-ipoib_clear_mcast(\r
- IN ipoib_port_t* const p_port );\r
-\r
-NDIS_STATUS\r
-ipoib_get_adapter_guids(\r
- IN NDIS_HANDLE* const h_adapter,\r
- IN OUT ipoib_adapter_t *p_adapter );\r
-\r
-NDIS_STATUS\r
-ipoib_get_adapter_params(\r
- IN NDIS_HANDLE* const wrapper_config_context,\r
- IN OUT ipoib_adapter_t *p_adapter,\r
- OUT PUCHAR *p_mac,\r
- OUT UINT *p_len);\r
-\r
-\r
-/* Implementation */\r
-ib_api_status_t\r
-ipoib_create_adapter(\r
- IN NDIS_HANDLE wrapper_config_context,\r
- IN void* const h_adapter,\r
- OUT ipoib_adapter_t** const pp_adapter )\r
-{\r
- ipoib_adapter_t *p_adapter;\r
- ib_api_status_t status;\r
- cl_status_t cl_status;\r
- PUCHAR mac;\r
- UINT len;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-\r
- p_adapter = cl_zalloc( sizeof(ipoib_adapter_t) );\r
- if( !p_adapter )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Failed to allocate ipoib_adapter_t (%d bytes)",\r
- sizeof(ipoib_adapter_t)) );\r
- return IB_INSUFFICIENT_MEMORY;\r
- }\r
-\r
- adapter_construct( p_adapter );\r
-\r
- p_adapter->h_adapter = h_adapter;\r
-\r
- p_adapter->p_ifc = cl_zalloc( sizeof(ib_al_ifc_t) );\r
- if( !p_adapter->p_ifc )\r
- {\r
- __adapter_free( &p_adapter->obj );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ipoib_create_adapter failed to alloc ipoib_ifc_t %d bytes\n",\r
- sizeof(ib_al_ifc_t)) );\r
- return IB_INSUFFICIENT_MEMORY;\r
- }\r
-\r
- /* Get the CA and port GUID from the bus driver. */\r
- status = ipoib_get_adapter_guids( h_adapter, p_adapter );\r
- if( status != NDIS_STATUS_SUCCESS )\r
- {\r
-ASSERT(FALSE);\r
-//return NDIS_STATUS_SUCCESS;\r
- __adapter_free( &p_adapter->obj );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ipoib_get_adapter_guids returned 0x%.8X.\n", status) );\r
- return status;\r
- }\r
-\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
- ("Port %016I64x (CA %016I64x port %d) initializing\n",\r
- p_adapter->guids.port_guid.guid, p_adapter->guids.ca_guid,\r
- p_adapter->guids.port_num) );\r
-\r
- cl_status = cl_obj_init( &p_adapter->obj, CL_DESTROY_SYNC,\r
- __adapter_destroying, NULL, __adapter_free );\r
- if( cl_status != CL_SUCCESS )\r
- {\r
- __adapter_free( &p_adapter->obj );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("cl_obj_init returned %#x\n", cl_status) );\r
- return IB_ERROR;\r
- }\r
-\r
- /* Read configuration parameters. */\r
- status = ipoib_get_adapter_params( wrapper_config_context,\r
- p_adapter , &mac, &len);\r
- if( status != NDIS_STATUS_SUCCESS )\r
- {\r
- cl_obj_destroy( &p_adapter->obj );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ipoib_get_adapter_params returned 0x%.8x.\n", status) );\r
- return status;\r
- }\r
- \r
- status = adapter_init( p_adapter );\r
- if( status != IB_SUCCESS )\r
- {\r
- cl_obj_destroy( &p_adapter->obj );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("adapter_init returned %s.\n", \r
- p_adapter->p_ifc->get_err_str( status )) );\r
- return status;\r
- }\r
-\r
- ETH_COPY_NETWORK_ADDRESS( p_adapter->params.conf_mac.addr, p_adapter->mac.addr );\r
- /* If there is a NetworkAddress override in registry, use it */\r
- if( (status == NDIS_STATUS_SUCCESS) && (len == HW_ADDR_LEN) )\r
- {\r
- if( ETH_IS_MULTICAST(mac) || ETH_IS_BROADCAST(mac) ||\r
- !ETH_IS_LOCALLY_ADMINISTERED(mac) )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_INIT,\r
- ("Overriding NetworkAddress is invalid - "\r
- "%02x-%02x-%02x-%02x-%02x-%02x\n",\r
- mac[0], mac[1], mac[2],\r
- mac[3], mac[4], mac[5]) );\r
- }\r
- else\r
- {\r
- ETH_COPY_NETWORK_ADDRESS( p_adapter->params.conf_mac.addr, mac );\r
- }\r
- }\r
-\r
- *pp_adapter = p_adapter;\r
-\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
- return status;\r
-}\r
-\r
-\r
-ib_api_status_t\r
-ipoib_start_adapter(\r
- IN ipoib_adapter_t* const p_adapter )\r
-{\r
- ib_api_status_t status;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-\r
- status = __ipoib_pnp_reg( p_adapter,\r
- IB_PNP_FLAG_REG_SYNC | IB_PNP_FLAG_REG_COMPLETE );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
- return status;\r
-}\r
-\r
-\r
-void\r
-ipoib_destroy_adapter(\r
- IN ipoib_adapter_t* const p_adapter )\r
-{\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-\r
- CL_ASSERT( p_adapter );\r
-\r
- /*\r
- * Flag the adapter as being removed. We use the IB_PNP_PORT_REMOVE state\r
- * for this purpose. Note that we protect this state change with both the\r
- * mutex and the lock. The mutex provides synchronization as a whole\r
- * between destruction and AL callbacks (PnP, Query, Destruction).\r
- * The lock provides protection\r
- */\r
- KeWaitForMutexObject(\r
- &p_adapter->mutex, Executive, KernelMode, FALSE, NULL );\r
- cl_obj_lock( &p_adapter->obj );\r
- p_adapter->state = IB_PNP_PORT_REMOVE;\r
-\r
- /*\r
- * Clear the pointer to the port object since the object destruction\r
- * will cascade to child objects. This prevents potential duplicate\r
- * destruction (or worse, stale pointer usage).\r
- */\r
- p_adapter->p_port = NULL;\r
-\r
- cl_obj_unlock( &p_adapter->obj );\r
-\r
- KeReleaseMutex( &p_adapter->mutex, FALSE );\r
-\r
- cl_obj_destroy( &p_adapter->obj );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
-}\r
-\r
-\r
-static void\r
-adapter_construct(\r
- IN ipoib_adapter_t* const p_adapter )\r
-{\r
- cl_obj_construct( &p_adapter->obj, IPOIB_OBJ_INSTANCE );\r
- cl_spinlock_construct( &p_adapter->send_stat_lock );\r
- cl_spinlock_construct( &p_adapter->recv_stat_lock );\r
- cl_qpool_construct( &p_adapter->item_pool );\r
- KeInitializeMutex( &p_adapter->mutex, 0 );\r
-\r
- cl_thread_construct(&p_adapter->destroy_thread);\r
- \r
- cl_vector_construct( &p_adapter->ip_vector );\r
-\r
- cl_perf_construct( &p_adapter->perf );\r
-\r
- p_adapter->state = IB_PNP_PORT_ADD;\r
- p_adapter->port_rate = FOUR_X_IN_100BPS;\r
-}\r
-\r
-\r
-static ib_api_status_t\r
-adapter_init(\r
- IN ipoib_adapter_t* const p_adapter )\r
-{\r
- cl_status_t cl_status;\r
- ib_api_status_t status;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-\r
- cl_status = cl_perf_init( &p_adapter->perf, MaxPerf );\r
- if( cl_status != CL_SUCCESS )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("cl_perf_init returned %#x\n", cl_status) );\r
- return IB_ERROR;\r
- }\r
-\r
- cl_status = cl_spinlock_init( &p_adapter->send_stat_lock );\r
- if( cl_status != CL_SUCCESS )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("cl_spinlock_init returned %#x\n", cl_status) );\r
- return IB_ERROR;\r
- }\r
-\r
- cl_status = cl_spinlock_init( &p_adapter->recv_stat_lock );\r
- if( cl_status != CL_SUCCESS )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("cl_spinlock_init returned %#x\n", cl_status) );\r
- return IB_ERROR;\r
- }\r
-\r
- cl_status = cl_qpool_init( &p_adapter->item_pool, ITEM_POOL_START, 0,\r
- ITEM_POOL_GROW, sizeof(cl_pool_obj_t), NULL, NULL, NULL );\r
- if( cl_status != CL_SUCCESS )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("cl_qpool_init returned %#x\n", cl_status) );\r
- return IB_ERROR;\r
- }\r
-\r
-\r
- /* We manually manage the size and capacity of the vector. */\r
- cl_status = cl_vector_init( &p_adapter->ip_vector, 0,\r
- 0, sizeof(net_address_item_t), NULL, NULL, p_adapter );\r
- if( cl_status != CL_SUCCESS )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("cl_vector_init for ip_vector returned %#x\n",\r
- cl_status) );\r
- return IB_ERROR;\r
- }\r
-\r
- /* Validate the port GUID and generate the MAC address. */\r
- status =\r
- ipoib_mac_from_guid( p_adapter->guids.port_guid.guid, p_adapter->params.guid_mask, &p_adapter->mac);\r
- if( status != IB_SUCCESS )\r
- {\r
- if( status == IB_INVALID_GUID_MASK )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_ERROR,\r
- ("Invalid GUID mask received, rejecting it") );\r
- ipoib_create_log(p_adapter->h_adapter, GUID_MASK_LOG_INDEX, EVENT_IPOIB_WRONG_PARAMETER_WRN);\r
- }\r
-\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ipoib_mac_from_guid returned %s\n", \r
- p_adapter->p_ifc->get_err_str( status )) );\r
- return status;\r
- }\r
-\r
- /* Open AL. */\r
- status = p_adapter->p_ifc->open_al( &p_adapter->h_al );\r
- if( status != IB_SUCCESS )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ib_open_al returned %s\n", \r
- p_adapter->p_ifc->get_err_str( status )) );\r
- return status;\r
- }\r
-\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
- return status;\r
-}\r
-\r
-\r
-static ib_api_status_t\r
-__ipoib_pnp_reg(\r
- IN ipoib_adapter_t* const p_adapter,\r
- IN ib_pnp_class_t flags )\r
-{\r
- ib_api_status_t status;\r
- ib_pnp_req_t pnp_req;\r
- \r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-\r
- CL_ASSERT( !p_adapter->h_pnp );\r
- CL_ASSERT( !p_adapter->registering );\r
-\r
- p_adapter->registering = TRUE;\r
- \r
- /* Register for PNP events. */\r
- cl_memclr( &pnp_req, sizeof(pnp_req) );\r
- pnp_req.pnp_class = IB_PNP_PORT | flags;\r
- /*\r
- * Context is the cl_obj of the adapter to allow passing cl_obj_deref\r
- * to ib_dereg_pnp.\r
- */\r
- pnp_req.pnp_context = &p_adapter->obj;\r
- pnp_req.pfn_pnp_cb = __ipoib_pnp_cb;\r
- status = p_adapter->p_ifc->reg_pnp( p_adapter->h_al, &pnp_req, &p_adapter->h_pnp );\r
- if( status != IB_SUCCESS )\r
- {\r
- ASSERT(FALSE);\r
- p_adapter->registering = FALSE;\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ib_reg_pnp returned %s\n", \r
- p_adapter->p_ifc->get_err_str( status )) );\r
- return status;\r
- }\r
- /*\r
- * Reference the adapter on behalf of the PNP registration.\r
- * This allows the destruction to block until the PNP deregistration\r
- * completes.\r
- */\r
- cl_obj_ref( &p_adapter->obj );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
- return status;\r
-}\r
-\r
-\r
-static void\r
-__adapter_destroying(\r
- IN cl_obj_t* const p_obj )\r
-{\r
- ipoib_adapter_t *p_adapter;\r
- KLOCK_QUEUE_HANDLE hdl;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-\r
- p_adapter = PARENT_STRUCT( p_obj, ipoib_adapter_t, obj );\r
-\r
- /*\r
- * The adapter's object will be dereferenced when the deregistration\r
- * completes. No need to lock here since all PnP related API calls\r
- * are driven by NDIS (via the Init/Reset/Destroy paths).\r
- */\r
- if( p_adapter->h_pnp )\r
- {\r
- p_adapter->p_ifc->dereg_pnp( p_adapter->h_pnp, cl_obj_deref );\r
- p_adapter->h_pnp = NULL;\r
- }\r
-\r
- if( p_adapter->packet_filter )\r
- {\r
- KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
- cl_obj_lock( &p_adapter->obj );\r
-\r
- ASSERT( cl_qlist_count( &g_ipoib.adapter_list ) );\r
- cl_qlist_remove_item( &g_ipoib.adapter_list, &p_adapter->entry );\r
-\r
- p_adapter->packet_filter = 0;\r
-\r
- cl_obj_unlock( &p_adapter->obj );\r
- KeReleaseInStackQueuedSpinLock( &hdl );\r
- }\r
-\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
-}\r
-\r
-\r
-static void\r
-__adapter_free(\r
- IN cl_obj_t* const p_obj )\r
-{\r
- ipoib_adapter_t *p_adapter;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-\r
- p_adapter = PARENT_STRUCT( p_obj, ipoib_adapter_t, obj );\r
-\r
- if( p_adapter->p_ifc )\r
- {\r
- if( p_adapter->h_al )\r
- p_adapter->p_ifc->close_al( p_adapter->h_al );\r
-\r
- cl_free( p_adapter->p_ifc );\r
- p_adapter->p_ifc = NULL;\r
- }\r
-\r
- cl_vector_destroy( &p_adapter->ip_vector );\r
- cl_qpool_destroy( &p_adapter->item_pool );\r
- cl_spinlock_destroy( &p_adapter->recv_stat_lock );\r
- cl_spinlock_destroy( &p_adapter->send_stat_lock );\r
- cl_obj_deinit( p_obj );\r
-\r
- cl_perf_destroy( &p_adapter->perf, TRUE );\r
-\r
- cl_free( p_adapter );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
-}\r
-\r
-\r
-static ib_api_status_t\r
-ipoib_query_pkey_index(ipoib_adapter_t *p_adapter)\r
-{\r
- ib_api_status_t status;\r
- ib_ca_attr_t *ca_attr;\r
- uint32_t ca_size;\r
- uint16_t index = 0;\r
-\r
- /* Query the CA for Pkey table */\r
- status = p_adapter->p_ifc->query_ca(p_adapter->p_port->ib_mgr.h_ca, NULL, &ca_size);\r
- if(status != IB_INSUFFICIENT_MEMORY)\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ib_query_ca failed\n"));\r
- return status;\r
- }\r
-\r
- ca_attr = (ib_ca_attr_t*)cl_zalloc(ca_size);\r
- if (!ca_attr)\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("cl_zalloc can't allocate %d\n",ca_size));\r
- return IB_INSUFFICIENT_MEMORY;\r
- }\r
-\r
- status = p_adapter->p_ifc->query_ca(p_adapter->p_port->ib_mgr.h_ca, ca_attr,&ca_size); \r
- if( status != IB_SUCCESS )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ib_query_ca returned %s\n", \r
- p_adapter->p_ifc->get_err_str( status )) );\r
- goto pkey_end;\r
- }\r
- CL_ASSERT(ca_attr->p_port_attr[p_adapter->p_port->port_num -1].p_pkey_table[0] == IB_DEFAULT_PKEY);\r
- for(index = 0; index < ca_attr->p_port_attr[p_adapter->p_port->port_num -1].num_pkeys; index++)\r
- {\r
- 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])\r
- break;\r
- }\r
- if(index >= ca_attr->p_port_attr[p_adapter->p_port->port_num -1].num_pkeys)\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Pkey table is invalid, index not found\n"));\r
- NdisWriteErrorLogEntry( p_adapter->h_adapter,\r
- EVENT_IPOIB_PARTITION_ERR, 1, p_adapter->guids.port_guid.pkey );\r
- status = IB_NOT_FOUND;\r
- p_adapter->p_port->pkey_index = PKEY_INVALID_INDEX;\r
- goto pkey_end;\r
- }\r
-\r
- p_adapter->p_port->pkey_index = index;\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_IB,\r
- ("for PKEY = 0x%04X got index = %d\n",p_adapter->guids.port_guid.pkey,index));\r
-\r
-pkey_end:\r
- if(ca_attr)\r
- cl_free(ca_attr);\r
- return status;\r
-}\r
-\r
-static ib_api_status_t\r
-__ipoib_pnp_cb(\r
- IN ib_pnp_rec_t *p_pnp_rec )\r
-{\r
- ipoib_adapter_t *p_adapter;\r
- ipoib_port_t *p_port;\r
- ib_pnp_event_t old_state;\r
- ib_pnp_port_rec_t *p_port_rec;\r
- ib_api_status_t status = IB_SUCCESS;\r
- NDIS_LINK_STATE link_state;\r
- NDIS_STATUS_INDICATION status_indication;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_PNP );\r
-\r
- CL_ASSERT( p_pnp_rec );\r
- NdisZeroMemory(&link_state, sizeof(NDIS_LINK_STATE));\r
- p_adapter =\r
- PARENT_STRUCT( p_pnp_rec->pnp_context, ipoib_adapter_t, obj );\r
-\r
- CL_ASSERT( p_adapter );\r
-\r
- /* Synchronize with destruction */\r
- KeWaitForMutexObject(\r
- &p_adapter->mutex, Executive, KernelMode, FALSE, NULL );\r
- cl_obj_lock( &p_adapter->obj );\r
- old_state = p_adapter->state;\r
- cl_obj_unlock( &p_adapter->obj );\r
- if( old_state == IB_PNP_PORT_REMOVE )\r
- {\r
- KeReleaseMutex( &p_adapter->mutex, FALSE );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_PNP,\r
- ("Aborting - Adapter destroying.\n") );\r
- return IB_NOT_DONE;\r
- }\r
-\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_PNP,\r
- ("p_pnp_rec->pnp_event = 0x%x (%s)\n",\r
- p_pnp_rec->pnp_event, ib_get_pnp_event_str( p_pnp_rec->pnp_event )) );\r
-\r
- p_port_rec = (ib_pnp_port_rec_t*)p_pnp_rec;\r
-\r
- switch( p_pnp_rec->pnp_event )\r
- {\r
- case IB_PNP_PORT_ADD:\r
- CL_ASSERT( !p_pnp_rec->context );\r
- /* Only process our port GUID. */\r
- if( p_pnp_rec->guid != p_adapter->guids.port_guid.guid )\r
- {\r
- status = IB_NOT_DONE;\r
- break;\r
- }\r
-\r
- /* Don't process if we're destroying. */\r
- if( p_adapter->obj.state == CL_DESTROYING )\r
- {\r
- status = IB_NOT_DONE;\r
- break;\r
- }\r
-\r
- CL_ASSERT( !p_adapter->p_port );\r
- /* Allocate all IB resources. */\r
- cl_obj_lock( &p_adapter->obj );\r
- p_adapter->state = IB_PNP_PORT_ADD;\r
- cl_obj_unlock( &p_adapter->obj );\r
- status = ipoib_create_port( p_adapter, p_port_rec, &p_port );\r
- cl_obj_lock( &p_adapter->obj );\r
- if( status != IB_SUCCESS )\r
- {\r
- p_adapter->state = old_state;\r
- cl_obj_unlock( &p_adapter->obj );\r
- p_adapter->hung = TRUE;\r
- break;\r
- }\r
-\r
- p_pnp_rec->context = p_port;\r
-\r
- p_adapter->p_port = p_port;\r
- cl_obj_unlock( &p_adapter->obj );\r
- break;\r
-\r
- case IB_PNP_PORT_REMOVE:\r
- /* Release all IB resources. */\r
- CL_ASSERT( p_pnp_rec->context );\r
-\r
- cl_obj_lock( &p_adapter->obj );\r
- p_adapter->state = IB_PNP_PORT_REMOVE;\r
- p_port = p_adapter->p_port;\r
- p_adapter->p_port = NULL;\r
- cl_obj_unlock( &p_adapter->obj );\r
- ipoib_port_destroy( p_port );\r
- p_pnp_rec->context = NULL;\r
- status = IB_SUCCESS;\r
- break;\r
-\r
- case IB_PNP_PORT_ACTIVE:\r
- /* Join multicast groups and put QP in RTS. */\r
- CL_ASSERT( p_pnp_rec->context );\r
-\r
- cl_obj_lock( &p_adapter->obj );\r
- p_adapter->state = IB_PNP_PORT_INIT;\r
- cl_obj_unlock( &p_adapter->obj );\r
- ipoib_port_up( p_adapter->p_port, p_port_rec );\r
-\r
- status = IB_SUCCESS;\r
- break;\r
-\r
- case IB_PNP_PORT_ARMED:\r
- status = IB_SUCCESS;\r
- break;\r
-\r
- case IB_PNP_PORT_INIT:\r
- /*\r
- * Init could happen if the SM brings the port down\r
- * without changing the physical link.\r
- */\r
- case IB_PNP_PORT_DOWN:\r
- CL_ASSERT( p_pnp_rec->context );\r
-\r
- cl_obj_lock( &p_adapter->obj );\r
- old_state = p_adapter->state;\r
- p_adapter->state = IB_PNP_PORT_DOWN;\r
- cl_obj_unlock( &p_adapter->obj );\r
- status = IB_SUCCESS;\r
-\r
- if( !p_adapter->registering && old_state != IB_PNP_PORT_DOWN )\r
- {\r
- link_state.Header.Revision = NDIS_LINK_STATE_REVISION_1;\r
- link_state.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;\r
- link_state.Header.Size = sizeof(NDIS_LINK_STATE);\r
- link_state.MediaConnectState = MediaConnectStateDisconnected;\r
- //link_state.MediaConnectState = MediaConnectStateConnected;\r
- link_state.MediaDuplexState = MediaDuplexStateFull;\r
- link_state.XmitLinkSpeed = link_state.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED;\r
-\r
- IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication,\r
- p_adapter->h_adapter,\r
- NDIS_STATUS_LINK_STATE,\r
- (PVOID)&link_state,\r
- sizeof(link_state));\r
-\r
- NdisMIndicateStatusEx(p_adapter->h_adapter,&status_indication);\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
- ("Link DOWN!\n") );\r
-\r
- ipoib_port_down( p_adapter->p_port );\r
- }\r
- break;\r
-\r
- case IB_PNP_REG_COMPLETE:\r
- if( p_adapter->registering )\r
- {\r
- p_adapter->registering = FALSE;\r
- cl_obj_lock( &p_adapter->obj );\r
- old_state = p_adapter->state;\r
- cl_obj_unlock( &p_adapter->obj );\r
-\r
- if( old_state == IB_PNP_PORT_DOWN )\r
- {\r
- /* If we were initializing, we might have pended some OIDs. */\r
- ipoib_resume_oids( p_adapter );\r
-\r
- link_state.Header.Revision = NDIS_LINK_STATE_REVISION_1;\r
- link_state.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;\r
- link_state.Header.Size = sizeof(NDIS_LINK_STATE);\r
- link_state.MediaConnectState = MediaConnectStateDisconnected;\r
- //link_state.MediaConnectState = MediaConnectStateConnected;\r
- link_state.MediaDuplexState = MediaDuplexStateFull;\r
- link_state.XmitLinkSpeed = link_state.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED;\r
-\r
- IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication,\r
- p_adapter->h_adapter,\r
- NDIS_STATUS_LINK_STATE,\r
- (PVOID)&link_state,\r
- sizeof(link_state));\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_INIT,\r
- ("Indicate DISCONNECT\n") );\r
- NdisMIndicateStatusEx(p_adapter->h_adapter,&status_indication); \r
- }\r
- }\r
-\r
- if( p_adapter->reset && p_adapter->state != IB_PNP_PORT_INIT )\r
- {\r
- p_adapter->reset = FALSE;\r
- NdisMResetComplete(\r
- p_adapter->h_adapter, NDIS_STATUS_SUCCESS, TRUE );\r
- }\r
- status = IB_SUCCESS;\r
- break;\r
-\r
- default:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
- ("IPOIB: Received unhandled PnP event 0x%x (%s)\n",\r
- p_pnp_rec->pnp_event, ib_get_pnp_event_str( p_pnp_rec->pnp_event )) );\r
- /* Fall through. */\r
-\r
- status = IB_SUCCESS;\r
-\r
- /* We ignore events below if the link is not active. */\r
- if( p_port_rec->p_port_attr->link_state != IB_LINK_ACTIVE )\r
- break;\r
-\r
- case IB_PNP_PKEY_CHANGE:\r
- if(p_pnp_rec->pnp_event == IB_PNP_PKEY_CHANGE && \r
- p_adapter->guids.port_guid.pkey != IB_DEFAULT_PKEY)\r
- {\r
- status = ipoib_query_pkey_index(p_adapter);\r
- if(status != IB_SUCCESS)\r
- {\r
- cl_obj_lock( &p_adapter->obj );\r
- p_adapter->state = IB_PNP_PORT_INIT;\r
- cl_obj_unlock( &p_adapter->obj );\r
- }\r
- }\r
-\r
- case IB_PNP_SM_CHANGE:\r
- case IB_PNP_GID_CHANGE:\r
- case IB_PNP_LID_CHANGE:\r
-\r
- cl_obj_lock( &p_adapter->obj );\r
- old_state = p_adapter->state;\r
- switch( old_state )\r
- {\r
- case IB_PNP_PORT_DOWN:\r
- p_adapter->state = IB_PNP_PORT_INIT;\r
- break;\r
-\r
- default:\r
- p_adapter->state = IB_PNP_PORT_DOWN;\r
- }\r
- cl_obj_unlock( &p_adapter->obj );\r
- \r
- if( p_adapter->registering )\r
- break;\r
-\r
- switch( old_state )\r
- {\r
- case IB_PNP_PORT_ACTIVE:\r
- case IB_PNP_PORT_INIT:\r
- link_state.Header.Revision = NDIS_LINK_STATE_REVISION_1;\r
- link_state.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;\r
- link_state.Header.Size = sizeof(NDIS_LINK_STATE);\r
- link_state.MediaConnectState = MediaConnectStateDisconnected;\r
- //link_state.MediaConnectState = MediaConnectStateConnected;\r
- link_state.MediaDuplexState = MediaDuplexStateFull;\r
- link_state.XmitLinkSpeed = link_state.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED;\r
-\r
- IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication,\r
- p_adapter->h_adapter,\r
- NDIS_STATUS_LINK_STATE,\r
- (PVOID)&link_state,\r
- sizeof(link_state));\r
-\r
- NdisMIndicateStatusEx(p_adapter->h_adapter,&status_indication); \r
-\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
- ("Link DOWN!\n") );\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_INIT,\r
- ("Indicate DISCONNECT\n") );\r
-\r
- ipoib_port_down( p_adapter->p_port );\r
- /* Fall through. */\r
-\r
- case IB_PNP_PORT_DOWN:\r
- cl_obj_lock( &p_adapter->obj );\r
- p_adapter->state = IB_PNP_PORT_INIT;\r
- cl_obj_unlock( &p_adapter->obj );\r
- ipoib_port_up( p_adapter->p_port, (ib_pnp_port_rec_t*)p_pnp_rec );\r
- }\r
- break;\r
- }\r
-\r
- KeReleaseMutex( &p_adapter->mutex, FALSE );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_PNP );\r
- return status;\r
-}\r
-\r
-\r
-/* Joins/leaves mcast groups based on currently programmed mcast MACs. */\r
-void\r
-ipoib_refresh_mcast(\r
- IN ipoib_adapter_t* const p_adapter,\r
- IN mac_addr_t* const p_mac_array,\r
- IN const uint8_t num_macs )\r
-{\r
- uint8_t i, j;\r
- ipoib_port_t *p_port = NULL;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_MCAST );\r
- cl_obj_lock( &p_adapter->obj );\r
- if( p_adapter->state == IB_PNP_PORT_ACTIVE )\r
- {\r
- p_port = p_adapter->p_port;\r
- ipoib_port_ref( p_port, ref_refresh_mcast );\r
- }\r
- cl_obj_unlock( &p_adapter->obj );\r
-\r
- if( p_port )\r
- {\r
- /* Purge old entries. */\r
- for( i = 0; i < p_adapter->mcast_array_size; i++ )\r
- {\r
- for( j = 0; j < num_macs; j++ )\r
- {\r
- if( !cl_memcmp( &p_adapter->mcast_array[i], &p_mac_array[j],\r
- sizeof(mac_addr_t) ) )\r
- {\r
- break;\r
- }\r
- }\r
- if( j != num_macs )\r
- continue;\r
-\r
- ipoib_port_remove_endpt( p_port, p_adapter->mcast_array[i] );\r
- }\r
-\r
- /* Add new entries */\r
- for( i = 0; i < num_macs; i++ )\r
- {\r
- for( j = 0; j < p_adapter->mcast_array_size; j++ )\r
- {\r
- if( !cl_memcmp( &p_adapter->mcast_array[j], &p_mac_array[i],\r
- sizeof(mac_addr_t) ) )\r
- {\r
- break;\r
- }\r
- }\r
-\r
- if( j != p_adapter->mcast_array_size )\r
- continue;\r
- if ( ( p_mac_array[i].addr[0] == 1 && p_mac_array[i].addr[1] == 0 && p_mac_array[i].addr[2] == 0x5e &&\r
- p_mac_array[i].addr[3] == 0 && p_mac_array[i].addr[4] == 0 && p_mac_array[i].addr[5] == 1 ) ||\r
- !( p_mac_array[i].addr[0] == 1 && p_mac_array[i].addr[1] == 0 && p_mac_array[i].addr[2] == 0x5e )\r
- )\r
- {\r
- ipoib_port_join_mcast( p_port, p_mac_array[i], IB_MC_REC_STATE_FULL_MEMBER );\r
- }\r
- }\r
- }\r
-\r
- /* Copy the MAC array. */\r
- NdisMoveMemory( p_adapter->mcast_array, p_mac_array,\r
- num_macs * sizeof(mac_addr_t) );\r
- p_adapter->mcast_array_size = num_macs;\r
-\r
- if( p_port )\r
- ipoib_port_deref( p_port, ref_refresh_mcast );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_MCAST );\r
-}\r
-\r
-\r
-ib_api_status_t\r
-ipoib_reset_adapter(\r
- IN ipoib_adapter_t* const p_adapter )\r
-{\r
- ib_api_status_t status;\r
- ib_pnp_handle_t h_pnp;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-\r
- if( p_adapter->reset )\r
- return IB_INVALID_STATE;\r
-\r
- p_adapter->hung = FALSE;\r
- p_adapter->reset = TRUE;\r
-\r
- if( p_adapter->h_pnp )\r
- {\r
- h_pnp = p_adapter->h_pnp;\r
- p_adapter->h_pnp = NULL;\r
- status = p_adapter->p_ifc->dereg_pnp( h_pnp, __ipoib_pnp_dereg );\r
- if( status == IB_SUCCESS )\r
- status = IB_NOT_DONE;\r
- }\r
- else\r
- {\r
- status = __ipoib_pnp_reg( p_adapter, IB_PNP_FLAG_REG_COMPLETE );\r
- if( status == IB_SUCCESS )\r
- p_adapter->hung = FALSE;\r
- }\r
- if (status == IB_NOT_DONE) {\r
- p_adapter->reset = TRUE;\r
- }\r
- else {\r
- p_adapter->reset = FALSE;\r
- }\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
- return status;\r
-}\r
-\r
-\r
-static void\r
-__ipoib_pnp_dereg(\r
- IN void* context )\r
-{\r
- ipoib_adapter_t* p_adapter;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-\r
- p_adapter = PARENT_STRUCT( context, ipoib_adapter_t, obj );\r
-\r
- cl_thread_init(&p_adapter->destroy_thread, __ipoib_adapter_reset, (void*)p_adapter, "destroy_thread");\r
- \r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-\r
-}\r
-\r
-static void\r
-__ipoib_adapter_reset(\r
- IN void* context)\r
-{\r
-\r
- ipoib_adapter_t *p_adapter;\r
- ipoib_port_t *p_port;\r
- ib_api_status_t status;\r
- ib_pnp_event_t state;\r
- \r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Got RESET\n") );\r
-// return;\r
- p_adapter = (ipoib_adapter_t*)context;\r
- \r
- /* Synchronize with destruction */\r
- KeWaitForMutexObject(\r
- &p_adapter->mutex, Executive, KernelMode, FALSE, NULL );\r
-\r
- cl_obj_lock( &p_adapter->obj );\r
-\r
- CL_ASSERT( !p_adapter->h_pnp );\r
-\r
- if( p_adapter->state != IB_PNP_PORT_REMOVE )\r
- p_adapter->state = IB_PNP_PORT_ADD;\r
-\r
- state = p_adapter->state;\r
-\r
- /* Destroy the current port instance if it still exists. */\r
- p_port = p_adapter->p_port;\r
- p_adapter->p_port = NULL;\r
- cl_obj_unlock( &p_adapter->obj );\r
-\r
- if( p_port )\r
- ipoib_port_destroy( p_port );\r
- ASSERT(p_adapter->reset == TRUE);\r
- if( state != IB_PNP_PORT_REMOVE )\r
- {\r
- status = __ipoib_pnp_reg( p_adapter, IB_PNP_FLAG_REG_COMPLETE );\r
- if( status != IB_SUCCESS )\r
- {\r
- p_adapter->reset = FALSE;\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("__ipoib_pnp_reg returned %s\n",\r
- p_adapter->p_ifc->get_err_str( status )) );\r
- NdisMResetComplete( \r
- p_adapter->h_adapter, NDIS_STATUS_HARD_ERRORS, TRUE );\r
- }\r
- }\r
- else\r
- {\r
- p_adapter->reset = FALSE;\r
- NdisMResetComplete(\r
- p_adapter->h_adapter, NDIS_STATUS_SUCCESS, TRUE );\r
- status = IB_SUCCESS;\r
- }\r
-\r
- /* Dereference the adapter since the previous registration is now gone. */\r
- cl_obj_deref( &p_adapter->obj );\r
-\r
- KeReleaseMutex( &p_adapter->mutex, FALSE );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
-}\r
-\r
-\r
-void\r
-ipoib_set_rate(\r
- IN ipoib_adapter_t* const p_adapter,\r
- IN const uint8_t link_width, \r
- IN const uint8_t link_speed )\r
-{\r
- uint32_t rate;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-\r
- /* Set the link speed based on the IB link speed (1x vs 4x, etc). */\r
- switch( link_speed )\r
- {\r
- case IB_LINK_SPEED_ACTIVE_2_5:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
- ("Link speed is 2.5Gs\n") );\r
- rate = IB_LINK_SPEED_ACTIVE_2_5;\r
- break;\r
-\r
- case IB_LINK_SPEED_ACTIVE_5:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
- ("Link speed is 5G\n") );\r
- rate = IB_LINK_SPEED_ACTIVE_5;\r
- break;\r
-\r
- case IB_LINK_SPEED_ACTIVE_10:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
- ("Link speed is 10G\n") );\r
- rate = IB_LINK_SPEED_ACTIVE_10;\r
- break;\r
-\r
- default:\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Invalid link speed %d.\n", link_speed) );\r
- rate = 0;\r
- }\r
-\r
- switch( link_width )\r
- {\r
- case IB_LINK_WIDTH_ACTIVE_1X:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
- ("Link width is 1X\n") );\r
- rate *= ONE_X_IN_100BPS;\r
- break;\r
-\r
- case IB_LINK_WIDTH_ACTIVE_4X:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
- ("Link width is 4X\n") );\r
- rate *= FOUR_X_IN_100BPS;\r
- break;\r
-\r
- case IB_LINK_WIDTH_ACTIVE_12X:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
- ("Link width is 12X\n") );\r
- rate *= TWELVE_X_IN_100BPS;\r
- break;\r
-\r
- default:\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Invalid link rate (%d).\n", link_width) );\r
- rate = 0;\r
- }\r
-\r
- p_adapter->port_rate = rate;\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
-}\r
-\r
-\r
-ib_api_status_t\r
-ipoib_set_active(\r
- IN ipoib_adapter_t* const p_adapter )\r
-{\r
- ib_pnp_event_t old_state;\r
- uint8_t i;\r
- ib_api_status_t status = IB_SUCCESS;\r
- NDIS_LINK_STATE link_state;\r
- NDIS_STATUS_INDICATION status_indication;\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-\r
- NdisZeroMemory(&link_state, sizeof(NDIS_LINK_STATE));\r
- cl_obj_lock( &p_adapter->obj );\r
- old_state = p_adapter->state;\r
-\r
- /* Change the state to indicate that we are now connected and live. */\r
- if( old_state == IB_PNP_PORT_INIT )\r
- p_adapter->state = IB_PNP_PORT_ACTIVE;\r
-\r
- cl_obj_unlock( &p_adapter->obj );\r
-\r
- /*\r
- * If we had a pending OID request for OID_GEN_LINK_SPEED,\r
- * complete it now.\r
- */\r
- switch( old_state )\r
- {\r
- case IB_PNP_PORT_ADD:\r
- ipoib_reg_addrs( p_adapter );\r
- /* Fall through. */\r
-\r
- case IB_PNP_PORT_REMOVE:\r
- ipoib_resume_oids( p_adapter );\r
- break;\r
-\r
- default:\r
- if (p_adapter->guids.port_guid.pkey != IB_DEFAULT_PKEY)\r
- {\r
- status = ipoib_query_pkey_index(p_adapter);\r
- if( IB_SUCCESS != status)\r
- {\r
- break;\r
- }\r
- }\r
- /* Join all programmed multicast groups. */\r
- for( i = 0; i < p_adapter->mcast_array_size; i++ )\r
- {\r
- ipoib_port_join_mcast(\r
- p_adapter->p_port, p_adapter->mcast_array[i] ,IB_MC_REC_STATE_FULL_MEMBER);\r
- }\r
-\r
- /* Register all existing addresses. */\r
- ipoib_reg_addrs( p_adapter );\r
-\r
- ipoib_resume_oids( p_adapter );\r
-\r
- /*\r
- * Now that we're in the broadcast group, notify that\r
- * we have a link.\r
- */\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, ("Link UP!\n") );\r
- NdisWriteErrorLogEntry( p_adapter->h_adapter,\r
- EVENT_IPOIB_PORT_UP + (p_adapter->port_rate/ONE_X_IN_100BPS),\r
- 1, p_adapter->port_rate );\r
-\r
- if( !p_adapter->reset )\r
- {\r
- link_state.Header.Revision = NDIS_LINK_STATE_REVISION_1;\r
- link_state.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;\r
- link_state.Header.Size = sizeof(NDIS_LINK_STATE);\r
- link_state.MediaConnectState = MediaConnectStateConnected;\r
- link_state.MediaDuplexState = MediaDuplexStateFull;\r
- link_state.XmitLinkSpeed = \r
- link_state.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED;\r
- link_state.PauseFunctions = NdisPauseFunctionsSendAndReceive;\r
- IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication,\r
- p_adapter->h_adapter,\r
- NDIS_STATUS_LINK_STATE,\r
- (PVOID)&link_state,\r
- sizeof(link_state));\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, ("***************Indicate connect!\n") );\r
- NdisMIndicateStatusEx(p_adapter->h_adapter,&status_indication);\r
- }\r
- }\r
-\r
- if( p_adapter->reset )\r
- {\r
- ASSERT(FALSE);\r
- p_adapter->reset = FALSE;\r
- NdisMResetComplete(\r
- p_adapter->h_adapter, NDIS_STATUS_SUCCESS, TRUE );\r
- }\r
-\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
- return status;\r
-}\r
-\r
-/*\r
- * If something goes wrong after the port goes active, e.g.\r
- * - PortInfo query failure\r
- * - MC Join timeout\r
- * - etc\r
- * Mark the port state as down, resume any pended OIDS, etc.\r
- */\r
-void\r
-ipoib_set_inactive(\r
- IN ipoib_adapter_t* const p_adapter )\r
-{\r
- ib_pnp_event_t old_state;\r
- NDIS_LINK_STATE link_state;\r
- NDIS_STATUS_INDICATION status_indication;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-\r
- NdisZeroMemory(&link_state, sizeof(NDIS_LINK_STATE));\r
- cl_obj_lock( &p_adapter->obj );\r
- old_state = p_adapter->state;\r
- if( old_state != IB_PNP_PORT_REMOVE )\r
- p_adapter->state = IB_PNP_PORT_DOWN;\r
- cl_obj_unlock( &p_adapter->obj );\r
-\r
- /*\r
- * If we had a pending OID request for OID_GEN_LINK_SPEED,\r
- * complete it now.\r
- */\r
- if( old_state == IB_PNP_PORT_INIT )\r
- {\r
- link_state.Header.Revision = NDIS_LINK_STATE_REVISION_1;\r
- link_state.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;\r
- link_state.Header.Size = sizeof(NDIS_LINK_STATE);\r
- link_state.MediaConnectState = MediaConnectStateDisconnected;\r
- //link_state.MediaConnectState = MediaConnectStateConnected;\r
- \r
- link_state.MediaDuplexState = MediaDuplexStateFull;\r
- link_state.XmitLinkSpeed = link_state.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED;\r
-\r
- IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication,\r
- p_adapter->h_adapter,\r
- NDIS_STATUS_LINK_STATE,\r
- (PVOID)&link_state,\r
- sizeof(link_state));\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, ("Indicate Disconnect!\n") );\r
- NdisMIndicateStatusEx(p_adapter->h_adapter,&status_indication);\r
-\r
- ipoib_resume_oids( p_adapter );\r
- }\r
-\r
- if( p_adapter->reset )\r
- {\r
- p_adapter->reset = FALSE;\r
- NdisMResetComplete(\r
- p_adapter->h_adapter, NDIS_STATUS_SUCCESS, TRUE );\r
- }\r
-\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
-}\r
-\r
-NDIS_STATUS\r
-ipoib_get_gen_stat(\r
- IN ipoib_adapter_t* const p_adapter,\r
- OUT pending_oid_t* const p_oid_info)\r
-{\r
- PNDIS_STATISTICS_INFO StatisticsInfo;\r
- IPOIB_ENTER( IPOIB_DBG_STAT );\r
-\r
- if (p_oid_info->buf_len < sizeof(StatisticsInfo))\r
- {\r
- *p_oid_info->p_bytes_needed = sizeof(NDIS_STATISTICS_INFO);\r
- return NDIS_STATUS_INVALID_LENGTH;\r
- }\r
-\r
- StatisticsInfo = (PNDIS_STATISTICS_INFO)p_oid_info->p_buf;\r
- StatisticsInfo->Header.Revision = NDIS_OBJECT_REVISION_1;\r
- StatisticsInfo->Header.Type = NDIS_OBJECT_TYPE_DEFAULT;\r
- StatisticsInfo->Header.Size = sizeof(NDIS_STATISTICS_INFO);\r
- /*StatisticsInfo->SupportedStatistics = NDIS_STATISTICS_FLAGS_VALID_RCV_DISCARDS |\r
- NDIS_STATISTICS_FLAGS_VALID_RCV_ERROR |\r
- NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_RCV |\r
- NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_RCV |\r
- NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_RCV |\r
- NDIS_STATISTICS_FLAGS_VALID_BYTES_RCV | \r
- NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_RCV |\r
- NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_RCV |\r
- NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_RCV |\r
-\r
- NDIS_STATISTICS_FLAGS_VALID_XMIT_DISCARDS |\r
- NDIS_STATISTICS_FLAGS_VALID_XMIT_ERROR |\r
- NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_XMIT | \r
- NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_XMIT |\r
- NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_XMIT |\r
- NDIS_STATISTICS_FLAGS_VALID_BYTES_XMIT |\r
- NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_XMIT |\r
- NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_XMIT |\r
- NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_XMIT; */\r
- \r
- \r
- StatisticsInfo->SupportedStatistics = NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_RCV |\r
- //The data in the ifHCInUcastPkts member is valid. \r
- NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_RCV |\r
- //The data in the ifHCInMulticastPkts member is valid. \r
- NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_RCV |\r
- //The data in the ifHCInBroadcastPkts member is valid. \r
- NDIS_STATISTICS_FLAGS_VALID_BYTES_RCV |\r
- //The data in the ifHCInOctets member is valid. \r
- NDIS_STATISTICS_FLAGS_VALID_RCV_DISCARDS |\r
- //The data in the ifInDiscards member is valid. \r
- NDIS_STATISTICS_FLAGS_VALID_RCV_ERROR |\r
- //The data in the ifInErrors member is valid. \r
- NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_XMIT |\r
- //The data in the ifHCOutUcastPkts member is valid. \r
- NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_XMIT |\r
- //The data in the ifHCOutMulticastPkts member is valid. \r
- NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_XMIT |\r
- //The data in the ifHCOutBroadcastPkts member is valid. \r
- NDIS_STATISTICS_FLAGS_VALID_BYTES_XMIT |\r
- //The data in the ifHCOutOctets member is valid. \r
- NDIS_STATISTICS_FLAGS_VALID_XMIT_ERROR |\r
- //The data in the ifOutErrors member is valid. \r
- NDIS_STATISTICS_FLAGS_VALID_XMIT_DISCARDS |\r
- //The data in the ifOutDiscards member is valid. \r
- NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_RCV |\r
- //The data in the ifHCInUcastOctets member is valid. \r
- NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_RCV |\r
- //The data in the ifHCInMulticastOctets member is valid. \r
- NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_RCV |\r
- //The data in the ifHCInBroadcastOctets member is valid. \r
- NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_XMIT |\r
- //The data in the ifHCOutUcastOctets member is valid. \r
- NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_XMIT |\r
- //The data in the ifHCOutMulticastOctets member is valid. \r
- NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_XMIT ;\r
- //The data in the ifHCOutBroadcastOctets member is valid\r
-\r
- cl_spinlock_acquire( &p_adapter->recv_stat_lock );\r
- StatisticsInfo->ifInDiscards = p_adapter->recv_stats.comp.dropped +\r
- p_adapter->recv_stats.comp.error; \r
- StatisticsInfo->ifInErrors = p_adapter->recv_stats.comp.error;\r
- StatisticsInfo->ifHCInOctets = p_adapter->recv_stats.ucast.bytes + \r
- p_adapter->recv_stats.bcast.bytes + \r
- p_adapter->recv_stats.mcast.bytes; \r
- StatisticsInfo->ifHCInUcastPkts = p_adapter->recv_stats.ucast.frames;\r
- StatisticsInfo->ifHCInMulticastPkts = p_adapter->recv_stats.mcast.frames; \r
- StatisticsInfo->ifHCInBroadcastPkts = p_adapter->recv_stats.bcast.frames; \r
- StatisticsInfo->ifHCInMulticastOctets = p_adapter->recv_stats.mcast.bytes;\r
- StatisticsInfo->ifHCInBroadcastOctets = p_adapter->recv_stats.bcast.bytes;\r
- StatisticsInfo->ifHCInUcastOctets = p_adapter->recv_stats.ucast.bytes;\r
- cl_spinlock_release( &p_adapter->recv_stat_lock );\r
-\r
- cl_spinlock_acquire( &p_adapter->send_stat_lock ); \r
- StatisticsInfo->ifHCOutOctets = p_adapter->send_stats.ucast.bytes + \r
- p_adapter->send_stats.mcast.bytes + \r
- p_adapter->send_stats.bcast.bytes; \r
- StatisticsInfo->ifHCOutUcastPkts = p_adapter->send_stats.ucast.frames; \r
- StatisticsInfo->ifHCOutMulticastPkts = p_adapter->send_stats.mcast.frames; \r
- StatisticsInfo->ifHCOutBroadcastPkts = p_adapter->send_stats.bcast.frames; \r
- StatisticsInfo->ifOutErrors = p_adapter->send_stats.comp.error; \r
- StatisticsInfo->ifOutDiscards = p_adapter->send_stats.comp.dropped;\r
- StatisticsInfo->ifHCOutUcastOctets = p_adapter->send_stats.ucast.bytes;\r
- StatisticsInfo->ifHCOutMulticastOctets = p_adapter->send_stats.mcast.bytes;\r
- StatisticsInfo->ifHCOutBroadcastOctets = p_adapter->send_stats.bcast.bytes;\r
- cl_spinlock_release( &p_adapter->send_stat_lock );\r
-\r
- *p_oid_info->p_bytes_used = sizeof(NDIS_STATISTICS_INFO);\r
-\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
- return NDIS_STATUS_SUCCESS;\r
-}\r
-\r
-NDIS_STATUS\r
-ipoib_get_recv_stat(\r
- IN ipoib_adapter_t* const p_adapter,\r
- IN const ip_stat_sel_t stat_sel,\r
- IN pending_oid_t* const p_oid_info )\r
-{\r
- uint64_t stat;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_STAT );\r
-\r
- CL_ASSERT( p_adapter );\r
-\r
- cl_spinlock_acquire( &p_adapter->recv_stat_lock );\r
- switch( stat_sel )\r
- {\r
- case IP_STAT_SUCCESS:\r
- stat = p_adapter->recv_stats.comp.success;\r
- break;\r
-\r
- case IP_STAT_ERROR:\r
- stat = p_adapter->recv_stats.comp.error;\r
- break;\r
-\r
- case IP_STAT_DROPPED:\r
- stat = p_adapter->recv_stats.comp.dropped;\r
- break;\r
-\r
- case IP_STAT_UCAST_BYTES:\r
- stat = p_adapter->recv_stats.ucast.bytes;\r
- break;\r
-\r
- case IP_STAT_UCAST_FRAMES:\r
- stat = p_adapter->recv_stats.ucast.frames;\r
- break;\r
-\r
- case IP_STAT_BCAST_BYTES:\r
- stat = p_adapter->recv_stats.bcast.bytes;\r
- break;\r
-\r
- case IP_STAT_BCAST_FRAMES:\r
- stat = p_adapter->recv_stats.bcast.frames;\r
- break;\r
-\r
- case IP_STAT_MCAST_BYTES:\r
- stat = p_adapter->recv_stats.mcast.bytes;\r
- break;\r
-\r
- case IP_STAT_MCAST_FRAMES:\r
- stat = p_adapter->recv_stats.mcast.frames;\r
- break;\r
-\r
- default:\r
- stat = 0;\r
- }\r
- cl_spinlock_release( &p_adapter->recv_stat_lock );\r
-\r
- *p_oid_info->p_bytes_needed = sizeof(uint64_t);\r
-\r
- if( p_oid_info->buf_len >= sizeof(uint64_t) )\r
- {\r
- *((uint64_t*)p_oid_info->p_buf) = stat;\r
- *p_oid_info->p_bytes_used = sizeof(uint64_t);\r
- }\r
- else if( p_oid_info->buf_len >= sizeof(uint32_t) )\r
- {\r
- *((uint32_t*)p_oid_info->p_buf) = (uint32_t)stat;\r
- *p_oid_info->p_bytes_used = sizeof(uint32_t);\r
- }\r
- else\r
- {\r
- *p_oid_info->p_bytes_used = 0;\r
- IPOIB_EXIT( IPOIB_DBG_STAT );\r
- return NDIS_STATUS_INVALID_LENGTH;\r
- }\r
-\r
- IPOIB_EXIT( IPOIB_DBG_STAT );\r
- return NDIS_STATUS_SUCCESS;\r
-}\r
-\r
-\r
-void\r
-ipoib_inc_recv_stat(\r
- IN ipoib_adapter_t* const p_adapter,\r
- IN const ip_stat_sel_t stat_sel,\r
- IN const size_t bytes OPTIONAL,\r
- IN const size_t packets OPTIONAL )\r
-{\r
- IPOIB_ENTER( IPOIB_DBG_STAT );\r
-\r
- cl_spinlock_acquire( &p_adapter->recv_stat_lock );\r
- switch( stat_sel )\r
- {\r
- case IP_STAT_ERROR:\r
- p_adapter->recv_stats.comp.error++;\r
- break;\r
-\r
- case IP_STAT_DROPPED:\r
- p_adapter->recv_stats.comp.dropped++;\r
- break;\r
-\r
- case IP_STAT_UCAST_BYTES:\r
- case IP_STAT_UCAST_FRAMES:\r
- p_adapter->recv_stats.comp.success++;\r
- p_adapter->recv_stats.ucast.frames += packets;\r
- p_adapter->recv_stats.ucast.bytes += bytes;\r
- break;\r
-\r
- case IP_STAT_BCAST_BYTES:\r
- case IP_STAT_BCAST_FRAMES:\r
- p_adapter->recv_stats.comp.success++;\r
- p_adapter->recv_stats.bcast.frames += packets;\r
- p_adapter->recv_stats.bcast.bytes += bytes;\r
- break;\r
-\r
- case IP_STAT_MCAST_BYTES:\r
- case IP_STAT_MCAST_FRAMES:\r
- p_adapter->recv_stats.comp.success++;\r
- p_adapter->recv_stats.mcast.frames += packets;\r
- p_adapter->recv_stats.mcast.bytes += bytes;\r
- break;\r
-\r
- default:\r
- break;\r
- }\r
- cl_spinlock_release( &p_adapter->recv_stat_lock );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_STAT );\r
-}\r
-\r
-NDIS_STATUS\r
-ipoib_get_send_stat(\r
- IN ipoib_adapter_t* const p_adapter,\r
- IN const ip_stat_sel_t stat_sel,\r
- IN pending_oid_t* const p_oid_info )\r
-{\r
- uint64_t stat;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_STAT );\r
-\r
- CL_ASSERT( p_adapter );\r
-\r
- cl_spinlock_acquire( &p_adapter->send_stat_lock );\r
- switch( stat_sel )\r
- {\r
- case IP_STAT_SUCCESS:\r
- stat = p_adapter->send_stats.comp.success;\r
- break;\r
-\r
- case IP_STAT_ERROR:\r
- stat = p_adapter->send_stats.comp.error;\r
- break;\r
-\r
- case IP_STAT_DROPPED:\r
- stat = p_adapter->send_stats.comp.dropped;\r
- break;\r
-\r
- case IP_STAT_UCAST_BYTES:\r
- stat = p_adapter->send_stats.ucast.bytes;\r
- break;\r
-\r
- case IP_STAT_UCAST_FRAMES:\r
- stat = p_adapter->send_stats.ucast.frames;\r
- break;\r
-\r
- case IP_STAT_BCAST_BYTES:\r
- stat = p_adapter->send_stats.bcast.bytes;\r
- break;\r
-\r
- case IP_STAT_BCAST_FRAMES:\r
- stat = p_adapter->send_stats.bcast.frames;\r
- break;\r
-\r
- case IP_STAT_MCAST_BYTES:\r
- stat = p_adapter->send_stats.mcast.bytes;\r
- break;\r
-\r
- case IP_STAT_MCAST_FRAMES:\r
- stat = p_adapter->send_stats.mcast.frames;\r
- break;\r
-\r
- default:\r
- stat = 0;\r
- }\r
- cl_spinlock_release( &p_adapter->send_stat_lock );\r
-\r
- *p_oid_info->p_bytes_needed = sizeof(uint64_t);\r
-\r
- if( p_oid_info->buf_len >= sizeof(uint64_t) )\r
- {\r
- *((uint64_t*)p_oid_info->p_buf) = stat;\r
- *p_oid_info->p_bytes_used = sizeof(uint64_t);\r
- }\r
- else if( p_oid_info->buf_len >= sizeof(uint32_t) )\r
- {\r
- *((uint32_t*)p_oid_info->p_buf) = (uint32_t)stat;\r
- *p_oid_info->p_bytes_used = sizeof(uint32_t);\r
- }\r
- else\r
- {\r
- *p_oid_info->p_bytes_used = 0;\r
- IPOIB_EXIT( IPOIB_DBG_STAT );\r
- return NDIS_STATUS_INVALID_LENGTH;\r
- }\r
-\r
- IPOIB_EXIT( IPOIB_DBG_STAT );\r
- return NDIS_STATUS_SUCCESS;\r
-}\r
-\r
-\r
-void\r
-ipoib_inc_send_stat(\r
- IN ipoib_adapter_t* const p_adapter,\r
- IN const ip_stat_sel_t stat_sel,\r
- IN const size_t bytes OPTIONAL )\r
-{\r
- IPOIB_ENTER( IPOIB_DBG_STAT );\r
-\r
- cl_spinlock_acquire( &p_adapter->send_stat_lock );\r
- switch( stat_sel )\r
- {\r
- case IP_STAT_ERROR:\r
- p_adapter->send_stats.comp.error++;\r
- break;\r
-\r
- case IP_STAT_DROPPED:\r
- p_adapter->send_stats.comp.dropped++;\r
- break;\r
-\r
- case IP_STAT_UCAST_BYTES:\r
- case IP_STAT_UCAST_FRAMES:\r
- p_adapter->send_stats.comp.success++;\r
- p_adapter->send_stats.ucast.frames++;\r
- p_adapter->send_stats.ucast.bytes += bytes;\r
- break;\r
-\r
- case IP_STAT_BCAST_BYTES:\r
- case IP_STAT_BCAST_FRAMES:\r
- p_adapter->send_stats.comp.success++;\r
- p_adapter->send_stats.bcast.frames++;\r
- p_adapter->send_stats.bcast.bytes += bytes;\r
- break;\r
-\r
- case IP_STAT_MCAST_BYTES:\r
- case IP_STAT_MCAST_FRAMES:\r
- p_adapter->send_stats.comp.success++;\r
- p_adapter->send_stats.mcast.frames++;\r
- p_adapter->send_stats.mcast.bytes += bytes;\r
- break;\r
-\r
- default:\r
- break;\r
- }\r
- cl_spinlock_release( &p_adapter->send_stat_lock );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_STAT );\r
-}\r
--- /dev/null
+/*\r
+ * Copyright (c) 2005 SilverStorm Technologies. All rights reserved.\r
+ * Copyright (c) 2006 Mellanox Technologies. All rights reserved.\r
+ * Portions Copyright (c) 2008 Microsoft Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ * - Redistributions of source code must retain the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer.\r
+ *\r
+ * - Redistributions in binary form must reproduce the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer in the documentation and/or other materials\r
+ * provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id: ipoib_adapter.c 4506 2009-06-23 14:40:54Z xalex $\r
+ */\r
+\r
+\r
+\r
+#include "ipoib_adapter.h"\r
+#include "ipoib_port.h"\r
+#include "ipoib_driver.h"\r
+#include "ipoib_debug.h"\r
+\r
+#if defined(EVENT_TRACING)\r
+#ifdef offsetof\r
+#undef offsetof\r
+#endif\r
+#include "ipoib_adapter.tmh"\r
+#endif\r
+\r
+\r
+#define ITEM_POOL_START 16\r
+#define ITEM_POOL_GROW 16\r
+\r
+\r
+/* IB Link speeds in 100bps */\r
+#define ONE_X_IN_100BPS 25000000\r
+#define FOUR_X_IN_100BPS 100000000\r
+#define TWELVE_X_IN_100BPS 300000000\r
+\r
+\r
+/* Declarations */\r
+static void\r
+adapter_construct(\r
+ IN ipoib_adapter_t* const p_adapter );\r
+\r
+\r
+static ib_api_status_t\r
+adapter_init(\r
+ IN ipoib_adapter_t* const p_adapter );\r
+\r
+\r
+static void\r
+__adapter_destroying(\r
+ IN cl_obj_t* const p_obj );\r
+\r
+\r
+static void\r
+__adapter_free(\r
+ IN cl_obj_t* const p_obj );\r
+\r
+\r
+static ib_api_status_t\r
+__ipoib_pnp_reg(\r
+ IN ipoib_adapter_t* const p_adapter,\r
+ IN ib_pnp_class_t flags );\r
+\r
+\r
+static void\r
+__ipoib_pnp_dereg(\r
+ IN void* context );\r
+\r
+\r
+static void\r
+__ipoib_adapter_reset(\r
+ IN void* context);\r
+\r
+\r
+static ib_api_status_t\r
+__ipoib_pnp_cb(\r
+ IN ib_pnp_rec_t *p_pnp_rec );\r
+\r
+\r
+void\r
+ipoib_join_mcast(\r
+ IN ipoib_adapter_t* const p_adapter );\r
+\r
+\r
+/* Leaves all mcast groups when port goes down. */\r
+static void\r
+ipoib_clear_mcast(\r
+ IN ipoib_port_t* const p_port );\r
+\r
+NDIS_STATUS\r
+ipoib_get_adapter_guids(\r
+ IN NDIS_HANDLE* const h_adapter,\r
+ IN OUT ipoib_adapter_t *p_adapter );\r
+\r
+NDIS_STATUS\r
+ipoib_get_adapter_params(\r
+ IN OUT ipoib_adapter_t *p_adapter,\r
+ OUT PUCHAR *p_mac,\r
+ OUT UINT *p_len);\r
+\r
+\r
+/* Implementation */\r
+ib_api_status_t\r
+ipoib_create_adapter(\r
+ IN void* const h_adapter,\r
+ OUT ipoib_adapter_t** const pp_adapter )\r
+{\r
+ ipoib_adapter_t *p_adapter;\r
+ NDIS_STATUS status;\r
+ ib_api_status_t ib_status;\r
+ cl_status_t cl_status;\r
+ PUCHAR mac;\r
+ UINT len;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+ p_adapter = (ipoib_adapter_t *) cl_zalloc( sizeof(ipoib_adapter_t) );\r
+ if( !p_adapter )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed to allocate ipoib_adapter_t (%d bytes)",\r
+ sizeof(ipoib_adapter_t)) );\r
+ return IB_INSUFFICIENT_MEMORY;\r
+ }\r
+\r
+ adapter_construct( p_adapter );\r
+\r
+ p_adapter->h_adapter = h_adapter;\r
+\r
+ p_adapter->p_ifc = (ib_al_ifc_t *) cl_zalloc( sizeof(ib_al_ifc_t) );\r
+ if( !p_adapter->p_ifc )\r
+ {\r
+ __adapter_free( &p_adapter->obj );\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ipoib_create_adapter failed to alloc ipoib_ifc_t %d bytes\n",\r
+ sizeof(ib_al_ifc_t)) );\r
+ return IB_INSUFFICIENT_MEMORY;\r
+ }\r
+\r
+ /* Get the CA and port GUID from the bus driver. */\r
+ status = ipoib_get_adapter_guids( (NDIS_HANDLE *const) h_adapter, p_adapter );\r
+ if( status != NDIS_STATUS_SUCCESS )\r
+ {\r
+ ASSERT(FALSE);\r
+ __adapter_free( &p_adapter->obj );\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ipoib_get_adapter_guids returned 0x%.8X.\n", status) );\r
+ return IB_ERROR;\r
+ }\r
+\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+ ("Port %016I64x (CA %016I64x port %d) initializing\n",\r
+ p_adapter->guids.port_guid.guid, p_adapter->guids.ca_guid,\r
+ p_adapter->guids.port_num) );\r
+\r
+ cl_status = cl_obj_init( &p_adapter->obj, CL_DESTROY_SYNC,\r
+ __adapter_destroying, NULL, __adapter_free );\r
+ if( cl_status != CL_SUCCESS )\r
+ {\r
+ __adapter_free( &p_adapter->obj );\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("cl_obj_init returned %#x\n", cl_status) );\r
+ return IB_ERROR;\r
+ }\r
+\r
+ /* Read configuration parameters. */\r
+ status = ipoib_get_adapter_params( p_adapter , &mac, &len );\r
+ if( status != NDIS_STATUS_SUCCESS )\r
+ {\r
+ cl_obj_destroy( &p_adapter->obj );\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ipoib_get_adapter_params returned 0x%.8x.\n", status) );\r
+ return IB_ERROR;\r
+ }\r
+ \r
+ ib_status = adapter_init( p_adapter );\r
+ if( ib_status != IB_SUCCESS )\r
+ {\r
+ cl_obj_destroy( &p_adapter->obj );\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("adapter_init returned %s.\n", \r
+ p_adapter->p_ifc->get_err_str( ib_status )) );\r
+ return ib_status;\r
+ }\r
+\r
+ ETH_COPY_NETWORK_ADDRESS( p_adapter->params.conf_mac.addr, p_adapter->mac.addr );\r
+ /* If there is a NetworkAddress override in registry, use it */\r
+ if( (status == NDIS_STATUS_SUCCESS) && (len == HW_ADDR_LEN) )\r
+ {\r
+ if( ETH_IS_MULTICAST(mac) || ETH_IS_BROADCAST(mac) ||\r
+ !ETH_IS_LOCALLY_ADMINISTERED(mac) )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_INIT,\r
+ ("Overriding NetworkAddress is invalid - "\r
+ "%02x-%02x-%02x-%02x-%02x-%02x\n",\r
+ mac[0], mac[1], mac[2],\r
+ mac[3], mac[4], mac[5]) );\r
+ }\r
+ else\r
+ {\r
+ ETH_COPY_NETWORK_ADDRESS( p_adapter->params.conf_mac.addr, mac );\r
+ }\r
+ }\r
+\r
+ *pp_adapter = p_adapter;\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+ return IB_SUCCESS;\r
+}\r
+\r
+\r
+ib_api_status_t\r
+ipoib_start_adapter(\r
+ IN ipoib_adapter_t* const p_adapter )\r
+{\r
+ ib_api_status_t status;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+ status = __ipoib_pnp_reg( p_adapter,\r
+ IB_PNP_FLAG_REG_SYNC | IB_PNP_FLAG_REG_COMPLETE );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+ return status;\r
+}\r
+\r
+\r
+void\r
+ipoib_destroy_adapter(\r
+ IN ipoib_adapter_t* const p_adapter )\r
+{\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+ CL_ASSERT( p_adapter );\r
+\r
+ /*\r
+ * Flag the adapter as being removed. We use the IB_PNP_PORT_REMOVE state\r
+ * for this purpose. Note that we protect this state change with both the\r
+ * mutex and the lock. The mutex provides synchronization as a whole\r
+ * between destruction and AL callbacks (PnP, Query, Destruction).\r
+ * The lock provides protection\r
+ */\r
+ KeWaitForMutexObject(\r
+ &p_adapter->mutex, Executive, KernelMode, FALSE, NULL );\r
+ cl_obj_lock( &p_adapter->obj );\r
+ p_adapter->state = IB_PNP_PORT_REMOVE;\r
+\r
+ /*\r
+ * Clear the pointer to the port object since the object destruction\r
+ * will cascade to child objects. This prevents potential duplicate\r
+ * destruction (or worse, stale pointer usage).\r
+ */\r
+ p_adapter->p_port = NULL;\r
+\r
+ cl_obj_unlock( &p_adapter->obj );\r
+\r
+ KeReleaseMutex( &p_adapter->mutex, FALSE );\r
+\r
+ cl_obj_destroy( &p_adapter->obj );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static void\r
+adapter_construct(\r
+ IN ipoib_adapter_t* const p_adapter )\r
+{\r
+ cl_obj_construct( &p_adapter->obj, IPOIB_OBJ_INSTANCE );\r
+ cl_spinlock_construct( &p_adapter->send_stat_lock );\r
+ cl_spinlock_construct( &p_adapter->recv_stat_lock );\r
+ cl_qpool_construct( &p_adapter->item_pool );\r
+ KeInitializeMutex( &p_adapter->mutex, 0 );\r
+\r
+ cl_thread_construct(&p_adapter->destroy_thread);\r
+ \r
+ cl_vector_construct( &p_adapter->ip_vector );\r
+\r
+ cl_perf_construct( &p_adapter->perf );\r
+\r
+ p_adapter->state = IB_PNP_PORT_ADD;\r
+ p_adapter->port_rate = FOUR_X_IN_100BPS;\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+adapter_init(\r
+ IN ipoib_adapter_t* const p_adapter )\r
+{\r
+ cl_status_t cl_status;\r
+ ib_api_status_t status;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+ cl_status = cl_perf_init( &p_adapter->perf, MaxPerf );\r
+ if( cl_status != CL_SUCCESS )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("cl_perf_init returned %#x\n", cl_status) );\r
+ return IB_ERROR;\r
+ }\r
+\r
+ cl_status = cl_spinlock_init( &p_adapter->send_stat_lock );\r
+ if( cl_status != CL_SUCCESS )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("cl_spinlock_init returned %#x\n", cl_status) );\r
+ return IB_ERROR;\r
+ }\r
+\r
+ cl_status = cl_spinlock_init( &p_adapter->recv_stat_lock );\r
+ if( cl_status != CL_SUCCESS )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("cl_spinlock_init returned %#x\n", cl_status) );\r
+ return IB_ERROR;\r
+ }\r
+\r
+ cl_status = cl_qpool_init( &p_adapter->item_pool, ITEM_POOL_START, 0,\r
+ ITEM_POOL_GROW, sizeof(cl_pool_obj_t), NULL, NULL, NULL );\r
+ if( cl_status != CL_SUCCESS )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("cl_qpool_init returned %#x\n", cl_status) );\r
+ return IB_ERROR;\r
+ }\r
+\r
+\r
+ /* We manually manage the size and capacity of the vector. */\r
+ cl_status = cl_vector_init( &p_adapter->ip_vector, 0,\r
+ 0, sizeof(net_address_item_t), NULL, NULL, p_adapter );\r
+ if( cl_status != CL_SUCCESS )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("cl_vector_init for ip_vector returned %#x\n",\r
+ cl_status) );\r
+ return IB_ERROR;\r
+ }\r
+\r
+ /* Validate the port GUID and generate the MAC address. */\r
+ status =\r
+ ipoib_mac_from_guid( p_adapter->guids.port_guid.guid, p_adapter->params.guid_mask, &p_adapter->mac);\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ if( status == IB_INVALID_GUID_MASK )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_ERROR,\r
+ ("Invalid GUID mask received, rejecting it") );\r
+ ipoib_create_log(p_adapter->h_adapter, GUID_MASK_LOG_INDEX, EVENT_IPOIB_WRONG_PARAMETER_WRN);\r
+ }\r
+\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ipoib_mac_from_guid returned %s\n", \r
+ p_adapter->p_ifc->get_err_str( status )) );\r
+ return status;\r
+ }\r
+\r
+ /* Open AL. */\r
+ status = p_adapter->p_ifc->open_al( &p_adapter->h_al );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ib_open_al returned %s\n", \r
+ p_adapter->p_ifc->get_err_str( status )) );\r
+ return status;\r
+ }\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+ return status;\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__ipoib_pnp_reg(\r
+ IN ipoib_adapter_t* const p_adapter,\r
+ IN ib_pnp_class_t flags )\r
+{\r
+ ib_api_status_t status;\r
+ ib_pnp_req_t pnp_req;\r
+ \r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+ CL_ASSERT( !p_adapter->h_pnp );\r
+ CL_ASSERT( !p_adapter->registering );\r
+\r
+ p_adapter->registering = TRUE;\r
+ \r
+ /* Register for PNP events. */\r
+ cl_memclr( &pnp_req, sizeof(pnp_req) );\r
+ pnp_req.pnp_class = IB_PNP_PORT | flags;\r
+ /*\r
+ * Context is the cl_obj of the adapter to allow passing cl_obj_deref\r
+ * to ib_dereg_pnp.\r
+ */\r
+ pnp_req.pnp_context = &p_adapter->obj;\r
+ pnp_req.pfn_pnp_cb = __ipoib_pnp_cb;\r
+ status = p_adapter->p_ifc->reg_pnp( p_adapter->h_al, &pnp_req, &p_adapter->h_pnp );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ ASSERT(FALSE);\r
+ p_adapter->registering = FALSE;\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ib_reg_pnp returned %s\n", \r
+ p_adapter->p_ifc->get_err_str( status )) );\r
+ return status;\r
+ }\r
+ /*\r
+ * Reference the adapter on behalf of the PNP registration.\r
+ * This allows the destruction to block until the PNP deregistration\r
+ * completes.\r
+ */\r
+ cl_obj_ref( &p_adapter->obj );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+ return status;\r
+}\r
+\r
+\r
+static void\r
+__adapter_destroying(\r
+ IN cl_obj_t* const p_obj )\r
+{\r
+ ipoib_adapter_t *p_adapter;\r
+ KLOCK_QUEUE_HANDLE hdl;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+ p_adapter = PARENT_STRUCT( p_obj, ipoib_adapter_t, obj );\r
+\r
+ /*\r
+ * The adapter's object will be dereferenced when the deregistration\r
+ * completes. No need to lock here since all PnP related API calls\r
+ * are driven by NDIS (via the Init/Reset/Destroy paths).\r
+ */\r
+ if( p_adapter->h_pnp )\r
+ {\r
+ p_adapter->p_ifc->dereg_pnp( p_adapter->h_pnp, (ib_pfn_destroy_cb_t) cl_obj_deref );\r
+ p_adapter->h_pnp = NULL;\r
+ }\r
+\r
+ if( p_adapter->packet_filter )\r
+ {\r
+ KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
+ cl_obj_lock( &p_adapter->obj );\r
+\r
+ ASSERT( cl_qlist_count( &g_ipoib.adapter_list ) );\r
+ cl_qlist_remove_item( &g_ipoib.adapter_list, &p_adapter->entry );\r
+\r
+ p_adapter->packet_filter = 0;\r
+\r
+ cl_obj_unlock( &p_adapter->obj );\r
+ KeReleaseInStackQueuedSpinLock( &hdl );\r
+ }\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static void\r
+__adapter_free(\r
+ IN cl_obj_t* const p_obj )\r
+{\r
+ ipoib_adapter_t *p_adapter;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+ p_adapter = PARENT_STRUCT( p_obj, ipoib_adapter_t, obj );\r
+\r
+ if( p_adapter->p_ifc )\r
+ {\r
+ if( p_adapter->h_al )\r
+ p_adapter->p_ifc->close_al( p_adapter->h_al );\r
+\r
+ cl_free( p_adapter->p_ifc );\r
+ p_adapter->p_ifc = NULL;\r
+ }\r
+\r
+ cl_vector_destroy( &p_adapter->ip_vector );\r
+ cl_qpool_destroy( &p_adapter->item_pool );\r
+ cl_spinlock_destroy( &p_adapter->recv_stat_lock );\r
+ cl_spinlock_destroy( &p_adapter->send_stat_lock );\r
+ cl_obj_deinit( p_obj );\r
+\r
+ cl_perf_destroy( &p_adapter->perf, TRUE );\r
+\r
+ cl_free( p_adapter );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+ipoib_query_pkey_index(ipoib_adapter_t *p_adapter)\r
+{\r
+ ib_api_status_t status;\r
+ ib_ca_attr_t *ca_attr;\r
+ uint32_t ca_size;\r
+ uint16_t index = 0;\r
+\r
+ /* Query the CA for Pkey table */\r
+ status = p_adapter->p_ifc->query_ca(p_adapter->p_port->ib_mgr.h_ca, NULL, &ca_size);\r
+ if(status != IB_INSUFFICIENT_MEMORY)\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ib_query_ca failed\n"));\r
+ return status;\r
+ }\r
+\r
+ ca_attr = (ib_ca_attr_t*)cl_zalloc(ca_size);\r
+ if (!ca_attr)\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("cl_zalloc can't allocate %d\n",ca_size));\r
+ return IB_INSUFFICIENT_MEMORY;\r
+ }\r
+\r
+ status = p_adapter->p_ifc->query_ca(p_adapter->p_port->ib_mgr.h_ca, ca_attr,&ca_size); \r
+ if( status != IB_SUCCESS )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ib_query_ca returned %s\n", \r
+ p_adapter->p_ifc->get_err_str( status )) );\r
+ goto pkey_end;\r
+ }\r
+ CL_ASSERT(ca_attr->p_port_attr[p_adapter->p_port->port_num -1].p_pkey_table[0] == IB_DEFAULT_PKEY);\r
+ for(index = 0; index < ca_attr->p_port_attr[p_adapter->p_port->port_num -1].num_pkeys; index++)\r
+ {\r
+ 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])\r
+ break;\r
+ }\r
+ if(index >= ca_attr->p_port_attr[p_adapter->p_port->port_num -1].num_pkeys)\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Pkey table is invalid, index not found\n"));\r
+ NdisWriteErrorLogEntry( p_adapter->h_adapter,\r
+ EVENT_IPOIB_PARTITION_ERR, 1, p_adapter->guids.port_guid.pkey );\r
+ status = IB_NOT_FOUND;\r
+ p_adapter->p_port->pkey_index = PKEY_INVALID_INDEX;\r
+ goto pkey_end;\r
+ }\r
+\r
+ p_adapter->p_port->pkey_index = index;\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_IB,\r
+ ("for PKEY = 0x%04X got index = %d\n",p_adapter->guids.port_guid.pkey,index));\r
+\r
+pkey_end:\r
+ if(ca_attr)\r
+ cl_free(ca_attr);\r
+ return status;\r
+}\r
+\r
+static ib_api_status_t\r
+__ipoib_pnp_cb(\r
+ IN ib_pnp_rec_t *p_pnp_rec )\r
+{\r
+ ipoib_adapter_t *p_adapter;\r
+ ipoib_port_t *p_port;\r
+ ib_pnp_event_t old_state;\r
+ ib_pnp_port_rec_t *p_port_rec;\r
+ ib_api_status_t status = IB_SUCCESS;\r
+ NDIS_LINK_STATE link_state;\r
+ NDIS_STATUS_INDICATION status_indication;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_PNP );\r
+\r
+ CL_ASSERT( p_pnp_rec );\r
+ NdisZeroMemory(&link_state, sizeof(NDIS_LINK_STATE));\r
+ p_adapter =\r
+ PARENT_STRUCT( p_pnp_rec->pnp_context, ipoib_adapter_t, obj );\r
+\r
+ CL_ASSERT( p_adapter );\r
+\r
+ /* Synchronize with destruction */\r
+ KeWaitForMutexObject(\r
+ &p_adapter->mutex, Executive, KernelMode, FALSE, NULL );\r
+ cl_obj_lock( &p_adapter->obj );\r
+ old_state = p_adapter->state;\r
+ cl_obj_unlock( &p_adapter->obj );\r
+ if( old_state == IB_PNP_PORT_REMOVE )\r
+ {\r
+ KeReleaseMutex( &p_adapter->mutex, FALSE );\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_PNP,\r
+ ("Aborting - Adapter destroying.\n") );\r
+ return IB_NOT_DONE;\r
+ }\r
+\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_PNP,\r
+ ("p_pnp_rec->pnp_event = 0x%x (%s)\n",\r
+ p_pnp_rec->pnp_event, ib_get_pnp_event_str( p_pnp_rec->pnp_event )) );\r
+\r
+ p_port_rec = (ib_pnp_port_rec_t*)p_pnp_rec;\r
+\r
+ switch( p_pnp_rec->pnp_event )\r
+ {\r
+ case IB_PNP_PORT_ADD:\r
+ CL_ASSERT( !p_pnp_rec->context );\r
+ /* Only process our port GUID. */\r
+ if( p_pnp_rec->guid != p_adapter->guids.port_guid.guid )\r
+ {\r
+ status = IB_NOT_DONE;\r
+ break;\r
+ }\r
+\r
+ /* Don't process if we're destroying. */\r
+ if( p_adapter->obj.state == CL_DESTROYING )\r
+ {\r
+ status = IB_NOT_DONE;\r
+ break;\r
+ }\r
+\r
+ CL_ASSERT( !p_adapter->p_port );\r
+ /* Allocate all IB resources. */\r
+ cl_obj_lock( &p_adapter->obj );\r
+ p_adapter->state = IB_PNP_PORT_ADD;\r
+ cl_obj_unlock( &p_adapter->obj );\r
+ status = ipoib_create_port( p_adapter, p_port_rec, &p_port );\r
+ cl_obj_lock( &p_adapter->obj );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ p_adapter->state = old_state;\r
+ cl_obj_unlock( &p_adapter->obj );\r
+ p_adapter->hung = TRUE;\r
+ break;\r
+ }\r
+\r
+ p_pnp_rec->context = p_port;\r
+\r
+ p_adapter->p_port = p_port;\r
+ cl_obj_unlock( &p_adapter->obj );\r
+ break;\r
+\r
+ case IB_PNP_PORT_REMOVE:\r
+ /* Release all IB resources. */\r
+ CL_ASSERT( p_pnp_rec->context );\r
+\r
+ cl_obj_lock( &p_adapter->obj );\r
+ p_adapter->state = IB_PNP_PORT_REMOVE;\r
+ p_port = p_adapter->p_port;\r
+ p_adapter->p_port = NULL;\r
+ cl_obj_unlock( &p_adapter->obj );\r
+ ipoib_port_destroy( p_port );\r
+ p_pnp_rec->context = NULL;\r
+ status = IB_SUCCESS;\r
+ break;\r
+\r
+ case IB_PNP_PORT_ACTIVE:\r
+ /* Join multicast groups and put QP in RTS. */\r
+ CL_ASSERT( p_pnp_rec->context );\r
+\r
+ cl_obj_lock( &p_adapter->obj );\r
+ p_adapter->state = IB_PNP_PORT_INIT;\r
+ cl_obj_unlock( &p_adapter->obj );\r
+ ipoib_port_up( p_adapter->p_port, p_port_rec );\r
+\r
+ status = IB_SUCCESS;\r
+ break;\r
+\r
+ case IB_PNP_PORT_ARMED:\r
+ status = IB_SUCCESS;\r
+ break;\r
+\r
+ case IB_PNP_PORT_INIT:\r
+ /*\r
+ * Init could happen if the SM brings the port down\r
+ * without changing the physical link.\r
+ */\r
+ case IB_PNP_PORT_DOWN:\r
+ CL_ASSERT( p_pnp_rec->context );\r
+\r
+ cl_obj_lock( &p_adapter->obj );\r
+ old_state = p_adapter->state;\r
+ p_adapter->state = IB_PNP_PORT_DOWN;\r
+ cl_obj_unlock( &p_adapter->obj );\r
+ status = IB_SUCCESS;\r
+\r
+ if( !p_adapter->registering && old_state != IB_PNP_PORT_DOWN )\r
+ {\r
+ link_state.Header.Revision = NDIS_LINK_STATE_REVISION_1;\r
+ link_state.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;\r
+ link_state.Header.Size = sizeof(NDIS_LINK_STATE);\r
+ link_state.MediaConnectState = MediaConnectStateDisconnected;\r
+ //link_state.MediaConnectState = MediaConnectStateConnected;\r
+ link_state.MediaDuplexState = MediaDuplexStateFull;\r
+ link_state.XmitLinkSpeed = link_state.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED;\r
+\r
+ IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication,\r
+ p_adapter->h_adapter,\r
+ NDIS_STATUS_LINK_STATE,\r
+ (PVOID)&link_state,\r
+ sizeof(link_state));\r
+\r
+ NdisMIndicateStatusEx(p_adapter->h_adapter,&status_indication);\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+ ("Link DOWN!\n") );\r
+\r
+ ipoib_port_down( p_adapter->p_port );\r
+ }\r
+ break;\r
+\r
+ case IB_PNP_REG_COMPLETE:\r
+ if( p_adapter->registering )\r
+ {\r
+ p_adapter->registering = FALSE;\r
+ cl_obj_lock( &p_adapter->obj );\r
+ old_state = p_adapter->state;\r
+ cl_obj_unlock( &p_adapter->obj );\r
+\r
+ if( old_state == IB_PNP_PORT_DOWN )\r
+ {\r
+ /* If we were initializing, we might have pended some OIDs. */\r
+ ipoib_resume_oids( p_adapter );\r
+\r
+ link_state.Header.Revision = NDIS_LINK_STATE_REVISION_1;\r
+ link_state.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;\r
+ link_state.Header.Size = sizeof(NDIS_LINK_STATE);\r
+ link_state.MediaConnectState = MediaConnectStateDisconnected;\r
+ //link_state.MediaConnectState = MediaConnectStateConnected;\r
+ link_state.MediaDuplexState = MediaDuplexStateFull;\r
+ link_state.XmitLinkSpeed = link_state.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED;\r
+\r
+ IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication,\r
+ p_adapter->h_adapter,\r
+ NDIS_STATUS_LINK_STATE,\r
+ (PVOID)&link_state,\r
+ sizeof(link_state));\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_INIT,\r
+ ("Indicate DISCONNECT\n") );\r
+ NdisMIndicateStatusEx(p_adapter->h_adapter,&status_indication); \r
+ }\r
+ }\r
+\r
+ if( p_adapter->reset && p_adapter->state != IB_PNP_PORT_INIT )\r
+ {\r
+ p_adapter->reset = FALSE;\r
+ NdisMResetComplete(\r
+ p_adapter->h_adapter, NDIS_STATUS_SUCCESS, TRUE );\r
+ }\r
+ status = IB_SUCCESS;\r
+ break;\r
+\r
+ default:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+ ("IPOIB: Received unhandled PnP event 0x%x (%s)\n",\r
+ p_pnp_rec->pnp_event, ib_get_pnp_event_str( p_pnp_rec->pnp_event )) );\r
+ /* Fall through. */\r
+\r
+ status = IB_SUCCESS;\r
+\r
+ /* We ignore events below if the link is not active. */\r
+ if( p_port_rec->p_port_attr->link_state != IB_LINK_ACTIVE )\r
+ break;\r
+\r
+ case IB_PNP_PKEY_CHANGE:\r
+ if(p_pnp_rec->pnp_event == IB_PNP_PKEY_CHANGE && \r
+ p_adapter->guids.port_guid.pkey != IB_DEFAULT_PKEY)\r
+ {\r
+ status = ipoib_query_pkey_index(p_adapter);\r
+ if(status != IB_SUCCESS)\r
+ {\r
+ cl_obj_lock( &p_adapter->obj );\r
+ p_adapter->state = IB_PNP_PORT_INIT;\r
+ cl_obj_unlock( &p_adapter->obj );\r
+ }\r
+ }\r
+\r
+ case IB_PNP_SM_CHANGE:\r
+ case IB_PNP_GID_CHANGE:\r
+ case IB_PNP_LID_CHANGE:\r
+\r
+ cl_obj_lock( &p_adapter->obj );\r
+ old_state = p_adapter->state;\r
+ switch( old_state )\r
+ {\r
+ case IB_PNP_PORT_DOWN:\r
+ p_adapter->state = IB_PNP_PORT_INIT;\r
+ break;\r
+\r
+ default:\r
+ p_adapter->state = IB_PNP_PORT_DOWN;\r
+ }\r
+ cl_obj_unlock( &p_adapter->obj );\r
+ \r
+ if( p_adapter->registering )\r
+ break;\r
+\r
+ switch( old_state )\r
+ {\r
+ case IB_PNP_PORT_ACTIVE:\r
+ case IB_PNP_PORT_INIT:\r
+ link_state.Header.Revision = NDIS_LINK_STATE_REVISION_1;\r
+ link_state.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;\r
+ link_state.Header.Size = sizeof(NDIS_LINK_STATE);\r
+ link_state.MediaConnectState = MediaConnectStateDisconnected;\r
+ //link_state.MediaConnectState = MediaConnectStateConnected;\r
+ link_state.MediaDuplexState = MediaDuplexStateFull;\r
+ link_state.XmitLinkSpeed = link_state.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED;\r
+\r
+ IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication,\r
+ p_adapter->h_adapter,\r
+ NDIS_STATUS_LINK_STATE,\r
+ (PVOID)&link_state,\r
+ sizeof(link_state));\r
+\r
+ NdisMIndicateStatusEx(p_adapter->h_adapter,&status_indication); \r
+\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+ ("Link DOWN!\n") );\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_INIT,\r
+ ("Indicate DISCONNECT\n") );\r
+\r
+ ipoib_port_down( p_adapter->p_port );\r
+ /* Fall through. */\r
+\r
+ case IB_PNP_PORT_DOWN:\r
+ cl_obj_lock( &p_adapter->obj );\r
+ p_adapter->state = IB_PNP_PORT_INIT;\r
+ cl_obj_unlock( &p_adapter->obj );\r
+ ipoib_port_up( p_adapter->p_port, (ib_pnp_port_rec_t*)p_pnp_rec );\r
+ }\r
+ break;\r
+ }\r
+\r
+ KeReleaseMutex( &p_adapter->mutex, FALSE );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_PNP );\r
+ return status;\r
+}\r
+\r
+\r
+/* Joins/leaves mcast groups based on currently programmed mcast MACs. */\r
+void\r
+ipoib_refresh_mcast(\r
+ IN ipoib_adapter_t* const p_adapter,\r
+ IN mac_addr_t* const p_mac_array,\r
+ IN const uint8_t num_macs )\r
+{\r
+ uint8_t i, j;\r
+ ipoib_port_t *p_port = NULL;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_MCAST );\r
+ cl_obj_lock( &p_adapter->obj );\r
+ if( p_adapter->state == IB_PNP_PORT_ACTIVE )\r
+ {\r
+ p_port = p_adapter->p_port;\r
+ ipoib_port_ref( p_port, ref_refresh_mcast );\r
+ }\r
+ cl_obj_unlock( &p_adapter->obj );\r
+\r
+ if( p_port )\r
+ {\r
+ /* Purge old entries. */\r
+ for( i = 0; i < p_adapter->mcast_array_size; i++ )\r
+ {\r
+ for( j = 0; j < num_macs; j++ )\r
+ {\r
+ if( !cl_memcmp( &p_adapter->mcast_array[i], &p_mac_array[j],\r
+ sizeof(mac_addr_t) ) )\r
+ {\r
+ break;\r
+ }\r
+ }\r
+ if( j != num_macs )\r
+ continue;\r
+\r
+ ipoib_port_remove_endpt( p_port, p_adapter->mcast_array[i] );\r
+ }\r
+\r
+ /* Add new entries */\r
+ for( i = 0; i < num_macs; i++ )\r
+ {\r
+ for( j = 0; j < p_adapter->mcast_array_size; j++ )\r
+ {\r
+ if( !cl_memcmp( &p_adapter->mcast_array[j], &p_mac_array[i],\r
+ sizeof(mac_addr_t) ) )\r
+ {\r
+ break;\r
+ }\r
+ }\r
+\r
+ if( j != p_adapter->mcast_array_size )\r
+ continue;\r
+ if ( ( p_mac_array[i].addr[0] == 1 && p_mac_array[i].addr[1] == 0 && p_mac_array[i].addr[2] == 0x5e &&\r
+ p_mac_array[i].addr[3] == 0 && p_mac_array[i].addr[4] == 0 && p_mac_array[i].addr[5] == 1 ) ||\r
+ !( p_mac_array[i].addr[0] == 1 && p_mac_array[i].addr[1] == 0 && p_mac_array[i].addr[2] == 0x5e )\r
+ )\r
+ {\r
+ ipoib_port_join_mcast( p_port, p_mac_array[i], IB_MC_REC_STATE_FULL_MEMBER );\r
+ }\r
+ }\r
+ }\r
+\r
+ /* Copy the MAC array. */\r
+ NdisMoveMemory( p_adapter->mcast_array, p_mac_array,\r
+ num_macs * sizeof(mac_addr_t) );\r
+ p_adapter->mcast_array_size = num_macs;\r
+\r
+ if( p_port )\r
+ ipoib_port_deref( p_port, ref_refresh_mcast );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_MCAST );\r
+}\r
+\r
+\r
+ib_api_status_t\r
+ipoib_reset_adapter(\r
+ IN ipoib_adapter_t* const p_adapter )\r
+{\r
+ ib_api_status_t status;\r
+ ib_pnp_handle_t h_pnp;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+ if( p_adapter->reset )\r
+ return IB_INVALID_STATE;\r
+\r
+ p_adapter->hung = FALSE;\r
+ p_adapter->reset = TRUE;\r
+\r
+ if( p_adapter->h_pnp )\r
+ {\r
+ h_pnp = p_adapter->h_pnp;\r
+ p_adapter->h_pnp = NULL;\r
+ status = p_adapter->p_ifc->dereg_pnp( h_pnp, __ipoib_pnp_dereg );\r
+ if( status == IB_SUCCESS )\r
+ status = IB_NOT_DONE;\r
+ }\r
+ else\r
+ {\r
+ status = __ipoib_pnp_reg( p_adapter, IB_PNP_FLAG_REG_COMPLETE );\r
+ if( status == IB_SUCCESS )\r
+ p_adapter->hung = FALSE;\r
+ }\r
+ if (status == IB_NOT_DONE) {\r
+ p_adapter->reset = TRUE;\r
+ }\r
+ else {\r
+ p_adapter->reset = FALSE;\r
+ }\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+ return status;\r
+}\r
+\r
+\r
+static void\r
+__ipoib_pnp_dereg(\r
+ IN void* context )\r
+{\r
+ ipoib_adapter_t* p_adapter;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+ p_adapter = PARENT_STRUCT( context, ipoib_adapter_t, obj );\r
+\r
+ cl_thread_init(&p_adapter->destroy_thread, __ipoib_adapter_reset, (void*)p_adapter, "destroy_thread");\r
+ \r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+}\r
+\r
+static void\r
+__ipoib_adapter_reset(\r
+ IN void* context)\r
+{\r
+\r
+ ipoib_adapter_t *p_adapter;\r
+ ipoib_port_t *p_port;\r
+ ib_api_status_t status;\r
+ ib_pnp_event_t state;\r
+ \r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Got RESET\n") );\r
+// return;\r
+ p_adapter = (ipoib_adapter_t*)context;\r
+ \r
+ /* Synchronize with destruction */\r
+ KeWaitForMutexObject(\r
+ &p_adapter->mutex, Executive, KernelMode, FALSE, NULL );\r
+\r
+ cl_obj_lock( &p_adapter->obj );\r
+\r
+ CL_ASSERT( !p_adapter->h_pnp );\r
+\r
+ if( p_adapter->state != IB_PNP_PORT_REMOVE )\r
+ p_adapter->state = IB_PNP_PORT_ADD;\r
+\r
+ state = p_adapter->state;\r
+\r
+ /* Destroy the current port instance if it still exists. */\r
+ p_port = p_adapter->p_port;\r
+ p_adapter->p_port = NULL;\r
+ cl_obj_unlock( &p_adapter->obj );\r
+\r
+ if( p_port )\r
+ ipoib_port_destroy( p_port );\r
+ ASSERT(p_adapter->reset == TRUE);\r
+ if( state != IB_PNP_PORT_REMOVE )\r
+ {\r
+ status = __ipoib_pnp_reg( p_adapter, IB_PNP_FLAG_REG_COMPLETE );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ p_adapter->reset = FALSE;\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("__ipoib_pnp_reg returned %s\n",\r
+ p_adapter->p_ifc->get_err_str( status )) );\r
+ NdisMResetComplete( \r
+ p_adapter->h_adapter, NDIS_STATUS_HARD_ERRORS, TRUE );\r
+ }\r
+ }\r
+ else\r
+ {\r
+ p_adapter->reset = FALSE;\r
+ NdisMResetComplete(\r
+ p_adapter->h_adapter, NDIS_STATUS_SUCCESS, TRUE );\r
+ status = IB_SUCCESS;\r
+ }\r
+\r
+ /* Dereference the adapter since the previous registration is now gone. */\r
+ cl_obj_deref( &p_adapter->obj );\r
+\r
+ KeReleaseMutex( &p_adapter->mutex, FALSE );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+void\r
+ipoib_set_rate(\r
+ IN ipoib_adapter_t* const p_adapter,\r
+ IN const uint8_t link_width, \r
+ IN const uint8_t link_speed )\r
+{\r
+ uint32_t rate;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+ /* Set the link speed based on the IB link speed (1x vs 4x, etc). */\r
+ switch( link_speed )\r
+ {\r
+ case IB_LINK_SPEED_ACTIVE_2_5:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+ ("Link speed is 2.5Gs\n") );\r
+ rate = IB_LINK_SPEED_ACTIVE_2_5;\r
+ break;\r
+\r
+ case IB_LINK_SPEED_ACTIVE_5:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+ ("Link speed is 5G\n") );\r
+ rate = IB_LINK_SPEED_ACTIVE_5;\r
+ break;\r
+\r
+ case IB_LINK_SPEED_ACTIVE_10:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+ ("Link speed is 10G\n") );\r
+ rate = IB_LINK_SPEED_ACTIVE_10;\r
+ break;\r
+\r
+ default:\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Invalid link speed %d.\n", link_speed) );\r
+ rate = 0;\r
+ }\r
+\r
+ switch( link_width )\r
+ {\r
+ case IB_LINK_WIDTH_ACTIVE_1X:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+ ("Link width is 1X\n") );\r
+ rate *= ONE_X_IN_100BPS;\r
+ break;\r
+\r
+ case IB_LINK_WIDTH_ACTIVE_4X:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+ ("Link width is 4X\n") );\r
+ rate *= FOUR_X_IN_100BPS;\r
+ break;\r
+\r
+ case IB_LINK_WIDTH_ACTIVE_12X:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+ ("Link width is 12X\n") );\r
+ rate *= TWELVE_X_IN_100BPS;\r
+ break;\r
+\r
+ default:\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Invalid link rate (%d).\n", link_width) );\r
+ rate = 0;\r
+ }\r
+\r
+ p_adapter->port_rate = rate;\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+ib_api_status_t\r
+ipoib_set_active(\r
+ IN ipoib_adapter_t* const p_adapter )\r
+{\r
+ ib_pnp_event_t old_state;\r
+ uint8_t i;\r
+ ib_api_status_t status = IB_SUCCESS;\r
+ NDIS_LINK_STATE link_state;\r
+ NDIS_STATUS_INDICATION status_indication;\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+ NdisZeroMemory(&link_state, sizeof(NDIS_LINK_STATE));\r
+ cl_obj_lock( &p_adapter->obj );\r
+ old_state = p_adapter->state;\r
+\r
+ /* Change the state to indicate that we are now connected and live. */\r
+ if( old_state == IB_PNP_PORT_INIT )\r
+ p_adapter->state = IB_PNP_PORT_ACTIVE;\r
+\r
+ cl_obj_unlock( &p_adapter->obj );\r
+\r
+ /*\r
+ * If we had a pending OID request for OID_GEN_LINK_SPEED,\r
+ * complete it now.\r
+ */\r
+ switch( old_state )\r
+ {\r
+ case IB_PNP_PORT_ADD:\r
+ ipoib_reg_addrs( p_adapter );\r
+ /* Fall through. */\r
+\r
+ case IB_PNP_PORT_REMOVE:\r
+ ipoib_resume_oids( p_adapter );\r
+ break;\r
+\r
+ default:\r
+ if (p_adapter->guids.port_guid.pkey != IB_DEFAULT_PKEY)\r
+ {\r
+ status = ipoib_query_pkey_index(p_adapter);\r
+ if( IB_SUCCESS != status)\r
+ {\r
+ break;\r
+ }\r
+ }\r
+ /* Join all programmed multicast groups. */\r
+ for( i = 0; i < p_adapter->mcast_array_size; i++ )\r
+ {\r
+ ipoib_port_join_mcast(\r
+ p_adapter->p_port, p_adapter->mcast_array[i] ,IB_MC_REC_STATE_FULL_MEMBER);\r
+ }\r
+\r
+ /* Register all existing addresses. */\r
+ ipoib_reg_addrs( p_adapter );\r
+\r
+ ipoib_resume_oids( p_adapter );\r
+\r
+ /*\r
+ * Now that we're in the broadcast group, notify that\r
+ * we have a link.\r
+ */\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, ("Link UP!\n") );\r
+ NdisWriteErrorLogEntry( p_adapter->h_adapter,\r
+ EVENT_IPOIB_PORT_UP + (p_adapter->port_rate/ONE_X_IN_100BPS),\r
+ 1, p_adapter->port_rate );\r
+\r
+ if( !p_adapter->reset )\r
+ {\r
+ link_state.Header.Revision = NDIS_LINK_STATE_REVISION_1;\r
+ link_state.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;\r
+ link_state.Header.Size = sizeof(NDIS_LINK_STATE);\r
+ link_state.MediaConnectState = MediaConnectStateConnected;\r
+ link_state.MediaDuplexState = MediaDuplexStateFull;\r
+ link_state.XmitLinkSpeed = \r
+ link_state.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED;\r
+ link_state.PauseFunctions = NdisPauseFunctionsSendAndReceive;\r
+ IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication,\r
+ p_adapter->h_adapter,\r
+ NDIS_STATUS_LINK_STATE,\r
+ (PVOID)&link_state,\r
+ sizeof(link_state));\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, ("***************Indicate connect!\n") );\r
+ NdisMIndicateStatusEx(p_adapter->h_adapter,&status_indication);\r
+ }\r
+ }\r
+\r
+ if( p_adapter->reset )\r
+ {\r
+ ASSERT(FALSE);\r
+ p_adapter->reset = FALSE;\r
+ NdisMResetComplete(\r
+ p_adapter->h_adapter, NDIS_STATUS_SUCCESS, TRUE );\r
+ }\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+ return status;\r
+}\r
+\r
+/*\r
+ * If something goes wrong after the port goes active, e.g.\r
+ * - PortInfo query failure\r
+ * - MC Join timeout\r
+ * - etc\r
+ * Mark the port state as down, resume any pended OIDS, etc.\r
+ */\r
+void\r
+ipoib_set_inactive(\r
+ IN ipoib_adapter_t* const p_adapter )\r
+{\r
+ ib_pnp_event_t old_state;\r
+ NDIS_LINK_STATE link_state;\r
+ NDIS_STATUS_INDICATION status_indication;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+ NdisZeroMemory(&link_state, sizeof(NDIS_LINK_STATE));\r
+ cl_obj_lock( &p_adapter->obj );\r
+ old_state = p_adapter->state;\r
+ if( old_state != IB_PNP_PORT_REMOVE )\r
+ p_adapter->state = IB_PNP_PORT_DOWN;\r
+ cl_obj_unlock( &p_adapter->obj );\r
+\r
+ /*\r
+ * If we had a pending OID request for OID_GEN_LINK_SPEED,\r
+ * complete it now.\r
+ */\r
+ if( old_state == IB_PNP_PORT_INIT )\r
+ {\r
+ link_state.Header.Revision = NDIS_LINK_STATE_REVISION_1;\r
+ link_state.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;\r
+ link_state.Header.Size = sizeof(NDIS_LINK_STATE);\r
+ link_state.MediaConnectState = MediaConnectStateDisconnected;\r
+ //link_state.MediaConnectState = MediaConnectStateConnected;\r
+ \r
+ link_state.MediaDuplexState = MediaDuplexStateFull;\r
+ link_state.XmitLinkSpeed = link_state.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED;\r
+\r
+ IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication,\r
+ p_adapter->h_adapter,\r
+ NDIS_STATUS_LINK_STATE,\r
+ (PVOID)&link_state,\r
+ sizeof(link_state));\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, ("Indicate Disconnect!\n") );\r
+ NdisMIndicateStatusEx(p_adapter->h_adapter,&status_indication);\r
+\r
+ ipoib_resume_oids( p_adapter );\r
+ }\r
+\r
+ if( p_adapter->reset )\r
+ {\r
+ p_adapter->reset = FALSE;\r
+ NdisMResetComplete(\r
+ p_adapter->h_adapter, NDIS_STATUS_SUCCESS, TRUE );\r
+ }\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+NDIS_STATUS\r
+ipoib_get_gen_stat(\r
+ IN ipoib_adapter_t* const p_adapter,\r
+ OUT pending_oid_t* const p_oid_info)\r
+{\r
+ PNDIS_STATISTICS_INFO StatisticsInfo;\r
+ IPOIB_ENTER( IPOIB_DBG_STAT );\r
+\r
+ if (p_oid_info->buf_len < sizeof(StatisticsInfo))\r
+ {\r
+ *p_oid_info->p_bytes_needed = sizeof(NDIS_STATISTICS_INFO);\r
+ return NDIS_STATUS_INVALID_LENGTH;\r
+ }\r
+\r
+ StatisticsInfo = (PNDIS_STATISTICS_INFO)p_oid_info->p_buf;\r
+ StatisticsInfo->Header.Revision = NDIS_OBJECT_REVISION_1;\r
+ StatisticsInfo->Header.Type = NDIS_OBJECT_TYPE_DEFAULT;\r
+ StatisticsInfo->Header.Size = sizeof(NDIS_STATISTICS_INFO);\r
+ /*StatisticsInfo->SupportedStatistics = NDIS_STATISTICS_FLAGS_VALID_RCV_DISCARDS |\r
+ NDIS_STATISTICS_FLAGS_VALID_RCV_ERROR |\r
+ NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_RCV |\r
+ NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_RCV |\r
+ NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_RCV |\r
+ NDIS_STATISTICS_FLAGS_VALID_BYTES_RCV | \r
+ NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_RCV |\r
+ NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_RCV |\r
+ NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_RCV |\r
+\r
+ NDIS_STATISTICS_FLAGS_VALID_XMIT_DISCARDS |\r
+ NDIS_STATISTICS_FLAGS_VALID_XMIT_ERROR |\r
+ NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_XMIT | \r
+ NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_XMIT |\r
+ NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_XMIT |\r
+ NDIS_STATISTICS_FLAGS_VALID_BYTES_XMIT |\r
+ NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_XMIT |\r
+ NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_XMIT |\r
+ NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_XMIT; */\r
+ \r
+ \r
+ StatisticsInfo->SupportedStatistics = NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_RCV |\r
+ //The data in the ifHCInUcastPkts member is valid. \r
+ NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_RCV |\r
+ //The data in the ifHCInMulticastPkts member is valid. \r
+ NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_RCV |\r
+ //The data in the ifHCInBroadcastPkts member is valid. \r
+ NDIS_STATISTICS_FLAGS_VALID_BYTES_RCV |\r
+ //The data in the ifHCInOctets member is valid. \r
+ NDIS_STATISTICS_FLAGS_VALID_RCV_DISCARDS |\r
+ //The data in the ifInDiscards member is valid. \r
+ NDIS_STATISTICS_FLAGS_VALID_RCV_ERROR |\r
+ //The data in the ifInErrors member is valid. \r
+ NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_XMIT |\r
+ //The data in the ifHCOutUcastPkts member is valid. \r
+ NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_XMIT |\r
+ //The data in the ifHCOutMulticastPkts member is valid. \r
+ NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_XMIT |\r
+ //The data in the ifHCOutBroadcastPkts member is valid. \r
+ NDIS_STATISTICS_FLAGS_VALID_BYTES_XMIT |\r
+ //The data in the ifHCOutOctets member is valid. \r
+ NDIS_STATISTICS_FLAGS_VALID_XMIT_ERROR |\r
+ //The data in the ifOutErrors member is valid. \r
+ NDIS_STATISTICS_FLAGS_VALID_XMIT_DISCARDS |\r
+ //The data in the ifOutDiscards member is valid. \r
+ NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_RCV |\r
+ //The data in the ifHCInUcastOctets member is valid. \r
+ NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_RCV |\r
+ //The data in the ifHCInMulticastOctets member is valid. \r
+ NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_RCV |\r
+ //The data in the ifHCInBroadcastOctets member is valid. \r
+ NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_XMIT |\r
+ //The data in the ifHCOutUcastOctets member is valid. \r
+ NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_XMIT |\r
+ //The data in the ifHCOutMulticastOctets member is valid. \r
+ NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_XMIT ;\r
+ //The data in the ifHCOutBroadcastOctets member is valid\r
+\r
+ cl_spinlock_acquire( &p_adapter->recv_stat_lock );\r
+ StatisticsInfo->ifInDiscards = p_adapter->recv_stats.comp.dropped +\r
+ p_adapter->recv_stats.comp.error; \r
+ StatisticsInfo->ifInErrors = p_adapter->recv_stats.comp.error;\r
+ StatisticsInfo->ifHCInOctets = p_adapter->recv_stats.ucast.bytes + \r
+ p_adapter->recv_stats.bcast.bytes + \r
+ p_adapter->recv_stats.mcast.bytes; \r
+ StatisticsInfo->ifHCInUcastPkts = p_adapter->recv_stats.ucast.frames;\r
+ StatisticsInfo->ifHCInMulticastPkts = p_adapter->recv_stats.mcast.frames; \r
+ StatisticsInfo->ifHCInBroadcastPkts = p_adapter->recv_stats.bcast.frames; \r
+ StatisticsInfo->ifHCInMulticastOctets = p_adapter->recv_stats.mcast.bytes;\r
+ StatisticsInfo->ifHCInBroadcastOctets = p_adapter->recv_stats.bcast.bytes;\r
+ StatisticsInfo->ifHCInUcastOctets = p_adapter->recv_stats.ucast.bytes;\r
+ cl_spinlock_release( &p_adapter->recv_stat_lock );\r
+\r
+ cl_spinlock_acquire( &p_adapter->send_stat_lock ); \r
+ StatisticsInfo->ifHCOutOctets = p_adapter->send_stats.ucast.bytes + \r
+ p_adapter->send_stats.mcast.bytes + \r
+ p_adapter->send_stats.bcast.bytes; \r
+ StatisticsInfo->ifHCOutUcastPkts = p_adapter->send_stats.ucast.frames; \r
+ StatisticsInfo->ifHCOutMulticastPkts = p_adapter->send_stats.mcast.frames; \r
+ StatisticsInfo->ifHCOutBroadcastPkts = p_adapter->send_stats.bcast.frames; \r
+ StatisticsInfo->ifOutErrors = p_adapter->send_stats.comp.error; \r
+ StatisticsInfo->ifOutDiscards = p_adapter->send_stats.comp.dropped;\r
+ StatisticsInfo->ifHCOutUcastOctets = p_adapter->send_stats.ucast.bytes;\r
+ StatisticsInfo->ifHCOutMulticastOctets = p_adapter->send_stats.mcast.bytes;\r
+ StatisticsInfo->ifHCOutBroadcastOctets = p_adapter->send_stats.bcast.bytes;\r
+ cl_spinlock_release( &p_adapter->send_stat_lock );\r
+\r
+ *p_oid_info->p_bytes_used = sizeof(NDIS_STATISTICS_INFO);\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+ return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+NDIS_STATUS\r
+ipoib_get_recv_stat(\r
+ IN ipoib_adapter_t* const p_adapter,\r
+ IN const ip_stat_sel_t stat_sel,\r
+ IN pending_oid_t* const p_oid_info )\r
+{\r
+ uint64_t stat;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_STAT );\r
+\r
+ CL_ASSERT( p_adapter );\r
+\r
+ cl_spinlock_acquire( &p_adapter->recv_stat_lock );\r
+ switch( stat_sel )\r
+ {\r
+ case IP_STAT_SUCCESS:\r
+ stat = p_adapter->recv_stats.comp.success;\r
+ break;\r
+\r
+ case IP_STAT_ERROR:\r
+ stat = p_adapter->recv_stats.comp.error;\r
+ break;\r
+\r
+ case IP_STAT_DROPPED:\r
+ stat = p_adapter->recv_stats.comp.dropped;\r
+ break;\r
+\r
+ case IP_STAT_UCAST_BYTES:\r
+ stat = p_adapter->recv_stats.ucast.bytes;\r
+ break;\r
+\r
+ case IP_STAT_UCAST_FRAMES:\r
+ stat = p_adapter->recv_stats.ucast.frames;\r
+ break;\r
+\r
+ case IP_STAT_BCAST_BYTES:\r
+ stat = p_adapter->recv_stats.bcast.bytes;\r
+ break;\r
+\r
+ case IP_STAT_BCAST_FRAMES:\r
+ stat = p_adapter->recv_stats.bcast.frames;\r
+ break;\r
+\r
+ case IP_STAT_MCAST_BYTES:\r
+ stat = p_adapter->recv_stats.mcast.bytes;\r
+ break;\r
+\r
+ case IP_STAT_MCAST_FRAMES:\r
+ stat = p_adapter->recv_stats.mcast.frames;\r
+ break;\r
+\r
+ default:\r
+ stat = 0;\r
+ }\r
+ cl_spinlock_release( &p_adapter->recv_stat_lock );\r
+\r
+ *p_oid_info->p_bytes_needed = sizeof(uint64_t);\r
+\r
+ if( p_oid_info->buf_len >= sizeof(uint64_t) )\r
+ {\r
+ *((uint64_t*)p_oid_info->p_buf) = stat;\r
+ *p_oid_info->p_bytes_used = sizeof(uint64_t);\r
+ }\r
+ else if( p_oid_info->buf_len >= sizeof(uint32_t) )\r
+ {\r
+ *((uint32_t*)p_oid_info->p_buf) = (uint32_t)stat;\r
+ *p_oid_info->p_bytes_used = sizeof(uint32_t);\r
+ }\r
+ else\r
+ {\r
+ *p_oid_info->p_bytes_used = 0;\r
+ IPOIB_EXIT( IPOIB_DBG_STAT );\r
+ return NDIS_STATUS_INVALID_LENGTH;\r
+ }\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_STAT );\r
+ return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+\r
+void\r
+ipoib_inc_recv_stat(\r
+ IN ipoib_adapter_t* const p_adapter,\r
+ IN const ip_stat_sel_t stat_sel,\r
+ IN const size_t bytes OPTIONAL,\r
+ IN const size_t packets OPTIONAL )\r
+{\r
+ IPOIB_ENTER( IPOIB_DBG_STAT );\r
+\r
+ cl_spinlock_acquire( &p_adapter->recv_stat_lock );\r
+ switch( stat_sel )\r
+ {\r
+ case IP_STAT_ERROR:\r
+ p_adapter->recv_stats.comp.error++;\r
+ break;\r
+\r
+ case IP_STAT_DROPPED:\r
+ p_adapter->recv_stats.comp.dropped++;\r
+ break;\r
+\r
+ case IP_STAT_UCAST_BYTES:\r
+ case IP_STAT_UCAST_FRAMES:\r
+ p_adapter->recv_stats.comp.success++;\r
+ p_adapter->recv_stats.ucast.frames += packets;\r
+ p_adapter->recv_stats.ucast.bytes += bytes;\r
+ break;\r
+\r
+ case IP_STAT_BCAST_BYTES:\r
+ case IP_STAT_BCAST_FRAMES:\r
+ p_adapter->recv_stats.comp.success++;\r
+ p_adapter->recv_stats.bcast.frames += packets;\r
+ p_adapter->recv_stats.bcast.bytes += bytes;\r
+ break;\r
+\r
+ case IP_STAT_MCAST_BYTES:\r
+ case IP_STAT_MCAST_FRAMES:\r
+ p_adapter->recv_stats.comp.success++;\r
+ p_adapter->recv_stats.mcast.frames += packets;\r
+ p_adapter->recv_stats.mcast.bytes += bytes;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ cl_spinlock_release( &p_adapter->recv_stat_lock );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_STAT );\r
+}\r
+\r
+NDIS_STATUS\r
+ipoib_get_send_stat(\r
+ IN ipoib_adapter_t* const p_adapter,\r
+ IN const ip_stat_sel_t stat_sel,\r
+ IN pending_oid_t* const p_oid_info )\r
+{\r
+ uint64_t stat;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_STAT );\r
+\r
+ CL_ASSERT( p_adapter );\r
+\r
+ cl_spinlock_acquire( &p_adapter->send_stat_lock );\r
+ switch( stat_sel )\r
+ {\r
+ case IP_STAT_SUCCESS:\r
+ stat = p_adapter->send_stats.comp.success;\r
+ break;\r
+\r
+ case IP_STAT_ERROR:\r
+ stat = p_adapter->send_stats.comp.error;\r
+ break;\r
+\r
+ case IP_STAT_DROPPED:\r
+ stat = p_adapter->send_stats.comp.dropped;\r
+ break;\r
+\r
+ case IP_STAT_UCAST_BYTES:\r
+ stat = p_adapter->send_stats.ucast.bytes;\r
+ break;\r
+\r
+ case IP_STAT_UCAST_FRAMES:\r
+ stat = p_adapter->send_stats.ucast.frames;\r
+ break;\r
+\r
+ case IP_STAT_BCAST_BYTES:\r
+ stat = p_adapter->send_stats.bcast.bytes;\r
+ break;\r
+\r
+ case IP_STAT_BCAST_FRAMES:\r
+ stat = p_adapter->send_stats.bcast.frames;\r
+ break;\r
+\r
+ case IP_STAT_MCAST_BYTES:\r
+ stat = p_adapter->send_stats.mcast.bytes;\r
+ break;\r
+\r
+ case IP_STAT_MCAST_FRAMES:\r
+ stat = p_adapter->send_stats.mcast.frames;\r
+ break;\r
+\r
+ default:\r
+ stat = 0;\r
+ }\r
+ cl_spinlock_release( &p_adapter->send_stat_lock );\r
+\r
+ *p_oid_info->p_bytes_needed = sizeof(uint64_t);\r
+\r
+ if( p_oid_info->buf_len >= sizeof(uint64_t) )\r
+ {\r
+ *((uint64_t*)p_oid_info->p_buf) = stat;\r
+ *p_oid_info->p_bytes_used = sizeof(uint64_t);\r
+ }\r
+ else if( p_oid_info->buf_len >= sizeof(uint32_t) )\r
+ {\r
+ *((uint32_t*)p_oid_info->p_buf) = (uint32_t)stat;\r
+ *p_oid_info->p_bytes_used = sizeof(uint32_t);\r
+ }\r
+ else\r
+ {\r
+ *p_oid_info->p_bytes_used = 0;\r
+ IPOIB_EXIT( IPOIB_DBG_STAT );\r
+ return NDIS_STATUS_INVALID_LENGTH;\r
+ }\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_STAT );\r
+ return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+\r
+void\r
+ipoib_inc_send_stat(\r
+ IN ipoib_adapter_t* const p_adapter,\r
+ IN const ip_stat_sel_t stat_sel,\r
+ IN const size_t bytes OPTIONAL )\r
+{\r
+ IPOIB_ENTER( IPOIB_DBG_STAT );\r
+\r
+ cl_spinlock_acquire( &p_adapter->send_stat_lock );\r
+ switch( stat_sel )\r
+ {\r
+ case IP_STAT_ERROR:\r
+ p_adapter->send_stats.comp.error++;\r
+ break;\r
+\r
+ case IP_STAT_DROPPED:\r
+ p_adapter->send_stats.comp.dropped++;\r
+ break;\r
+\r
+ case IP_STAT_UCAST_BYTES:\r
+ case IP_STAT_UCAST_FRAMES:\r
+ p_adapter->send_stats.comp.success++;\r
+ p_adapter->send_stats.ucast.frames++;\r
+ p_adapter->send_stats.ucast.bytes += bytes;\r
+ break;\r
+\r
+ case IP_STAT_BCAST_BYTES:\r
+ case IP_STAT_BCAST_FRAMES:\r
+ p_adapter->send_stats.comp.success++;\r
+ p_adapter->send_stats.bcast.frames++;\r
+ p_adapter->send_stats.bcast.bytes += bytes;\r
+ break;\r
+\r
+ case IP_STAT_MCAST_BYTES:\r
+ case IP_STAT_MCAST_FRAMES:\r
+ p_adapter->send_stats.comp.success++;\r
+ p_adapter->send_stats.mcast.frames++;\r
+ p_adapter->send_stats.mcast.bytes += bytes;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ cl_spinlock_release( &p_adapter->send_stat_lock );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_STAT );\r
+}\r
\r
ib_api_status_t\r
ipoib_create_adapter(\r
- IN NDIS_HANDLE wrapper_config_context,\r
IN void* const h_adapter,\r
OUT ipoib_adapter_t** const pp_adapter );\r
\r
+++ /dev/null
-/*\r
- * Copyright (c) 2005 SilverStorm Technologies. All rights reserved.\r
- * Copyright (c) 2006 Mellanox Technologies. All rights reserved.\r
- * Portions Copyright (c) 2008 Microsoft Corporation. All rights reserved.\r
- *\r
- * This software is available to you under the OpenIB.org BSD license\r
- * below:\r
- *\r
- * Redistribution and use in source and binary forms, with or\r
- * without modification, are permitted provided that the following\r
- * conditions are met:\r
- *\r
- * - Redistributions of source code must retain the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer.\r
- *\r
- * - Redistributions in binary form must reproduce the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer in the documentation and/or other materials\r
- * provided with the distribution.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- * SOFTWARE.\r
- *\r
- * $Id: ipoib_driver.c 4506 2009-06-23 14:40:54Z xalex $\r
- */\r
-\r
-#include "limits.h"\r
-#include "ipoib_driver.h"\r
-#include "ipoib_debug.h"\r
-\r
-#if defined(EVENT_TRACING)\r
-#ifdef offsetof\r
-#undef offsetof\r
-#endif\r
-#include "ipoib_driver.tmh"\r
-#endif\r
-\r
-#include "ipoib_port.h"\r
-#include "ipoib_ibat.h"\r
-#include <complib/cl_bus_ifc.h>\r
-#include <complib/cl_init.h>\r
-#include <initguid.h>\r
-#include <iba/ipoib_ifc.h>\r
-#include "ntstrsafe.h"\r
-#include "strsafe.h"\r
-#include <offload.h>\r
-\r
-\r
-\r
-#define MAJOR_DRIVER_VERSION 2\r
-#define MINOR_DRIVER_VERSION 1\r
-#if defined(NDIS60_MINIPORT)\r
-#define MAJOR_NDIS_VERSION 6\r
-#define MINOR_NDIS_VERSION 0\r
-\r
-#else\r
-#error NDIS Version not defined, try defining NDIS60_MINIPORT\r
-#endif\r
-\r
-PDRIVER_OBJECT g_p_drv_obj;\r
-\r
-\r
-#if 0\r
-static const NDIS_OID SUPPORTED_OIDS[] =\r
-{\r
- OID_GEN_SUPPORTED_LIST,\r
- OID_GEN_HARDWARE_STATUS,\r
- OID_GEN_MEDIA_SUPPORTED,\r
- OID_GEN_MEDIA_IN_USE,\r
- OID_GEN_MAXIMUM_LOOKAHEAD,\r
- OID_GEN_MAXIMUM_FRAME_SIZE,\r
- OID_GEN_LINK_SPEED,\r
- OID_GEN_TRANSMIT_BUFFER_SPACE,\r
- OID_GEN_RECEIVE_BUFFER_SPACE,\r
- OID_GEN_TRANSMIT_BLOCK_SIZE,\r
- OID_GEN_RECEIVE_BLOCK_SIZE,\r
- OID_GEN_VENDOR_ID,\r
- OID_GEN_VENDOR_DESCRIPTION,\r
- OID_GEN_CURRENT_PACKET_FILTER,\r
- OID_GEN_CURRENT_LOOKAHEAD,\r
- OID_GEN_DRIVER_VERSION,\r
- OID_GEN_MAXIMUM_TOTAL_SIZE,\r
- OID_GEN_PROTOCOL_OPTIONS,\r
- OID_GEN_MAC_OPTIONS,\r
- OID_GEN_MEDIA_CONNECT_STATUS,\r
- OID_GEN_MAXIMUM_SEND_PACKETS,\r
- OID_GEN_NETWORK_LAYER_ADDRESSES,\r
- OID_GEN_VENDOR_DRIVER_VERSION,\r
- OID_GEN_PHYSICAL_MEDIUM,\r
- OID_GEN_XMIT_OK,\r
- OID_GEN_RCV_OK,\r
- OID_GEN_XMIT_ERROR,\r
- OID_GEN_RCV_ERROR,\r
- OID_GEN_RCV_NO_BUFFER,\r
- OID_GEN_DIRECTED_BYTES_XMIT,\r
- OID_GEN_DIRECTED_FRAMES_XMIT,\r
- OID_GEN_MULTICAST_BYTES_XMIT,\r
- OID_GEN_MULTICAST_FRAMES_XMIT,\r
- OID_GEN_BROADCAST_BYTES_XMIT,\r
- OID_GEN_BROADCAST_FRAMES_XMIT,\r
- OID_GEN_DIRECTED_BYTES_RCV,\r
- OID_GEN_DIRECTED_FRAMES_RCV,\r
- OID_GEN_MULTICAST_BYTES_RCV,\r
- OID_GEN_MULTICAST_FRAMES_RCV,\r
- OID_GEN_BROADCAST_BYTES_RCV,\r
- OID_GEN_BROADCAST_FRAMES_RCV,\r
- OID_802_3_PERMANENT_ADDRESS,\r
- OID_802_3_CURRENT_ADDRESS,\r
- OID_802_3_MULTICAST_LIST,\r
- OID_802_3_MAXIMUM_LIST_SIZE,\r
- OID_802_3_MAC_OPTIONS,\r
- OID_802_3_RCV_ERROR_ALIGNMENT,\r
- OID_802_3_XMIT_ONE_COLLISION,\r
- OID_802_3_XMIT_MORE_COLLISIONS,\r
- OID_TCP_TASK_OFFLOAD\r
-};\r
-#endif\r
-\r
-NDIS_OID NICSupportedOidsTest[] =\r
-{\r
- OID_GEN_SUPPORTED_LIST,\r
- OID_GEN_HARDWARE_STATUS,\r
- OID_GEN_MEDIA_SUPPORTED,\r
- OID_GEN_MEDIA_IN_USE,\r
- OID_GEN_MAXIMUM_LOOKAHEAD,\r
- OID_GEN_MAXIMUM_FRAME_SIZE,\r
- OID_GEN_TRANSMIT_BUFFER_SPACE,\r
- OID_GEN_RECEIVE_BUFFER_SPACE,\r
- OID_GEN_TRANSMIT_BLOCK_SIZE,\r
- OID_GEN_RECEIVE_BLOCK_SIZE,\r
- OID_GEN_VENDOR_ID,\r
- OID_GEN_VENDOR_DESCRIPTION,\r
- OID_GEN_VENDOR_DRIVER_VERSION,\r
- OID_GEN_CURRENT_PACKET_FILTER,\r
- OID_GEN_CURRENT_LOOKAHEAD,\r
- OID_GEN_DRIVER_VERSION,\r
- OID_GEN_MAXIMUM_TOTAL_SIZE,\r
- OID_GEN_MAC_OPTIONS,\r
- OID_GEN_MAXIMUM_SEND_PACKETS,\r
- OID_GEN_XMIT_OK,\r
- OID_GEN_RCV_OK,\r
- OID_GEN_XMIT_ERROR,\r
- OID_GEN_RCV_ERROR,\r
- OID_GEN_RCV_NO_BUFFER,\r
- OID_GEN_RCV_CRC_ERROR,\r
- OID_GEN_TRANSMIT_QUEUE_LENGTH,\r
- OID_802_3_PERMANENT_ADDRESS,\r
- OID_802_3_CURRENT_ADDRESS,\r
- OID_802_3_MULTICAST_LIST,\r
- OID_802_3_MAXIMUM_LIST_SIZE,\r
- OID_802_3_RCV_ERROR_ALIGNMENT,\r
- OID_802_3_XMIT_ONE_COLLISION,\r
- OID_802_3_XMIT_MORE_COLLISIONS,\r
- OID_802_3_XMIT_DEFERRED,\r
- OID_802_3_XMIT_MAX_COLLISIONS,\r
- OID_802_3_RCV_OVERRUN,\r
- OID_802_3_XMIT_UNDERRUN,\r
- OID_802_3_XMIT_HEARTBEAT_FAILURE,\r
- OID_802_3_XMIT_TIMES_CRS_LOST,\r
- OID_802_3_XMIT_LATE_COLLISIONS,\r
-\r
-#if !BUILD_W2K\r
- OID_GEN_PHYSICAL_MEDIUM,\r
-#endif\r
-\r
- OID_TCP_TASK_OFFLOAD,\r
- \r
-/* powermanagement */\r
-\r
- OID_PNP_CAPABILITIES,\r
- OID_PNP_SET_POWER,\r
- OID_PNP_QUERY_POWER,\r
- OID_PNP_ADD_WAKE_UP_PATTERN,\r
- OID_PNP_REMOVE_WAKE_UP_PATTERN,\r
- OID_PNP_ENABLE_WAKE_UP,\r
-\r
-\r
-/* custom oid WMI support */\r
-// OID_CUSTOM_PERF_COUNTERS,\r
- // OID_CUSTOM_STRING,\r
-\r
- OID_GEN_RECEIVE_SCALE_CAPABILITIES,\r
- OID_GEN_RECEIVE_SCALE_PARAMETERS,\r
-\r
-//\r
-// new and required for NDIS 6 miniports\r
-//\r
- OID_GEN_LINK_PARAMETERS,\r
- OID_GEN_INTERRUPT_MODERATION,\r
- OID_GEN_STATISTICS,\r
-\r
-/* Offload */\r
- OID_TCP_OFFLOAD_CURRENT_CONFIG,\r
- OID_TCP_OFFLOAD_PARAMETERS,\r
- OID_TCP_OFFLOAD_HARDWARE_CAPABILITIES,\r
- OID_OFFLOAD_ENCAPSULATION,\r
-\r
-/* Header - Data seperation */\r
- // OID_GEN_HD_SPLIT_PARAMETERS,\r
- // OID_GEN_HD_SPLIT_CURRENT_CONFIG,\r
- \r
-/* VLAN */\r
- // OID_ADD_VALN_ID,\r
- // OID_DELETE_VLAN_ID,\r
-\r
-/* Set MAC */\r
- // OID_SET_MAC_ADDRESS\r
-\r
-};\r
-\r
-static const NDIS_OID SUPPORTED_OIDS[] =\r
-{\r
- OID_GEN_SUPPORTED_LIST,\r
- OID_GEN_HARDWARE_STATUS,\r
- OID_GEN_MEDIA_SUPPORTED,\r
- OID_GEN_MEDIA_IN_USE,\r
- OID_GEN_MAXIMUM_LOOKAHEAD,\r
- OID_GEN_MAXIMUM_FRAME_SIZE,\r
- OID_GEN_TRANSMIT_BUFFER_SPACE,\r
- OID_GEN_RECEIVE_BUFFER_SPACE,\r
- OID_GEN_TRANSMIT_BLOCK_SIZE,\r
- OID_GEN_RECEIVE_BLOCK_SIZE,\r
- OID_GEN_VENDOR_ID,\r
- OID_GEN_VENDOR_DESCRIPTION,\r
- OID_GEN_VENDOR_DRIVER_VERSION,\r
- OID_GEN_CURRENT_PACKET_FILTER,\r
- OID_GEN_CURRENT_LOOKAHEAD,\r
- OID_GEN_DRIVER_VERSION,\r
- OID_GEN_MAXIMUM_TOTAL_SIZE,\r
- OID_GEN_MAC_OPTIONS,\r
- OID_GEN_MAXIMUM_SEND_PACKETS,\r
- OID_GEN_XMIT_OK,\r
- OID_GEN_RCV_OK,\r
- OID_GEN_XMIT_ERROR,\r
- OID_GEN_RCV_ERROR,\r
- OID_GEN_RCV_NO_BUFFER,\r
- OID_GEN_RCV_CRC_ERROR,\r
- OID_GEN_TRANSMIT_QUEUE_LENGTH,\r
- OID_802_3_PERMANENT_ADDRESS,\r
- OID_802_3_CURRENT_ADDRESS,\r
- OID_802_3_MULTICAST_LIST,\r
- OID_802_3_MAXIMUM_LIST_SIZE,\r
- OID_802_3_RCV_ERROR_ALIGNMENT,\r
- OID_802_3_XMIT_ONE_COLLISION,\r
- OID_802_3_XMIT_MORE_COLLISIONS,\r
- OID_802_3_XMIT_DEFERRED,\r
- OID_802_3_XMIT_MAX_COLLISIONS,\r
- OID_802_3_RCV_OVERRUN,\r
- OID_802_3_XMIT_UNDERRUN,\r
- OID_802_3_XMIT_HEARTBEAT_FAILURE,\r
- OID_802_3_XMIT_TIMES_CRS_LOST,\r
- OID_802_3_XMIT_LATE_COLLISIONS,\r
-\r
-#if !BUILD_W2K\r
- OID_GEN_PHYSICAL_MEDIUM,\r
-#endif\r
-\r
- OID_TCP_TASK_OFFLOAD,\r
- \r
-/* powermanagement */\r
-\r
- OID_PNP_CAPABILITIES,\r
- OID_PNP_SET_POWER,\r
- OID_PNP_QUERY_POWER,\r
- OID_PNP_ADD_WAKE_UP_PATTERN,\r
- OID_PNP_REMOVE_WAKE_UP_PATTERN,\r
- OID_PNP_ENABLE_WAKE_UP,\r
-\r
-#if 0\r
-/* custom oid WMI support */\r
- OID_CUSTOM_PERF_COUNTERS,\r
- OID_CUSTOM_STRING,\r
-#endif\r
-\r
- OID_GEN_RECEIVE_SCALE_CAPABILITIES,\r
- OID_GEN_RECEIVE_SCALE_PARAMETERS,\r
- \r
-\r
-//\r
-// new and required for NDIS 6 miniports\r
-//\r
- OID_GEN_LINK_PARAMETERS,\r
- OID_GEN_INTERRUPT_MODERATION,\r
- OID_GEN_STATISTICS,\r
-\r
-/* Offload */\r
- OID_TCP_OFFLOAD_CURRENT_CONFIG,\r
- OID_TCP_OFFLOAD_PARAMETERS,\r
- OID_TCP_OFFLOAD_HARDWARE_CAPABILITIES,\r
- OID_OFFLOAD_ENCAPSULATION,\r
- \r
-#if 0\r
-\r
-/* Header - Data seperation */\r
- OID_GEN_HD_SPLIT_PARAMETERS,\r
- OID_GEN_HD_SPLIT_CURRENT_CONFIG,\r
-\r
-/* VLAN */\r
- OID_ADD_VALN_ID,\r
- OID_DELETE_VLAN_ID,\r
-\r
-\r
-/* Set MAC */\r
- OID_SET_MAC_ADDRESS\r
-#endif\r
-\r
-};\r
-\r
-static const unsigned char VENDOR_ID[] = {0x00, 0x06, 0x6A, 0x00};\r
-\r
-#define VENDOR_DESCRIPTION "Internet Protocol over InfiniBand"\r
-\r
-#define IB_INFINITE_SERVICE_LEASE 0xFFFFFFFF\r
-\r
-//The mask is 8 bit and can't contain more than 6 non-zero bits\r
-#define MAX_GUID_MAX 0xFC\r
-\r
-\r
-/* Global driver debug level */\r
-uint32_t g_ipoib_dbg_level = TRACE_LEVEL_ERROR;\r
-uint32_t g_ipoib_dbg_flags = 0x00000fff;\r
-ipoib_globals_t g_ipoib = {0};\r
-NDIS_HANDLE g_IpoibMiniportDriverHandle = NULL;\r
-NDIS_HANDLE g_IpoibDriverContext = NULL;\r
-\r
-\r
-\r
-typedef struct _IPOIB_REG_ENTRY\r
-{\r
- NDIS_STRING RegName; // variable name text\r
- BOOLEAN bRequired; // 1 -> required, 0 -> optional\r
- UINT FieldOffset; // offset in parent struct\r
- UINT FieldSize; // size (in bytes) of the field\r
- UINT Default; // default value to use\r
- UINT Min; // minimum value allowed\r
- UINT Max; // maximum value allowed\r
-} IPOIB_REG_ENTRY, *PIPOIB_REG_ENTRY;\r
-\r
-IPOIB_REG_ENTRY HCARegTable[] = {\r
- // reg value name If Required Offset in parentr struct Field size Default Min Max\r
- {NDIS_STRING_CONST("GUIDMask"), 0, IPOIB_OFFSET(guid_mask), IPOIB_SIZE(guid_mask), 0, 0, MAX_GUID_MAX},\r
- /* GUIDMask should be the first element */\r
- {NDIS_STRING_CONST("RqDepth"), 1, IPOIB_OFFSET(rq_depth), IPOIB_SIZE(rq_depth), 512, 128, 1024},\r
- {NDIS_STRING_CONST("RqLowWatermark"), 0, IPOIB_OFFSET(rq_low_watermark), IPOIB_SIZE(rq_low_watermark), 4, 2, 8},\r
- {NDIS_STRING_CONST("SqDepth"), 1, IPOIB_OFFSET(sq_depth), IPOIB_SIZE(sq_depth), 512, 128, 1024},\r
- {NDIS_STRING_CONST("SendChksum"), 1, IPOIB_OFFSET(send_chksum_offload), IPOIB_SIZE(send_chksum_offload),CSUM_ENABLED,CSUM_DISABLED,CSUM_BYPASS},\r
- {NDIS_STRING_CONST("RecvChksum"), 1, IPOIB_OFFSET(recv_chksum_offload), IPOIB_SIZE(recv_chksum_offload),CSUM_ENABLED,CSUM_DISABLED,CSUM_BYPASS},\r
- {NDIS_STRING_CONST("SaTimeout"), 1, IPOIB_OFFSET(sa_timeout), IPOIB_SIZE(sa_timeout), 1000, 250, UINT_MAX},\r
- {NDIS_STRING_CONST("SaRetries"), 1, IPOIB_OFFSET(sa_retry_cnt), IPOIB_SIZE(sa_retry_cnt), 10, 1, UINT_MAX},\r
- {NDIS_STRING_CONST("RecvRatio"), 1, IPOIB_OFFSET(recv_pool_ratio), IPOIB_SIZE(recv_pool_ratio), 1, 1, 10},\r
- {NDIS_STRING_CONST("PayloadMtu"), 1, IPOIB_OFFSET(payload_mtu), IPOIB_SIZE(payload_mtu), 2044, 512, MAX_UD_PAYLOAD_MTU},\r
- {NDIS_STRING_CONST("lso"), 0, IPOIB_OFFSET(lso), IPOIB_SIZE(lso), 0, 0, 1},\r
- {NDIS_STRING_CONST("MCLeaveRescan"), 1, IPOIB_OFFSET(mc_leave_rescan), IPOIB_SIZE(mc_leave_rescan), 260, 1, 3600},\r
- {NDIS_STRING_CONST("BCJoinRetry"), 1, IPOIB_OFFSET(bc_join_retry), IPOIB_SIZE(bc_join_retry), 50, 0, 1000},\r
- {NDIS_STRING_CONST("CmEnabled"), 0, IPOIB_OFFSET(cm_enabled), IPOIB_SIZE(cm_enabled), FALSE, FALSE, TRUE},\r
- {NDIS_STRING_CONST("CmPayloadMtu"), 1, IPOIB_OFFSET(cm_payload_mtu), IPOIB_SIZE(cm_payload_mtu), MAX_CM_PAYLOAD_MTU, 512, MAX_CM_PAYLOAD_MTU}\r
-\r
-}; \r
-\r
-#define IPOIB_NUM_REG_PARAMS (sizeof (HCARegTable) / sizeof(IPOIB_REG_ENTRY))\r
-\r
-\r
-void\r
-ipoib_create_log(\r
- NDIS_HANDLE h_adapter,\r
- UINT ind,\r
- ULONG eventLogMsgId)\r
-\r
-{\r
-#define cMaxStrLen 40\r
-#define cArrLen 3\r
-\r
- PWCHAR logMsgArray[cArrLen]; \r
- WCHAR strVal[cMaxStrLen];\r
- NDIS_STRING AdapterInstanceName;\r
-\r
- IPOIB_INIT_NDIS_STRING(&AdapterInstanceName);\r
- if (NdisMQueryAdapterInstanceName(&AdapterInstanceName, h_adapter)!= NDIS_STATUS_SUCCESS ){\r
- ASSERT(FALSE);\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR,IPOIB_DBG_ERROR, ("[IPoIB] Init:Failed to retreive adapter name.\n"));\r
- return;\r
- }\r
- logMsgArray[0] = AdapterInstanceName.Buffer;\r
- \r
- if (RtlStringCbPrintfW(strVal, sizeof(strVal), L"0x%x", HCARegTable[ind].Default) != STATUS_SUCCESS) {\r
- ASSERT(FALSE);\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR,IPOIB_DBG_ERROR,\r
- ("[IPoIB] Init: Problem copying string value: exiting\n")); \r
- return;\r
- }\r
- \r
- logMsgArray[0] = AdapterInstanceName.Buffer;\r
- logMsgArray[1] = HCARegTable[ind].RegName.Buffer;\r
- logMsgArray[2] = strVal;\r
- \r
- NdisWriteEventLogEntry(g_p_drv_obj, eventLogMsgId, 0, cArrLen, &logMsgArray, 0, NULL);\r
-\r
-}\r
-\r
-\r
-\r
-NTSTATUS\r
-DriverEntry(\r
- IN PDRIVER_OBJECT p_drv_obj,\r
- IN PUNICODE_STRING p_reg_path );\r
-\r
-VOID\r
-ipoib_unload(\r
- IN PDRIVER_OBJECT p_drv_obj );\r
-\r
-NDIS_STATUS\r
-ipoib_initialize_ex(\r
- IN NDIS_HANDLE h_adapter,\r
- IN NDIS_HANDLE config_context,\r
- IN PNDIS_MINIPORT_INIT_PARAMETERS MiniportInitParameters);\r
-\r
-NDIS_STATUS \r
-MPInitializeTest(\r
- IN NDIS_HANDLE MiniportAdapterHandle,\r
- IN NDIS_HANDLE MiniportDriverContext,\r
- IN PNDIS_MINIPORT_INIT_PARAMETERS MiniportInitParameters\r
- );\r
-\r
-\r
-\r
-BOOLEAN\r
-ipoib_check_for_hang(\r
- IN NDIS_HANDLE adapter_context );\r
-\r
-void\r
-ipoib_halt_ex(\r
- IN NDIS_HANDLE adapter_context,\r
- IN NDIS_HALT_ACTION HaltAction);\r
-\r
-NDIS_STATUS\r
-ipoib_query_info(\r
- IN NDIS_HANDLE adapter_context,\r
- IN NDIS_OID oid,\r
- IN PVOID info_buf,\r
- IN ULONG info_buf_len,\r
- OUT PULONG p_bytes_written,\r
- OUT PULONG p_bytes_needed );\r
-\r
-\r
-\r
-NDIS_STATUS\r
-ipoib_reset(\r
- IN NDIS_HANDLE adapter_context,\r
- OUT PBOOLEAN p_addr_reset);\r
-\r
-NDIS_STATUS\r
-ipoib_set_info(\r
- IN NDIS_HANDLE adapter_context,\r
- IN NDIS_OID oid,\r
- IN PVOID info_buf,\r
- IN ULONG info_buf_length,\r
- OUT PULONG p_bytes_read,\r
- OUT PULONG p_bytes_needed );\r
-\r
-//NDIS60\r
-void\r
-ipoib_send_net_buffer_list(\r
- IN NDIS_HANDLE adapter_context,\r
- IN PNET_BUFFER_LIST net_buffer_list,\r
- IN NDIS_PORT_NUMBER port_num,\r
- IN ULONG send_flags);\r
-\r
-void\r
-ipoib_pnp_notify(\r
- IN NDIS_HANDLE adapter_context,\r
- IN PNET_DEVICE_PNP_EVENT pnp_event);\r
-\r
-VOID\r
-ipoib_shutdown_ex(\r
- IN NDIS_HANDLE adapter_context,\r
- IN NDIS_SHUTDOWN_ACTION shutdown_action);\r
-\r
-\r
-void\r
-ipoib_cancel_xmit(\r
- IN NDIS_HANDLE adapter_context,\r
- IN PVOID cancel_id );\r
-\r
-\r
-static void\r
-ipoib_complete_query(\r
- IN ipoib_adapter_t* const p_adapter,\r
- IN pending_oid_t* const p_oid_info,\r
- IN const NDIS_STATUS status,\r
- IN const void* const p_buf,\r
- IN const ULONG buf_len );\r
-\r
-static NDIS_STATUS\r
-__ipoib_set_net_addr(\r
- IN ipoib_adapter_t * p_adapter,\r
- IN PVOID info_buf,\r
- IN ULONG info_buf_len,\r
- OUT PULONG p_bytes_read,\r
- OUT PULONG p_bytes_needed );\r
-\r
-static NDIS_STATUS\r
-__ipoib_get_tcp_task_offload(\r
- IN ipoib_adapter_t* p_adapter,\r
- OUT pending_oid_t *pNdisRequest);\r
-\r
-static void\r
-__ipoib_ats_reg_cb(\r
- IN ib_reg_svc_rec_t *p_reg_svc_rec );\r
-\r
-static void\r
-__ipoib_ats_dereg_cb(\r
- IN void *context );\r
-\r
-static NTSTATUS\r
-__ipoib_read_registry(\r
- IN UNICODE_STRING* const p_registry_path );\r
-\r
-static NDIS_STATUS\r
-ipoib_set_options(\r
- IN NDIS_HANDLE NdisMiniportDriverHandle,\r
- IN NDIS_HANDLE MiniportDriverContext);\r
-\r
-static NDIS_STATUS\r
-ipoib_oid_handler(\r
- IN NDIS_HANDLE adapter_context,\r
- IN PNDIS_OID_REQUEST pNdisRequest);\r
-\r
-static void\r
-ipoib_cancel_oid_request(\r
- IN NDIS_HANDLE adapter_context,\r
- IN PVOID requestId);\r
- \r
-static NDIS_STATUS \r
-ipoib_pause(\r
- IN NDIS_HANDLE adapter_context, \r
- IN PNDIS_MINIPORT_PAUSE_PARAMETERS pause_parameters);\r
-\r
-static NDIS_STATUS \r
-ipoib_restart(\r
- IN NDIS_HANDLE adapter_context, \r
- IN PNDIS_MINIPORT_RESTART_PARAMETERS restart_parameters);\r
-\r
-\r
-\r
-//! Standard Windows Device Driver Entry Point\r
-/*! DriverEntry is the first routine called after a driver is loaded, and\r
-is responsible for initializing the driver. On W2k this occurs when the PnP\r
-Manager matched a PnP ID to one in an INF file that references this driver.\r
-Any not success return value will cause the driver to fail to load.\r
-IRQL = PASSIVE_LEVEL\r
-\r
-@param p_drv_obj Pointer to Driver Object for this device driver\r
-@param p_registry_path Pointer to unicode string containing path to this driver's registry area\r
-@return STATUS_SUCCESS, NDIS_STATUS_BAD_CHARACTERISTICS, NDIS_STATUS_BAD_VERSION,\r
-NDIS_STATUS_RESOURCES, or NDIS_STATUS_FAILURE\r
-*/\r
-NTSTATUS\r
-DriverEntry(\r
- IN PDRIVER_OBJECT p_drv_obj,\r
- IN PUNICODE_STRING p_registry_path )\r
-{\r
- NDIS_STATUS status;\r
- NDIS_MINIPORT_DRIVER_CHARACTERISTICS characteristics;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
- g_p_drv_obj = p_drv_obj;\r
-\r
-#ifdef _DEBUG_\r
- PAGED_CODE();\r
-#endif\r
-#if defined(EVENT_TRACING)\r
- WPP_INIT_TRACING(p_drv_obj, p_registry_path);\r
-#endif\r
- status = CL_INIT;\r
- if( !NT_SUCCESS( status ) )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("cl_init failed.\n") );\r
- return status;\r
- }\r
-\r
- __ipoib_read_registry(p_registry_path);\r
- \r
- KeInitializeSpinLock( &g_ipoib.lock );\r
- cl_qlist_init( &g_ipoib.adapter_list );\r
-\r
- NdisZeroMemory(&characteristics, sizeof(characteristics));\r
-\r
- characteristics.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_DRIVER_CHARACTERISTICS,\r
- characteristics.Header.Size = sizeof(NDIS_MINIPORT_DRIVER_CHARACTERISTICS);\r
- characteristics.Header.Revision = NDIS_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_1;\r
-\r
- characteristics.MajorNdisVersion = MAJOR_NDIS_VERSION;\r
- characteristics.MinorNdisVersion = MINOR_NDIS_VERSION;\r
- characteristics.MajorDriverVersion = MAJOR_DRIVER_VERSION;\r
- characteristics.MinorDriverVersion = MINOR_DRIVER_VERSION;\r
-\r
-\r
- characteristics.CheckForHangHandlerEx = ipoib_check_for_hang;\r
- characteristics.HaltHandlerEx = ipoib_halt_ex;\r
- characteristics.InitializeHandlerEx = ipoib_initialize_ex;// MPInitializeTest\r
- characteristics.OidRequestHandler = ipoib_oid_handler;\r
- characteristics.CancelOidRequestHandler = ipoib_cancel_oid_request;\r
- characteristics.ResetHandlerEx = ipoib_reset;\r
- characteristics.DevicePnPEventNotifyHandler = ipoib_pnp_notify;\r
- characteristics.ReturnNetBufferListsHandler = ipoib_return_net_buffer_list;\r
- characteristics.SendNetBufferListsHandler = ipoib_send_net_buffer_list;\r
-\r
- characteristics.SetOptionsHandler = ipoib_set_options;\r
- characteristics.PauseHandler = ipoib_pause;\r
- characteristics.RestartHandler = ipoib_restart;\r
- characteristics.UnloadHandler = ipoib_unload;\r
- characteristics.CancelSendHandler = ipoib_cancel_xmit;\r
- characteristics.ShutdownHandlerEx = ipoib_shutdown_ex;\r
-\r
-\r
-\r
-//TODO NDIS60 set g_ prefix to global variables\r
- status = NdisMRegisterMiniportDriver(\r
- p_drv_obj, p_registry_path,(PNDIS_HANDLE)&g_IpoibDriverContext, &characteristics,&g_IpoibMiniportDriverHandle );\r
- if( status != NDIS_STATUS_SUCCESS )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, \r
- ("NdisMRegisterMiniportDriver failed with status of %d\n", status) );\r
- CL_DEINIT;\r
- }\r
-\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
- return status;\r
-}\r
-\r
-static NDIS_STATUS\r
-ipoib_set_options(\r
- IN NDIS_HANDLE NdisMiniportDriverHandle,\r
- IN NDIS_HANDLE MiniportDriverContext\r
- )\r
-{\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-\r
- UNREFERENCED_PARAMETER(NdisMiniportDriverHandle);\r
- UNREFERENCED_PARAMETER(MiniportDriverContext);\r
- \r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
- return NDIS_STATUS_SUCCESS;\r
-}\r
-\r
-static NTSTATUS\r
-__ipoib_read_registry(\r
- IN UNICODE_STRING* const p_registry_path )\r
-{\r
- NTSTATUS status;\r
- /* Remember the terminating entry in the table below. */\r
- RTL_QUERY_REGISTRY_TABLE table[4];\r
- UNICODE_STRING param_path;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
- RtlInitUnicodeString( ¶m_path, NULL );\r
- param_path.MaximumLength = p_registry_path->Length + \r
- sizeof(L"\\Parameters");\r
- param_path.Buffer = cl_zalloc( param_path.MaximumLength );\r
- if( !param_path.Buffer )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, \r
- ("Failed to allocate parameters path buffer.\n") );\r
- return STATUS_INSUFFICIENT_RESOURCES;\r
- }\r
-\r
- RtlAppendUnicodeStringToString( ¶m_path, p_registry_path );\r
- RtlAppendUnicodeToString( ¶m_path, L"\\Parameters" );\r
-\r
- /*\r
- * Clear the table. This clears all the query callback pointers,\r
- * and sets up the terminating table entry.\r
- */\r
- cl_memclr( table, sizeof(table) );\r
-\r
- /* Setup the table entries. */\r
- table[0].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
- table[0].Name = L"DebugLevel";\r
- table[0].EntryContext = &g_ipoib_dbg_level;\r
- table[0].DefaultType = REG_DWORD;\r
- table[0].DefaultData = &g_ipoib_dbg_level;\r
- table[0].DefaultLength = sizeof(ULONG);\r
-\r
- table[1].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
- table[1].Name = L"DebugFlags";\r
- table[1].EntryContext = &g_ipoib_dbg_flags;\r
- table[1].DefaultType = REG_DWORD;\r
- table[1].DefaultData = &g_ipoib_dbg_flags;\r
- table[1].DefaultLength = sizeof(ULONG);\r
-\r
- table[2].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
- table[2].Name = L"bypass_check_bcast_rate";\r
- table[2].EntryContext = &g_ipoib.bypass_check_bcast_rate;\r
- table[2].DefaultType = REG_DWORD;\r
- table[2].DefaultData = &g_ipoib.bypass_check_bcast_rate;\r
- table[2].DefaultLength = sizeof(ULONG);\r
-\r
- /* Have at it! */\r
- status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE, \r
- param_path.Buffer, table, NULL, NULL );\r
-\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("debug level %d debug flags 0x%.8x\n",\r
- g_ipoib_dbg_level,\r
- g_ipoib_dbg_flags));\r
-\r
-#if DBG\r
- if( g_ipoib_dbg_flags & IPOIB_DBG_ERR )\r
- g_ipoib_dbg_flags |= CL_DBG_ERROR;\r
-#endif\r
-\r
- cl_free( param_path.Buffer );\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
- return status;\r
-}\r
-\r
-\r
-VOID\r
-ipoib_unload(\r
- IN PDRIVER_OBJECT p_drv_obj )\r
-{\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
- UNREFERENCED_PARAMETER(p_drv_obj);\r
- #if defined(EVENT_TRACING)\r
- WPP_CLEANUP(p_drv_obj);\r
- #endif\r
- //NDIS6.0\r
- NdisMDeregisterMiniportDriver(g_IpoibMiniportDriverHandle);\r
- UNREFERENCED_PARAMETER( p_drv_obj );\r
- CL_DEINIT;\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
-}\r
-\r
-\r
-\r
-NDIS_STATUS\r
-ipoib_get_adapter_params(\r
- IN NDIS_HANDLE* const wrapper_config_context,\r
- IN OUT ipoib_adapter_t *p_adapter,\r
- OUT PUCHAR *p_mac,\r
- OUT UINT *p_len)\r
-{\r
- NDIS_STATUS status;\r
- NDIS_HANDLE h_config;\r
- NDIS_CONFIGURATION_OBJECT config_obj;\r
- NDIS_CONFIGURATION_PARAMETER *p_param;\r
- UINT value;\r
- PIPOIB_REG_ENTRY pRegEntry;\r
- UINT i;\r
- PUCHAR structPointer;\r
- \r
- int sq_depth_step = 128;\r
-\r
- UNUSED_PARAM(wrapper_config_context);\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-\r
- config_obj.Header.Type = NDIS_OBJECT_TYPE_CONFIGURATION_OBJECT;\r
- config_obj.Header.Revision = NDIS_CONFIGURATION_OBJECT_REVISION_1;\r
- config_obj.Header.Size = sizeof(NDIS_CONFIGURATION_OBJECT);\r
- config_obj.NdisHandle = p_adapter->h_adapter;\r
- config_obj.Flags = 0;\r
-\r
- status = NdisOpenConfigurationEx( &config_obj, &h_config);\r
- if( status != NDIS_STATUS_SUCCESS )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("NdisOpenConfigurationEx returned 0x%.8x\n", status) );\r
- return status;\r
- }\r
-\r
- // read all the registry values \r
- for (i = 0, pRegEntry = HCARegTable; i < IPOIB_NUM_REG_PARAMS; ++i)\r
- {\r
- // initialize pointer to appropriate place inside 'params'\r
- structPointer = (PUCHAR) &p_adapter->params + pRegEntry[i].FieldOffset;\r
-\r
- // Get the configuration value for a specific parameter. Under NT the\r
- // parameters are all read in as DWORDs.\r
- NdisReadConfiguration(\r
- &status,\r
- &p_param,\r
- h_config,\r
- &pRegEntry[i].RegName,\r
- NdisParameterInteger);\r
-\r
- // If the parameter was present, then check its value for validity.\r
- if (status == NDIS_STATUS_SUCCESS)\r
- {\r
- // Check that param value is not too small or too large\r
- if (p_param->ParameterData.IntegerData < pRegEntry[i].Min ||\r
- p_param->ParameterData.IntegerData > pRegEntry[i].Max)\r
- {\r
- value = pRegEntry[i].Default;\r
- ipoib_create_log(p_adapter->h_adapter, i, EVENT_IPOIB_WRONG_PARAMETER_WRN);\r
- 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)); \r
-\r
- }\r
- else\r
- {\r
- value = p_param->ParameterData.IntegerData;\r
- IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_INIT, ("Read configuration. Registry %S, Value= 0x%x\n", pRegEntry[i].RegName.Buffer, value));\r
- }\r
- }\r
-\r
- else\r
- {\r
- value = pRegEntry[i].Default;\r
- status = NDIS_STATUS_SUCCESS;\r
- if (pRegEntry[i].bRequired)\r
- {\r
- ipoib_create_log(p_adapter->h_adapter, i, EVENT_IPOIB_WRONG_PARAMETER_ERR);\r
- 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));\r
- }\r
- else\r
- {\r
- ipoib_create_log(p_adapter->h_adapter, i, EVENT_IPOIB_WRONG_PARAMETER_INFO);\r
- IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_INIT, ("Read configuration. Registry %S value not found, Value= 0x%x\n", pRegEntry[i].RegName.Buffer, value));\r
- }\r
-\r
- }\r
- //\r
- // Store the value in the adapter structure.\r
- //\r
- switch(pRegEntry[i].FieldSize)\r
- {\r
- case 1:\r
- *((PUCHAR) structPointer) = (UCHAR) value;\r
- break;\r
-\r
- case 2:\r
- *((PUSHORT) structPointer) = (USHORT) value;\r
- break;\r
-\r
- case 4:\r
- *((PULONG) structPointer) = (ULONG) value;\r
- break;\r
-\r
- default:\r
- IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, ("Bogus field size %d\n", pRegEntry[i].FieldSize));\r
- break;\r
- }\r
- }\r
-\r
- // Send queue depth needs to be a power of two\r
- //static const INT sq_depth_step = 128;\r
-\r
- if (p_adapter->params.sq_depth % sq_depth_step) {\r
- static const c_sq_ind = 2;\r
- p_adapter->params.sq_depth = sq_depth_step *(\r
- p_adapter->params.sq_depth / sq_depth_step + !!( (p_adapter->params.sq_depth % sq_depth_step) > (sq_depth_step/2) ));\r
- ipoib_create_log(p_adapter->h_adapter, c_sq_ind, EVENT_IPOIB_WRONG_PARAMETER_WRN);\r
- 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 ));\r
-\r
- }\r
-\r
-\r
- // Adjusting the low watermark parameter\r
- p_adapter->params.rq_low_watermark =\r
- p_adapter->params.rq_depth / p_adapter->params.rq_low_watermark;\r
- \r
- /* disable CM if LSO is active */\r
- if( p_adapter->params.cm_enabled )\r
- {\r
- p_adapter->params.cm_enabled = !p_adapter->params.lso;\r
- if( !p_adapter->params.cm_enabled )\r
- {\r
- NdisWriteErrorLogEntry( p_adapter->h_adapter,\r
- EVENT_IPOIB_CONNECTED_MODE_ERR, 1, 0xbadc0de0 );\r
- }\r
- }\r
-\r
- if( p_adapter->params.cm_enabled )\r
- {\r
- p_adapter->params.cm_xfer_block_size = \r
- (sizeof(eth_hdr_t) + p_adapter->params.cm_payload_mtu);\r
- }\r
-\r
- p_adapter->params.xfer_block_size = \r
- (sizeof(eth_hdr_t) + p_adapter->params.payload_mtu);\r
-\r
- NdisReadNetworkAddress( &status, p_mac, p_len, h_config );\r
-\r
- NdisCloseConfiguration( h_config );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
- return NDIS_STATUS_SUCCESS;\r
-}\r
-\r
-\r
-NDIS_STATUS\r
-ipoib_get_adapter_guids(\r
- IN NDIS_HANDLE* const h_adapter,\r
- IN OUT ipoib_adapter_t *p_adapter )\r
-{\r
- NTSTATUS status;\r
- ib_al_ifc_data_t data;\r
- IO_STACK_LOCATION io_stack, *p_fwd_io_stack;\r
- DEVICE_OBJECT *p_pdo;\r
- IRP *p_irp;\r
- KEVENT event;\r
- IO_STATUS_BLOCK io_status;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-\r
- NdisMGetDeviceProperty( h_adapter, &p_pdo, NULL, NULL, NULL, NULL );\r
-\r
- /* Query for our interface */\r
- data.size = sizeof(ipoib_ifc_data_t);\r
- data.version = IPOIB_INTERFACE_DATA_VERSION;\r
- data.type = &GUID_IPOIB_INTERFACE_DATA;\r
- data.p_data = &p_adapter->guids;\r
-\r
- io_stack.MinorFunction = IRP_MN_QUERY_INTERFACE;\r
- io_stack.Parameters.QueryInterface.Version = AL_INTERFACE_VERSION;\r
- io_stack.Parameters.QueryInterface.Size = sizeof(ib_al_ifc_t);\r
- io_stack.Parameters.QueryInterface.Interface =\r
- (INTERFACE*)p_adapter->p_ifc;\r
- io_stack.Parameters.QueryInterface.InterfaceSpecificData = &data;\r
- io_stack.Parameters.QueryInterface.InterfaceType = \r
- &GUID_IB_AL_INTERFACE;\r
-\r
- KeInitializeEvent( &event, NotificationEvent, FALSE );\r
-\r
- /* Build the IRP for the HCA. */\r
- p_irp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP, p_pdo,\r
- NULL, 0, NULL, &event, &io_status );\r
- if( !p_irp )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Failed to allocate query interface IRP.\n") );\r
- return STATUS_INSUFFICIENT_RESOURCES;\r
- }\r
-\r
- /* Copy the request query parameters. */\r
- p_fwd_io_stack = IoGetNextIrpStackLocation( p_irp );\r
- p_fwd_io_stack->MinorFunction = IRP_MN_QUERY_INTERFACE;\r
- p_fwd_io_stack->Parameters.QueryInterface =\r
- io_stack.Parameters.QueryInterface;\r
- p_irp->IoStatus.Status = STATUS_NOT_SUPPORTED;\r
-\r
- /* Send the IRP. */\r
- status = IoCallDriver( p_pdo, p_irp );\r
- if( status == STATUS_PENDING )\r
- {\r
- KeWaitForSingleObject( &event, Executive, KernelMode,\r
- FALSE, NULL );\r
- status = io_status.Status;\r
- }\r
-\r
- if( !NT_SUCCESS( status ) )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Query interface for IPOIB interface returned %08x.\n", status) );\r
- return status;\r
- }\r
-\r
- /*\r
- * Dereference the interface now so that the bus driver doesn't fail a\r
- * query remove IRP. We will always get unloaded before the bus driver\r
- * since we're a child device.\r
- */\r
- if (p_adapter->p_ifc)\r
- p_adapter->p_ifc->wdm.InterfaceDereference(\r
- p_adapter->p_ifc->wdm.Context );\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
- return NDIS_STATUS_SUCCESS;\r
-}\r
-\r
-\r
-//! Initialization function called for each IOC discovered\r
-/* The MiniportInitialize function is a required function that sets up a\r
-NIC (or virtual NIC) for network I/O operations, claims all hardware\r
-resources necessary to the NIC in the registry, and allocates resources\r
-the driver needs to carry out network I/O operations.\r
-IRQL = PASSIVE_LEVEL\r
-\r
-@param p_open_status Pointer to a status field set if this function returns NDIS_STATUS_OPEN_ERROR\r
-@param p_selected_medium_index Pointer to unsigned integer noting index into medium_array for this NIC\r
-@param medium_array Array of mediums for this NIC\r
-@param medium_array_size Number of elements in medium_array\r
-@param h_adapter Handle assigned by NDIS for this NIC\r
-@param wrapper_config_context Handle used for Ndis initialization functions\r
-@return NDIS_STATUS_SUCCESS, NDIS_STATUS_UNSUPPORTED_MEDIA, NDIS_STATUS_RESOURCES,\r
-NDIS_STATUS_NOT_SUPPORTED \r
-*/\r
-\r
-/*void foo1(int i)\r
-{\r
- char temp[5200];\r
- if (i ==0) return;\r
- cl_msg_out("i = %d\n", i);\r
- foo1(i-1);\r
- \r
-}*/\r
- \r
-NDIS_STATUS\r
-SetDeviceRegistrationAttributes(\r
- ipoib_adapter_t *p_adapter,\r
- NDIS_HANDLE h_adapter\r
- )\r
-{\r
- NDIS_MINIPORT_ADD_DEVICE_REGISTRATION_ATTRIBUTES atr;\r
- NTSTATUS Status;\r
-\r
- NdisZeroMemory(&atr, sizeof(NDIS_MINIPORT_ADD_DEVICE_REGISTRATION_ATTRIBUTES));\r
-\r
- //\r
- // setting registration attributes\r
- //\r
- atr.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADD_DEVICE_REGISTRATION_ATTRIBUTES;\r
- atr.Header.Revision = NDIS_MINIPORT_ADD_DEVICE_REGISTRATION_ATTRIBUTES_REVISION_1;\r
- atr.Header.Size = NDIS_SIZEOF_MINIPORT_ADD_DEVICE_REGISTRATION_ATTRIBUTES_REVISION_1;\r
-\r
-\r
- atr.MiniportAddDeviceContext = (NDIS_HANDLE)p_adapter;\r
- atr.Flags = 0; \r
-\r
- Status = NdisMSetMiniportAttributes(h_adapter,\r
- (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&atr);\r
-\r
- return Status;\r
-}\r
-\r
-//NDIS 6.1\r
-#if 0\r
-NDIS_STATUS\r
-SetHardwareAssistAttributes(\r
- ipoib_adapter_t *p_adapter,\r
- NDIS_HANDLE h_adapter\r
- )\r
-{\r
- NDIS_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES atr;\r
- NTSTATUS Status;\r
-\r
- NdisZeroMemory(&atr, sizeof(NDIS_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES));\r
-\r
- //\r
- // setting registration attributes\r
- //\r
- atr.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES;\r
- atr.Header.Revision = NDIS_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES_REVISION_1;\r
- atr.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES_REVISION_1;\r
-\r
- NDIS_HD_SPLIT_ATTRIBUTES nhsa;\r
- NdisZeroMemory(&nhsa, sizeof(nhsa));\r
-\r
- nhsa.Header.Type = NDIS_OBJECT_TYPE_HD_SPLIT_ATTRIBUTES;\r
- nhsa.Header.Revision = NDIS_OFFLOAD_REVISION_1;\r
- nhsa.Header.Size = NDIS_SIZEOF_HD_SPLIT_ATTRIBUTES_REVISION_1;\r
-\r
- // BUGBUG: We are just cheating here ...\r
- nhsa.HardwareCapabilities = NDIS_HD_SPLIT_CAPS_SUPPORTS_HEADER_DATA_SPLIT;\r
-#if 0\r
- ... Only supported on B0\r
-\r
- NDIS_HD_SPLIT_CAPS_SUPPORTS_IPV4_OPTIONS |\r
- NDIS_HD_SPLIT_CAPS_SUPPORTS_IPV6_EXTENSION_HEADERS |\r
- NDIS_HD_SPLIT_CAPS_SUPPORTS_TCP_OPTIONS;\r
-#endif\r
-\r
- // The bellow should be left zero\r
- if (pPort->Config.HeaderDataSplit) {\r
- nhsa.CurrentCapabilities = NDIS_HD_SPLIT_CAPS_SUPPORTS_HEADER_DATA_SPLIT;\r
- } else {\r
- nhsa.CurrentCapabilities = 0;\r
- }\r
-\r
- nhsa.HDSplitFlags = 0;\r
- nhsa.BackfillSize = 0;\r
- nhsa.MaxHeaderSize = 0; \r
-\r
- atr.HDSplitAttributes = &nhsa;\r
-\r
- Status = NdisMSetMiniportAttributes(h_adapter,\r
- (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&atr);\r
-\r
- if (nhsa.HDSplitFlags & NDIS_HD_SPLIT_ENABLE_HEADER_DATA_SPLIT) {\r
- ASSERT(pPort->Config.HeaderDataSplit == TRUE);\r
- pPort->Config.HeaderDataSplit = TRUE;\r
- } \r
- else {\r
- ASSERT(pPort->Config.HeaderDataSplit == FALSE);\r
- pPort->Config.HeaderDataSplit = FALSE;\r
- }\r
-\r
- return Status;\r
-}\r
-#endif\r
-\r
-/*++\r
-Routine Description:\r
- the routine sets attributes that are associated with a miniport adapter.\r
-\r
-Arguments:\r
- pPort - Pointer to port object\r
-\r
-Return Value:\r
- NDIS_STATUS\r
-\r
-Note:\r
- Should be called in PASSIVE_LEVEL\r
- \r
---*/\r
-NDIS_STATUS\r
-SetAdapterRegistrationAttributes(\r
- ipoib_adapter_t *p_adapter,\r
- NDIS_HANDLE h_adapter\r
- )\r
- {\r
- NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES atr;\r
- NTSTATUS Status;\r
-\r
- NdisZeroMemory(&atr, sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES));\r
-\r
- /* setting registration attributes */\r
-\r
- atr.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES;\r
- atr.Header.Revision = NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;\r
- atr.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;\r
- //TODO NDIS60 Port or adapter\r
- atr.MiniportAdapterContext = (NDIS_HANDLE)p_adapter; //(NDIS_HANDLE)pPort->p_adapter;\r
- atr.AttributeFlags = NDIS_MINIPORT_ATTRIBUTES_BUS_MASTER;\r
- atr.CheckForHangTimeInSeconds = 10;\r
- atr.InterfaceType = NdisInterfacePci ; // ???? UH\r
- //TODO NDIS60 PNP or PCI ?\r
- //RegistrationAttributes.InterfaceType = NdisInterfacePNPBus;\r
-\r
- Status = NdisMSetMiniportAttributes(h_adapter,\r
- (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&atr);\r
-\r
- return Status;\r
-}\r
-\r
-\r
-/*++\r
-Routine Description:\r
- the routine sets generic attributes that are associated with a miniport \r
- adapter.\r
-\r
-Arguments:\r
- pPort - Pointer to port object\r
-\r
-Return Value:\r
- NDIS_STATUS\r
-\r
-Note:\r
- Should be called in PASSIVE_LEVEL\r
- \r
---*/\r
-NDIS_STATUS\r
-SetGenericAttributes(\r
- ipoib_adapter_t *p_adapter,\r
- NDIS_HANDLE h_adapter\r
- )\r
-{\r
- NDIS_STATUS Status;\r
-\r
- NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES gat;\r
- NdisZeroMemory(&gat, sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES));\r
-\r
- /* set up generic attributes */\r
-\r
- gat.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES;\r
- gat.Header.Revision = NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1;\r
- gat.Header.Size = sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES);\r
-\r
- gat.MediaType = NdisMedium802_3; \r
- gat.MaxXmitLinkSpeed = IPOIB_MEDIA_MAX_SPEED;\r
- gat.MaxRcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED;\r
- gat.XmitLinkSpeed = IPOIB_MEDIA_MAX_SPEED; //TODO NDIS60 NDIS_LINK_SPEED_UNKNOWN\r
- gat.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED; // TODO NDIS60 NDIS_LINK_SPEED_UNKNOWN ???\r
-\r
- gat.MediaConnectState = MediaConnectStateConnected; //TODO NDIS60 Check the current state\r
- gat.MediaDuplexState = MediaDuplexStateFull;\r
-\r
- gat.MtuSize = MAX_IB_MTU;\r
- gat.LookaheadSize = MAX_XFER_BLOCK_SIZE;\r
- gat.MacOptions = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | \r
- NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |\r
- NDIS_MAC_OPTION_NO_LOOPBACK |\r
- NDIS_MAC_OPTION_FULL_DUPLEX;\r
- //NDIS_MAC_OPTION_8021P_PRIORITY; //TODO NDIS60\r
- // DT: Enable for Header Data Split WHQL\r
- // | NDIS_MAC_OPTION_8021Q_VLAN;\r
-\r
- gat.SupportedPacketFilters = NDIS_PACKET_TYPE_DIRECTED |\r
- NDIS_PACKET_TYPE_MULTICAST |\r
- //NDIS_PACKET_TYPE_ALL_MULTICAST |\r
- NDIS_PACKET_TYPE_BROADCAST;\r
- \r
- gat.MaxMulticastListSize = MAX_MCAST;\r
-\r
- gat.MacAddressLength = HW_ADDR_LEN;\r
- \r
- NdisMoveMemory(gat.PermanentMacAddress,\r
- p_adapter->mac.addr,\r
- HW_ADDR_LEN);\r
-\r
- NdisMoveMemory(gat.CurrentMacAddress,\r
- p_adapter->params.conf_mac.addr,\r
- HW_ADDR_LEN);\r
-\r
-\r
- gat.PhysicalMediumType = NdisPhysicalMedium802_3;\r
- gat.AccessType = NET_IF_ACCESS_BROADCAST; \r
-\r
- gat.SupportedOidList = (PNDIS_OID)SUPPORTED_OIDS;\r
- gat.SupportedOidListLength = sizeof(SUPPORTED_OIDS);\r
-\r
-\r
- gat.DirectionType = NET_IF_DIRECTION_SENDRECEIVE; \r
- gat.ConnectionType = NET_IF_CONNECTION_DEDICATED; \r
- gat.IfType = IF_TYPE_ETHERNET_CSMACD; \r
- gat.IfConnectorPresent = TRUE; \r
- //TODO NDIS60 This value is absent for ETH driver\r
- gat.AccessType = NET_IF_ACCESS_BROADCAST; // NET_IF_ACCESS_BROADCAST for a typical ethernet adapter\r
-\r
-\r
- //TODO NDIS60 is it possible to reduce unsupported statistics\r
- gat.SupportedStatistics = \r
- NDIS_STATISTICS_XMIT_OK_SUPPORTED |\r
- NDIS_STATISTICS_RCV_OK_SUPPORTED |\r
- NDIS_STATISTICS_XMIT_ERROR_SUPPORTED |\r
- NDIS_STATISTICS_RCV_ERROR_SUPPORTED |\r
- NDIS_STATISTICS_RCV_CRC_ERROR_SUPPORTED |\r
- NDIS_STATISTICS_RCV_NO_BUFFER_SUPPORTED |\r
- NDIS_STATISTICS_TRANSMIT_QUEUE_LENGTH_SUPPORTED;\r
-\r
- //SupportedStatistics = NDIS_STATISTICS_XMIT_OK_SUPPORTED |\r
- // NDIS_STATISTICS_GEN_STATISTICS_SUPPORTED;\r
-\r
-\r
- //\r
- // Set power management capabilities\r
- //\r
- gat.PowerManagementCapabilities = NULL;\r
-#if 0\r
- NDIS_PNP_CAPABILITIES PowerManagementCapabilities;\r
- NdisZeroMemory(&PowerManagementCapabilities, sizeof(NDIS_PNP_CAPABILITIES));\r
- if (MPIsPoMgmtSupported(pPort))\r
- {\r
- MPFillPoMgmtCaps(pPort, &PowerManagementCapabilities, &Status, &unUsed);\r
- ASSERT(NT_SUCCESS(Status)); \r
- gat.PowerManagementCapabilities = &PowerManagementCapabilities;\r
- } \r
- else\r
- {\r
- \r
- }\r
-#endif\r
-\r
- //\r
- // Set RSS attributes\r
- //\r
- gat.RecvScaleCapabilities = NULL;\r
-#if 0\r
- NDIS_RECEIVE_SCALE_CAPABILITIES RssCapabilities;\r
- NdisZeroMemory(&RssCapabilities, sizeof(PNDIS_RECEIVE_SCALE_CAPABILITIES));\r
- Status = MPFillRssCapabilities(pPort, &RssCapabilities, &unUsed);\r
- if (NT_SUCCESS(Status)) \r
- {\r
- gat.RecvScaleCapabilities = &RssCapabilities;\r
- } \r
- else\r
- {\r
- //\r
- // do not fail the call because of failure to get PM caps\r
- //\r
- Status = NDIS_STATUS_SUCCESS;\r
- gat.RecvScaleCapabilities = NULL;\r
- }\r
-#endif\r
-\r
- Status = NdisMSetMiniportAttributes(h_adapter,\r
- (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&gat);\r
-\r
- return Status;\r
-}\r
-\r
-\r
-/*++\r
-Routine Description:\r
- The routine sets an NDIS_OFFLOAD structure indicates the current offload \r
- capabilities that are provided by the miniport adapter \r
- \r
-Arguments:\r
- pPort - a pointer to port object\r
- offload - reference to NDIS_OFFLOAD object that should be filled\r
-\r
-Return Value:\r
- None.\r
- \r
---*/\r
-static\r
-void\r
-OffloadConfig(\r
- ipoib_adapter_t *p_adapter,\r
- NDIS_OFFLOAD *p_offload\r
- )\r
-{ \r
-\r
- ULONG ulEncapsulation = NDIS_ENCAPSULATION_IEEE_802_3 | NDIS_ENCAPSULATION_IEEE_802_3_P_AND_Q;\r
-\r
- NdisZeroMemory(p_offload, NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_1);\r
-\r
- p_offload->Header.Type = NDIS_OBJECT_TYPE_OFFLOAD;\r
- p_offload->Header.Revision = NDIS_OFFLOAD_REVISION_1; // BUGBUG: do we need to support revision 2? UH 17-May-2008\r
- p_offload->Header.Size = NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_1;\r
-\r
- p_offload->Checksum.IPv4Transmit.Encapsulation = ulEncapsulation;\r
- p_offload->Checksum.IPv4Transmit.IpOptionsSupported = \r
- p_offload->Checksum.IPv4Transmit.TcpOptionsSupported = \r
- p_offload->Checksum.IPv4Transmit.TcpChecksum = \r
- p_offload->Checksum.IPv4Transmit.UdpChecksum = \r
- p_offload->Checksum.IPv4Transmit.IpChecksum =!!(p_adapter->params.send_chksum_offload);\r
-\r
- p_offload->Checksum.IPv4Receive.Encapsulation = ulEncapsulation;\r
- p_offload->Checksum.IPv4Receive.IpOptionsSupported = \r
- p_offload->Checksum.IPv4Receive.TcpOptionsSupported = \r
- p_offload->Checksum.IPv4Receive.TcpChecksum = \r
- p_offload->Checksum.IPv4Receive.UdpChecksum = \r
- p_offload->Checksum.IPv4Receive.IpChecksum = !!(p_adapter->params.recv_chksum_offload); //TODO NDIS60\r
-\r
-\r
- p_offload->Checksum.IPv6Transmit.Encapsulation = ulEncapsulation;\r
- p_offload->Checksum.IPv6Transmit.IpExtensionHeadersSupported = \r
- p_offload->Checksum.IPv6Transmit.TcpOptionsSupported =\r
- p_offload->Checksum.IPv6Transmit.TcpChecksum = \r
- p_offload->Checksum.IPv6Transmit.UdpChecksum = FALSE;\r
-\r
-\r
- p_offload->Checksum.IPv6Receive.Encapsulation = ulEncapsulation;\r
- p_offload->Checksum.IPv6Receive.IpExtensionHeadersSupported = \r
- p_offload->Checksum.IPv6Receive.TcpOptionsSupported = \r
- p_offload->Checksum.IPv6Receive.TcpChecksum = \r
- p_offload->Checksum.IPv6Receive.UdpChecksum = FALSE;\r
-\r
- if (p_adapter->params.lso)\r
- {\r
- p_offload->LsoV1.IPv4.Encapsulation = ulEncapsulation;\r
- p_offload->LsoV1.IPv4.MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE;\r
-#define LSO_MIN_SEG_COUNT 2\r
- p_offload->LsoV1.IPv4.MinSegmentCount = LSO_MIN_SEG_COUNT;\r
- \r
- \r
- p_offload->LsoV1.IPv4.TcpOptions = NDIS_OFFLOAD_SUPPORTED;\r
- p_offload->LsoV1.IPv4.IpOptions = NDIS_OFFLOAD_SUPPORTED;\r
-\r
- p_offload->LsoV2.IPv4.Encapsulation = ulEncapsulation;\r
- p_offload->LsoV2.IPv4.MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE;\r
- p_offload->LsoV2.IPv4.MinSegmentCount = LSO_MIN_SEG_COUNT;\r
-\r
- p_offload->LsoV2.IPv6.Encapsulation = ulEncapsulation;\r
- p_offload->LsoV2.IPv6.MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE;\r
- p_offload->LsoV2.IPv6.MinSegmentCount = LSO_MIN_SEG_COUNT;\r
-\r
- p_offload->LsoV2.IPv6.IpExtensionHeadersSupported = NDIS_OFFLOAD_NOT_SUPPORTED;\r
- p_offload->LsoV2.IPv6.TcpOptionsSupported = NDIS_OFFLOAD_SUPPORTED;\r
- }\r
-\r
-}\r
-\r
-\r
-/*++\r
-Routine Description:\r
- The routine sets an NDIS_OFFLOAD structure that indicates all the task \r
- offload capabilites that are supported by the NIC. These capabilities include\r
- capabilities that are currently disabled by standardized keywords in the registry. \r
- \r
-Arguments:\r
- offload - reference to NDIS_OFFLOAD object that should be filled\r
-\r
-Return Value:\r
- None.\r
- \r
---*/\r
-static\r
-void\r
-OffloadCapabilities(\r
- NDIS_OFFLOAD *p_offload\r
- )\r
-{ \r
- ULONG ulEncapsulation = NDIS_ENCAPSULATION_IEEE_802_3 | NDIS_ENCAPSULATION_IEEE_802_3_P_AND_Q ;\r
- NdisZeroMemory(p_offload, NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_1); \r
-\r
- p_offload->Header.Type = NDIS_OBJECT_TYPE_OFFLOAD;\r
- p_offload->Header.Revision = NDIS_OFFLOAD_REVISION_1; // BUGBUG: do we need to support revision 2? UH 17-May-2008\r
- p_offload->Header.Size = NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_1;\r
-\r
- p_offload->Checksum.IPv4Transmit.Encapsulation = ulEncapsulation;\r
- p_offload->Checksum.IPv4Transmit.IpOptionsSupported = TRUE;\r
- p_offload->Checksum.IPv4Transmit.TcpOptionsSupported = TRUE;\r
- p_offload->Checksum.IPv4Transmit.TcpChecksum = TRUE;\r
- p_offload->Checksum.IPv4Transmit.UdpChecksum = TRUE;\r
- p_offload->Checksum.IPv4Transmit.IpChecksum = TRUE;\r
-\r
- p_offload->Checksum.IPv4Receive.Encapsulation = ulEncapsulation;\r
- p_offload->Checksum.IPv4Receive.IpOptionsSupported = TRUE;\r
- p_offload->Checksum.IPv4Receive.TcpOptionsSupported = TRUE;\r
- p_offload->Checksum.IPv4Receive.TcpChecksum = TRUE;\r
- p_offload->Checksum.IPv4Receive.UdpChecksum = TRUE; \r
- p_offload->Checksum.IPv4Receive.IpChecksum = TRUE;\r
-\r
-\r
- //\r
- // BUGBUG::\r
- // During a HW bug that didn't handle correctly packets with \r
- // IPv6 Extension Headers -> we set IpExtensionHeadersSupported to TRUE\r
- //\r
- p_offload->Checksum.IPv6Transmit.Encapsulation = ulEncapsulation;\r
- p_offload->Checksum.IPv6Transmit.IpExtensionHeadersSupported = TRUE;\r
- p_offload->Checksum.IPv6Transmit.TcpOptionsSupported = TRUE;\r
- p_offload->Checksum.IPv6Transmit.TcpChecksum = TRUE;\r
- p_offload->Checksum.IPv6Transmit.UdpChecksum = TRUE;\r
-\r
-\r
- p_offload->Checksum.IPv6Receive.Encapsulation = ulEncapsulation;\r
- p_offload->Checksum.IPv6Receive.IpExtensionHeadersSupported = TRUE;\r
- p_offload->Checksum.IPv6Receive.TcpOptionsSupported = TRUE;\r
- p_offload->Checksum.IPv6Receive.TcpChecksum = TRUE;\r
- p_offload->Checksum.IPv6Receive.UdpChecksum = TRUE;\r
-\r
- p_offload->LsoV1.IPv4.Encapsulation = ulEncapsulation;\r
- p_offload->LsoV1.IPv4.MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE;\r
- p_offload->LsoV1.IPv4.MinSegmentCount = 2;\r
- p_offload->LsoV1.IPv4.TcpOptions = NDIS_OFFLOAD_SUPPORTED;\r
- p_offload->LsoV1.IPv4.IpOptions = NDIS_OFFLOAD_SUPPORTED;\r
-\r
- p_offload->LsoV2.IPv4.Encapsulation = ulEncapsulation;\r
- p_offload->LsoV2.IPv4.MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE;\r
- p_offload->LsoV2.IPv4.MinSegmentCount = 2;\r
-\r
- p_offload->LsoV2.IPv6.Encapsulation = ulEncapsulation;\r
- p_offload->LsoV2.IPv6.MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE;\r
- p_offload->LsoV2.IPv6.MinSegmentCount = 2;\r
-\r
- p_offload->LsoV2.IPv6.IpExtensionHeadersSupported = NDIS_OFFLOAD_NOT_SUPPORTED;\r
- p_offload->LsoV2.IPv6.TcpOptionsSupported = NDIS_OFFLOAD_SUPPORTED;\r
-\r
- }\r
-\r
-\r
-/*++\r
-Routine Description:\r
- The routine sets offload attributes that are associated with a miniport \r
- adapter.\r
-\r
-Arguments:\r
- pPort - Pointer to port object\r
-\r
-Return Value:\r
- NDIS_STATUS\r
-\r
-Note:\r
- Should be called in PASSIVE_LEVEL\r
- \r
---*/\r
-NDIS_STATUS\r
-SetOffloadAttributes(\r
- ipoib_adapter_t *p_adapter,\r
- NDIS_HANDLE h_adapter\r
- )\r
-{\r
- NDIS_STATUS Status;\r
- NDIS_OFFLOAD offload,hwOffload;\r
- //ULONG ulEncapsulation = NDIS_ENCAPSULATION_IEEE_802_3 | NDIS_ENCAPSULATION_IEEE_802_3_P_AND_Q;\r
-\r
- NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES oat; \r
- NdisZeroMemory(&oat, sizeof(NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES));\r
-\r
- oat.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES;\r
- oat.Header.Revision = NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES_REVISION_1;\r
- oat.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES_REVISION_1;\r
-\r
-\r
- OffloadConfig(p_adapter, &offload);\r
-\r
-\r
- OffloadCapabilities(&hwOffload);\r
-\r
- oat.DefaultOffloadConfiguration = &offload;\r
- oat.HardwareOffloadCapabilities = &hwOffload;\r
-\r
- Status = NdisMSetMiniportAttributes(h_adapter,\r
- (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&oat);\r
-\r
- return Status;\r
-}\r
-\r
-\r
-/*++\r
-\r
-Routine Description:\r
- An NDIS 6.0 miniport driver must call NdisMSetMiniportAttributes\r
- at least twice. The first call is to register itself with NDIS.\r
- The second call is to register the miniport driver's general\r
- attributes with NDIS.\r
-\r
- NdisMSetMiniportAttributes takes a parameter of type\r
- NDIS_MINIPORT_ADAPTER_ATTRIBUTES, which is a union of several miniport\r
- adapter attributes. Miniport drivers must first call\r
- NdisMSetMiniportAttributes and pass in an\r
- NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES structure\r
- that contains the pointer to its own context area, attribute flags,\r
- check-for-hang time, and interface type.\r
-\r
- All NDIS 6.0 miniport drivers are deserialized by default.\r
-\r
-Arguments:\r
- pPort - Pointer to port object\r
-\r
-Return Value:\r
- NDIS_STATUS\r
-\r
-Note:\r
- Should be called in PASSIVE_LEVEL\r
- \r
---*/\r
- NDIS_STATUS\r
- SetAttributes(\r
- ipoib_adapter_t *p_adapter,\r
- NDIS_HANDLE h_adapter\r
- )\r
- {\r
- NTSTATUS Status;\r
-\r
-\r
- Status = SetDeviceRegistrationAttributes(p_adapter, h_adapter);\r
- if (Status != NDIS_STATUS_SUCCESS)\r
- {\r
- //ETH_PRINT(TRACE_LEVEL_ERROR, ETH_INIT, "Set device registration failed Error=0x%x\n", Status);\r
- return Status;\r
- }\r
-\r
-\r
- Status = SetAdapterRegistrationAttributes(p_adapter, h_adapter);\r
- if (Status != NDIS_STATUS_SUCCESS)\r
- {\r
- //ETH_PRINT(TRACE_LEVEL_ERROR, ETH_INIT, "Set adapter attributes failed Error=0x%x\n", Status);\r
- return Status;\r
- }\r
-\r
- Status = SetOffloadAttributes(p_adapter, h_adapter);\r
- if (Status != NDIS_STATUS_SUCCESS)\r
- {\r
- //ETH_PRINT(TRACE_LEVEL_ERROR, ETH_INIT, "Set OFFLOAD attributes failed Error=0x%x\n", Status);\r
- return Status;\r
- }\r
- \r
-#if 0\r
- if(!pPort->Config.fWHQL)\r
- {\r
- Status = SetHardwareAssistAttributes(pPort);\r
- if (Status != NDIS_STATUS_SUCCESS)\r
- {\r
- //ETH_PRINT(TRACE_LEVEL_ERROR, ETH_INIT, "Set Hardware Assist Attributes failed Error=0x%x\n", Status);\r
- return Status;\r
- }\r
- }\r
-#endif\r
-\r
- Status = SetGenericAttributes(p_adapter, h_adapter);\r
- if (Status != NDIS_STATUS_SUCCESS)\r
- {\r
- //ETH_PRINT(TRACE_LEVEL_ERROR, ETH_INIT, "Set generic attributes failed Error=0x%x\n", Status);\r
- return Status;\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-\r
-\r
-NDIS_STATUS\r
-InitNdisScatterGatherDma(\r
- ipoib_adapter_t *p_adapter,\r
- NDIS_HANDLE h_adapter\r
- )\r
-{\r
- NDIS_STATUS status;\r
- NDIS_SG_DMA_DESCRIPTION DmaDescription;\r
- \r
- NdisZeroMemory(&DmaDescription, sizeof(DmaDescription));\r
-\r
- DmaDescription.Header.Type = NDIS_OBJECT_TYPE_SG_DMA_DESCRIPTION;\r
- DmaDescription.Header.Revision = NDIS_SG_DMA_DESCRIPTION_REVISION_1;\r
- DmaDescription.Header.Size = sizeof(NDIS_SG_DMA_DESCRIPTION);\r
- DmaDescription.Flags = NDIS_SG_DMA_64_BIT_ADDRESS; \r
- //\r
- // Even if offload is enabled, the packet size for mapping shouldn't change\r
- //\r
- DmaDescription.MaximumPhysicalMapping = LARGE_SEND_OFFLOAD_SIZE + LSO_MAX_HEADER;\r
-\r
- DmaDescription.ProcessSGListHandler = ipoib_process_sg_list;\r
- DmaDescription.SharedMemAllocateCompleteHandler = NULL;\r
-\r
- DmaDescription.Header.Type = NDIS_OBJECT_TYPE_SG_DMA_DESCRIPTION;\r
- DmaDescription.Header.Revision = NDIS_SG_DMA_DESCRIPTION_REVISION_1;\r
- DmaDescription.Header.Size = sizeof(NDIS_SG_DMA_DESCRIPTION);//NDIS_SIZEOF_SG_DMA_DESCRIPTION_REVISION_1;\r
-\r
- DmaDescription.Flags = NDIS_SG_DMA_64_BIT_ADDRESS;\r
- //DmaDescription.MaximumPhysicalMapping = pPort->p_adapter->params.xfer_block_size;\r
-\r
- DmaDescription.ProcessSGListHandler = ipoib_process_sg_list;\r
- DmaDescription.SharedMemAllocateCompleteHandler = NULL;\r
- \r
- status = NdisMRegisterScatterGatherDma(\r
- h_adapter,\r
- &DmaDescription,\r
- &p_adapter->NdisMiniportDmaHandle);\r
-\r
- if( status != NDIS_STATUS_SUCCESS )\r
- {\r
- //TODO NDIS60\r
- //ipoib_destroy_adapter( p_adapter );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("NdisMRegisterScatterGatherDma returned 0x%.8x.\n", status) );\r
- \r
- }\r
- //NDIS sets this value before it returns from NdisMRegisterScatterGatherDma. \r
- //Miniport drivers should use this size to preallocate memory for each scatter/gather list. \r
- p_adapter->sg_list_size = DmaDescription.ScatterGatherListSize ;\r
- \r
- return status;\r
-}\r
-\r
-\r
-NDIS_STATUS \r
-MPInitializeTest(\r
- IN NDIS_HANDLE MiniportAdapterHandle,\r
- IN NDIS_HANDLE MiniportDriverContext,\r
- IN PNDIS_MINIPORT_INIT_PARAMETERS MiniportInitParameters\r
- )\r
-/*++\r
-Routine Description:\r
-\r
- MiniportInitialize handler\r
-\r
-Arguments:\r
-\r
- MiniportAdapterHandle The handle NDIS uses to refer to us\r
- MiniportDriverContext Handle passed to NDIS when we registered the driver\r
- MiniportInitParameters Initialization parameters\r
- \r
-Return Value:\r
-\r
- NDIS_STATUS_SUCCESS unless something goes wrong\r
-\r
---*/\r
-{\r
-\r
- NDIS_STATUS Status = NDIS_STATUS_SUCCESS;\r
- //PMP_PORT pPort = NULL;\r
- ipoib_adapter_t *p_adapter;\r
-// NDIS_MINIPORT_INTERRUPT_CHARACTERISTICS Interrupt;\r
- NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES RegistrationAttributes;\r
- NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES GeneralAttributes;\r
- //NDIS_TIMER_CHARACTERISTICS Timer; \r
- NDIS_PNP_CAPABILITIES PowerManagementCapabilities; \r
- //PMP_ADAPTER Adapter = NULL;\r
- //PVOID NetworkAddress;\r
-// UINT index;\r
-// UINT uiPnpCommandValue;\r
-// ULONG ulInfoLen;\r
- //ULONG InterruptVersion;\r
-// LARGE_INTEGER liDueTime;\r
- //BOOLEAN isTimerAlreadyInQueue = FALSE;\r
-// uint8_t portId;\r
- ib_api_status_t ib_status;\r
-#if 0 \r
-#if DBG\r
- LARGE_INTEGER TS, TD, TE;\r
-#endif\r
-#endif\r
-\r
- cl_dbg_out ("====> MPInitialize\n");\r
-\r
- UNREFERENCED_PARAMETER(MiniportDriverContext);\r
- UNREFERENCED_PARAMETER(MiniportInitParameters);\r
- \r
-\r
-\r
- \r
-\r
- {\r
-\r
- ib_status = ipoib_create_adapter(MiniportDriverContext, MiniportAdapterHandle, &p_adapter );\r
- if( ib_status != IB_SUCCESS )\r
- {\r
- ASSERT(FALSE);\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ipoib_create_adapter returned status %d.\n", ib_status ) );\r
- return NDIS_STATUS_FAILURE;\r
- }\r
-\r
- \r
-\r
- NdisZeroMemory(&RegistrationAttributes, sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES));\r
- NdisZeroMemory(&GeneralAttributes, sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES));\r
-\r
- //\r
- // setting registration attributes\r
- //\r
- RegistrationAttributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES;\r
- RegistrationAttributes.Header.Revision = NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;\r
- RegistrationAttributes.Header.Size = sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES);\r
-\r
- RegistrationAttributes.MiniportAdapterContext = (NDIS_HANDLE)p_adapter;\r
- RegistrationAttributes.AttributeFlags = NDIS_MINIPORT_ATTRIBUTES_HARDWARE_DEVICE | \r
- NDIS_MINIPORT_ATTRIBUTES_BUS_MASTER;\r
- \r
- RegistrationAttributes.CheckForHangTimeInSeconds = 2;\r
- RegistrationAttributes.InterfaceType = NdisInterfacePci;\r
-\r
- Status = NdisMSetMiniportAttributes(MiniportAdapterHandle,\r
- (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&RegistrationAttributes);\r
-\r
- if (Status != NDIS_STATUS_SUCCESS)\r
- {\r
- //break;\r
- return Status;\r
- }\r
-\r
-#if 0 \r
- //\r
- // Read the registry parameters\r
- //\r
- Status = NICReadRegParameters(Adapter);\r
- \r
- if (Status != NDIS_STATUS_SUCCESS) \r
- {\r
- break;\r
- }\r
-\r
- \r
- //\r
- // Find the physical adapter\r
- //\r
- Status = MpFindAdapter(Adapter, MiniportInitParameters->AllocatedResources);\r
- if (Status != NDIS_STATUS_SUCCESS)\r
- {\r
- break;\r
- }\r
-\r
- //\r
- // Map bus-relative IO range to system IO space\r
- //\r
- Status = NdisMRegisterIoPortRange(\r
- (PVOID *)&Adapter->PortOffset,\r
- Adapter->AdapterHandle,\r
- Adapter->IoBaseAddress,\r
- Adapter->IoRange);\r
- if (Status != NDIS_STATUS_SUCCESS)\r
- {\r
- DBGPRINT(MP_ERROR, ("NdisMRegisterioPortRange failed\n"));\r
- \r
- NdisWriteErrorLogEntry(\r
- Adapter->AdapterHandle,\r
- NDIS_ERROR_CODE_BAD_IO_BASE_ADDRESS,\r
- 0);\r
- \r
- break;\r
- }\r
- \r
- //\r
- // Read additional info from NIC such as MAC address\r
- //\r
- Status = NICReadAdapterInfo(Adapter);\r
- if (Status != NDIS_STATUS_SUCCESS) \r
- {\r
- break;\r
- }\r
-\r
-#endif\r
- //\r
- // set up generic attributes\r
- //\r
- \r
-\r
- GeneralAttributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES;\r
- GeneralAttributes.Header.Revision = NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1;\r
- GeneralAttributes.Header.Size = sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES);\r
-\r
- GeneralAttributes.MediaType = NdisMedium802_3;\r
-\r
- GeneralAttributes.MtuSize = DEFAULT_MTU;\r
-#define LINE_SPEED_10_GBTS 10000000000\r
- GeneralAttributes.MaxXmitLinkSpeed = LINE_SPEED_10_GBTS;\r
- GeneralAttributes.MaxRcvLinkSpeed = LINE_SPEED_10_GBTS;\r
- GeneralAttributes.XmitLinkSpeed = NDIS_LINK_SPEED_UNKNOWN;\r
- GeneralAttributes.RcvLinkSpeed = NDIS_LINK_SPEED_UNKNOWN;\r
- GeneralAttributes.MediaConnectState = MediaConnectStateUnknown;\r
- GeneralAttributes.MediaDuplexState = MediaDuplexStateUnknown;\r
- GeneralAttributes.LookaheadSize = MAX_XFER_BLOCK_SIZE;\r
-#if 0\r
- MPFillPoMgmtCaps (Adapter, \r
- &PowerManagementCapabilities, \r
- &Status,\r
- &ulInfoLen);\r
-#endif\r
- NdisZeroMemory(&PowerManagementCapabilities, sizeof(NDIS_PNP_CAPABILITIES));\r
- Status = NDIS_STATUS_NOT_SUPPORTED;\r
- // ulInfoLen = 0;\r
-\r
- if (Status == NDIS_STATUS_SUCCESS)\r
- {\r
- GeneralAttributes.PowerManagementCapabilities = &PowerManagementCapabilities;\r
- }\r
- else\r
- {\r
- GeneralAttributes.PowerManagementCapabilities = NULL;\r
- }\r
-\r
- //\r
- // do not fail the call because of failure to get PM caps\r
- //\r
- Status = NDIS_STATUS_SUCCESS;\r
-\r
- GeneralAttributes.MacOptions = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | \r
- NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |\r
- NDIS_MAC_OPTION_NO_LOOPBACK;\r
-\r
- GeneralAttributes.SupportedPacketFilters = NDIS_PACKET_TYPE_DIRECTED |\r
- NDIS_PACKET_TYPE_MULTICAST |\r
- NDIS_PACKET_TYPE_ALL_MULTICAST |\r
- NDIS_PACKET_TYPE_BROADCAST;\r
- \r
- GeneralAttributes.MaxMulticastListSize = MAX_MCAST;\r
- GeneralAttributes.MacAddressLength = HW_ADDR_LEN;\r
- NdisMoveMemory(GeneralAttributes.PermanentMacAddress,\r
- p_adapter->mac.addr,\r
- HW_ADDR_LEN);\r
-\r
- NdisMoveMemory(GeneralAttributes.CurrentMacAddress,\r
- p_adapter->params.conf_mac.addr,\r
- HW_ADDR_LEN);\r
- GeneralAttributes.RecvScaleCapabilities = NULL;\r
- GeneralAttributes.AccessType = NET_IF_ACCESS_BROADCAST; // NET_IF_ACCESS_BROADCAST for a typical ethernet adapter\r
- GeneralAttributes.DirectionType = NET_IF_DIRECTION_SENDRECEIVE; // NET_IF_DIRECTION_SENDRECEIVE for a typical ethernet adapter\r
- GeneralAttributes.ConnectionType = NET_IF_CONNECTION_DEDICATED; // NET_IF_CONNECTION_DEDICATED for a typical ethernet adapter\r
- GeneralAttributes.IfType = IF_TYPE_ETHERNET_CSMACD; // IF_TYPE_ETHERNET_CSMACD for a typical ethernet adapter (regardless of speed)\r
- GeneralAttributes.IfConnectorPresent = TRUE; // RFC 2665 TRUE if physical adapter\r
-\r
- GeneralAttributes.SupportedStatistics = NDIS_STATISTICS_XMIT_OK_SUPPORTED |\r
- NDIS_STATISTICS_RCV_OK_SUPPORTED |\r
- NDIS_STATISTICS_XMIT_ERROR_SUPPORTED |\r
- NDIS_STATISTICS_RCV_ERROR_SUPPORTED |\r
- NDIS_STATISTICS_RCV_CRC_ERROR_SUPPORTED |\r
- NDIS_STATISTICS_RCV_NO_BUFFER_SUPPORTED |\r
- NDIS_STATISTICS_TRANSMIT_QUEUE_LENGTH_SUPPORTED |\r
- NDIS_STATISTICS_GEN_STATISTICS_SUPPORTED;\r
- \r
- GeneralAttributes.SupportedOidList = NICSupportedOidsTest;\r
- GeneralAttributes.SupportedOidListLength = sizeof(NICSupportedOidsTest);\r
-\r
- Status = NdisMSetMiniportAttributes(MiniportAdapterHandle,\r
- (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&GeneralAttributes);\r
-\r
-\r
-#if 0 \r
- //\r
- // Allocate all other memory blocks including shared memory\r
- //\r
- Status = NICAllocAdapterMemory(Adapter);\r
- if (Status != NDIS_STATUS_SUCCESS) \r
- {\r
- break;\r
- }\r
- //\r
- // Init send data structures\r
- //\r
- NICInitSend(Adapter);\r
-\r
- //\r
- // Init receive data structures\r
- //\r
- Status = NICInitRecv(Adapter);\r
- if (Status != NDIS_STATUS_SUCCESS)\r
- {\r
- break;\r
- }\r
- //\r
- // Map bus-relative registers to virtual system-space\r
- // \r
- Status = NdisMMapIoSpace(\r
- (PVOID *) &(Adapter->CSRAddress),\r
- Adapter->AdapterHandle,\r
- Adapter->MemPhysAddress,\r
- NIC_MAP_IOSPACE_LENGTH);\r
- if (Status != NDIS_STATUS_SUCCESS)\r
- {\r
- DBGPRINT(MP_ERROR, ("NdisMMapIoSpace failed\n"));\r
- \r
- NdisWriteErrorLogEntry(\r
- Adapter->AdapterHandle,\r
- NDIS_ERROR_CODE_RESOURCE_CONFLICT,\r
- 1,\r
- ERRLOG_MAP_IO_SPACE);\r
- \r
- break;\r
- }\r
-\r
- DBGPRINT(MP_INFO, ("CSRAddress="PTR_FORMAT"\n", Adapter->CSRAddress));\r
-\r
- //\r
- // Disable interrupts here which is as soon as possible\r
- //\r
- NICDisableInterrupt(Adapter);\r
-#endif\r
- \r
- //\r
- // Register the interrupt\r
- //\r
- //\r
- \r
- //\r
- // the embeded NDIS interrupt structure is already zero'ed out\r
- // as part of the adapter structure\r
- //\r
- #if 0\r
- NdisZeroMemory(&Interrupt, sizeof(NDIS_MINIPORT_INTERRUPT_CHARACTERISTICS));\r
- \r
- Interrupt.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_INTERRUPT;\r
- Interrupt.Header.Revision = NDIS_MINIPORT_INTERRUPT_REVISION_1;\r
- Interrupt.Header.Size = sizeof(NDIS_MINIPORT_INTERRUPT_CHARACTERISTICS);\r
-\r
- Interrupt.InterruptHandler = MPIsr;\r
- Interrupt.InterruptDpcHandler = MPHandleInterrupt;\r
- Interrupt.DisableInterruptHandler = NULL;\r
- Interrupt.EnableInterruptHandler = NULL;\r
-\r
-\r
-\r
- Status = NdisMRegisterInterruptEx(Adapter->AdapterHandle,\r
- Adapter,\r
- &Interrupt,\r
- &Adapter->NdisInterruptHandle\r
- );\r
- \r
- \r
- if (Status != NDIS_STATUS_SUCCESS)\r
- {\r
- DBGPRINT(MP_ERROR, ("NdisMRegisterInterrupt failed\n"));\r
- \r
- NdisWriteErrorLogEntry(\r
- Adapter->AdapterHandle,\r
- NDIS_ERROR_CODE_INTERRUPT_CONNECT,\r
- 0);\r
- \r
- break;\r
- }\r
- \r
- //\r
- // If the driver support MSI\r
- //\r
- Adapter->InterruptType = Interrupt.InterruptType;\r
-\r
- if (Adapter->InterruptType == NDIS_CONNECT_MESSAGE_BASED)\r
- {\r
- Adapter->MessageInfoTable = Interrupt.MessageInfoTable;\r
- }\r
- \r
- //\r
- // If the driver supports MSI, here it should what kind of interrupt is granted. If MSI is granted,\r
- // the driver can check Adapter->MessageInfoTable to get MSI information\r
- //\r
- \r
- \r
- MP_SET_FLAG(Adapter, fMP_ADAPTER_INTERRUPT_IN_USE);\r
-\r
- //\r
- // Test our adapter hardware\r
- //\r
- Status = NICSelfTest(Adapter);\r
- if (Status != NDIS_STATUS_SUCCESS)\r
- {\r
- break;\r
- }\r
- \r
- //\r
- // Init the hardware and set up everything\r
- //\r
- Status = NICInitializeAdapter(Adapter);\r
- if (Status != NDIS_STATUS_SUCCESS)\r
- {\r
- break;\r
- }\r
- \r
- //\r
- // initial state is paused\r
- //\r
- Adapter->AdapterState = NicPaused;\r
- \r
- //\r
- // Set the link detection flag\r
- //\r
- MP_SET_FLAG(Adapter, fMP_ADAPTER_LINK_DETECTION);\r
- \r
- //\r
- // Increment the reference count so halt handler will wait \r
- //\r
- MP_INC_REF(Adapter); \r
-\r
- //\r
- // Enable the interrupt\r
- //\r
- NICEnableInterrupt(Adapter);\r
-\r
- \r
- NdisZeroMemory(&Timer, sizeof(NDIS_TIMER_CHARACTERISTICS));\r
- \r
- Timer.Header.Type = NDIS_OBJECT_TYPE_TIMER_CHARACTERISTICS;\r
- Timer.Header.Revision = NDIS_TIMER_CHARACTERISTICS_REVISION_1;\r
- Timer.Header.Size = sizeof(NDIS_TIMER_CHARACTERISTICS);\r
-\r
- Timer.AllocationTag = NIC_TAG;\r
- Timer.TimerFunction = MpLinkDetectionDpc;\r
- Timer.FunctionContext = Adapter;\r
-\r
- //\r
- // Minimize init-time\r
- //\r
- Status = NdisAllocateTimerObject(\r
- Adapter->AdapterHandle,\r
- &Timer,\r
- &Adapter->LinkDetectionTimerHandle);\r
-\r
- if (Status != NDIS_STATUS_SUCCESS)\r
- {\r
- break;\r
- }\r
-\r
- liDueTime.QuadPart = NIC_LINK_DETECTION_DELAY;\r
- isTimerAlreadyInQueue =NdisSetTimerObject(Adapter->LinkDetectionTimerHandle, liDueTime, 0, NULL);\r
- ASSERT(!isTimerAlreadyInQueue);\r
-#endif \r
- } \r
-#if 0\r
- if (Adapter && (Status != NDIS_STATUS_SUCCESS))\r
- {\r
- //\r
- // Undo everything if it failed\r
- //\r
- MP_DEC_REF(Adapter);\r
- MpFreeAdapter(Adapter);\r
- }\r
-\r
- DBGPRINT_S(Status, ("<==== MPInitialize, Status=%x\n", Status));\r
-#endif\r
- /* Create the adapter adapter */\r
- ib_status = ipoib_start_adapter( p_adapter );\r
- if( ib_status != IB_SUCCESS )\r
- {\r
- ASSERT(FALSE);\r
-\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ipoib_start_adapter returned status %d.\n", ib_status ) );\r
- return NDIS_STATUS_FAILURE;\r
- }\r
- \r
- ipoib_ref_ibat();\r
- return NDIS_STATUS_SUCCESS;\r
-}\r
-\r
-\r
-\r
-NDIS_STATUS\r
-ipoib_initialize_ex(\r
- IN NDIS_HANDLE h_adapter,\r
- IN NDIS_HANDLE config_context,\r
- IN PNDIS_MINIPORT_INIT_PARAMETERS MiniportInitParameters)\r
- {\r
- NDIS_STATUS status;\r
- ib_api_status_t ib_status;\r
- ipoib_adapter_t *p_adapter;\r
- //NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES RegistrationAttributes;\r
- //NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES GeneralAttributes;\r
-#if IPOIB_USE_DMA\r
- //NDIS_SG_DMA_DESCRIPTION DmaDescription;\r
-#endif\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
- \r
-#ifdef _DEBUG_\r
- PAGED_CODE();\r
-#endif\r
- \r
- UNUSED_PARAM( config_context );\r
- UNUSED_PARAM( MiniportInitParameters );\r
- \r
- //foo1(100);\r
- /* Create the adapter adapter */\r
- ib_status = ipoib_create_adapter(config_context, h_adapter, &p_adapter );\r
- if( ib_status != IB_SUCCESS )\r
- {\r
- ASSERT(FALSE);\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ipoib_create_adapter returned status %d.\n", ib_status ) );\r
- return NDIS_STATUS_FAILURE;\r
- }\r
- p_adapter->ipoib_state = IPOIB_PAUSED;\r
- status = SetAttributes(p_adapter, h_adapter);\r
- if (status != NDIS_STATUS_SUCCESS) {\r
- ASSERT(FALSE);\r
- }\r
-#if 0\r
- NdisZeroMemory(&RegistrationAttributes, sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES));\r
- NdisZeroMemory(&GeneralAttributes, sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES));\r
- \r
- /* setting registration attributes */\r
- RegistrationAttributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES;\r
- RegistrationAttributes.Header.Revision = NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;\r
- RegistrationAttributes.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;\r
- \r
- RegistrationAttributes.MiniportAdapterContext = (NDIS_HANDLE)p_adapter;\r
- RegistrationAttributes.AttributeFlags = NDIS_MINIPORT_ATTRIBUTES_BUS_MASTER;\r
- \r
- RegistrationAttributes.CheckForHangTimeInSeconds = 10;\r
- RegistrationAttributes.InterfaceType = NdisInterfacePNPBus;\r
- \r
- status = NdisMSetMiniportAttributes(h_adapter,\r
- (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&RegistrationAttributes);\r
- \r
- if (status != NDIS_STATUS_SUCCESS)\r
- {\r
- ipoib_destroy_adapter( p_adapter );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("NdisMSetMiniportAttributes returned 0x%.8x.\n", status) );\r
- return status;\r
- }\r
- \r
- /* set up generic attributes */\r
- \r
- GeneralAttributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES;\r
- GeneralAttributes.Header.Revision = NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1;\r
- GeneralAttributes.Header.Size = sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES);\r
- \r
- GeneralAttributes.MediaType = NdisMedium802_3;\r
- //TODO\r
- GeneralAttributes.MtuSize = MAX_IB_MTU;\r
- GeneralAttributes.MaxXmitLinkSpeed = IPOIB_MEDIA_MAX_SPEED;\r
- GeneralAttributes.MaxRcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED;\r
- GeneralAttributes.XmitLinkSpeed = NDIS_LINK_SPEED_UNKNOWN;\r
- GeneralAttributes.RcvLinkSpeed = NDIS_LINK_SPEED_UNKNOWN;\r
- GeneralAttributes.MediaConnectState = MediaConnectStateUnknown;\r
- GeneralAttributes.MediaDuplexState = MediaDuplexStateUnknown;\r
- GeneralAttributes.LookaheadSize = MAX_XFER_BLOCK_SIZE;\r
- \r
- GeneralAttributes.PowerManagementCapabilities = NULL;\r
- \r
- GeneralAttributes.MacOptions = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |\r
- NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |\r
- NDIS_MAC_OPTION_NO_LOOPBACK |\r
- NDIS_MAC_OPTION_FULL_DUPLEX;\r
- \r
- GeneralAttributes.SupportedPacketFilters = NDIS_PACKET_TYPE_DIRECTED |\r
- NDIS_PACKET_TYPE_MULTICAST |\r
- NDIS_PACKET_TYPE_ALL_MULTICAST |\r
- NDIS_PACKET_TYPE_BROADCAST;\r
- \r
- GeneralAttributes.MaxMulticastListSize = MAX_MCAST;\r
- GeneralAttributes.MacAddressLength = HW_ADDR_LEN;\r
- \r
- NdisMoveMemory(GeneralAttributes.PermanentMacAddress,\r
- p_adapter->mac.addr,\r
- HW_ADDR_LEN);\r
- \r
- NdisMoveMemory(GeneralAttributes.CurrentMacAddress,\r
- p_adapter->params.conf_mac.addr,\r
- HW_ADDR_LEN);\r
- \r
- \r
- GeneralAttributes.PhysicalMediumType = NdisPhysicalMediumUnspecified;\r
- GeneralAttributes.RecvScaleCapabilities = NULL;\r
- GeneralAttributes.AccessType = NET_IF_ACCESS_BROADCAST; // NET_IF_ACCESS_BROADCAST for a typical ethernet adapter\r
- GeneralAttributes.DirectionType = NET_IF_DIRECTION_SENDRECEIVE; // NET_IF_DIRECTION_SENDRECEIVE for a typical ethernet adapter\r
- GeneralAttributes.ConnectionType = NET_IF_CONNECTION_DEDICATED; // NET_IF_CONNECTION_DEDICATED for a typical ethernet adapter\r
- GeneralAttributes.IfType = IF_TYPE_ETHERNET_CSMACD; // IF_TYPE_ETHERNET_CSMACD for a typical ethernet adapter (regardless of speed)\r
- GeneralAttributes.IfConnectorPresent = TRUE; // RFC 2665 TRUE if physical adapter\r
- \r
- GeneralAttributes.SupportedStatistics = NDIS_STATISTICS_XMIT_OK_SUPPORTED |\r
- NDIS_STATISTICS_RCV_OK_SUPPORTED |\r
- NDIS_STATISTICS_XMIT_ERROR_SUPPORTED |\r
- NDIS_STATISTICS_RCV_ERROR_SUPPORTED |\r
- NDIS_STATISTICS_RCV_CRC_ERROR_SUPPORTED |\r
- NDIS_STATISTICS_RCV_NO_BUFFER_SUPPORTED |\r
- NDIS_STATISTICS_TRANSMIT_QUEUE_LENGTH_SUPPORTED |\r
- NDIS_STATISTICS_GEN_STATISTICS_SUPPORTED;\r
- \r
- GeneralAttributes.SupportedOidList = (PNDIS_OID)SUPPORTED_OIDS;\r
- GeneralAttributes.SupportedOidListLength = sizeof(SUPPORTED_OIDS);\r
- \r
- status = NdisMSetMiniportAttributes(h_adapter,\r
- (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&GeneralAttributes);\r
- \r
- if (status != NDIS_STATUS_SUCCESS)\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("NdisMSetMiniportAttributes returned 0x%.8x.\n", status) );\r
- }\r
- \r
-#if IPOIB_USE_DMA\r
- \r
- NdisZeroMemory(&DmaDescription, sizeof(DmaDescription));\r
- \r
- DmaDescription.Header.Type = NDIS_OBJECT_TYPE_SG_DMA_DESCRIPTION;\r
- DmaDescription.Header.Revision = NDIS_SG_DMA_DESCRIPTION_REVISION_1;\r
- DmaDescription.Header.Size = sizeof(NDIS_SG_DMA_DESCRIPTION);//NDIS_SIZEOF_SG_DMA_DESCRIPTION_REVISION_1;\r
- \r
- DmaDescription.Flags = NDIS_SG_DMA_64_BIT_ADDRESS;\r
- DmaDescription.MaximumPhysicalMapping = p_adapter->params.xfer_block_size;\r
- \r
- DmaDescription.ProcessSGListHandler = ipoib_process_sg_list;\r
- DmaDescription.SharedMemAllocateCompleteHandler = NULL;\r
- \r
- status = NdisMRegisterScatterGatherDma(\r
- p_adapter->h_adapter,\r
- &DmaDescription,\r
- &p_adapter->NdisMiniportDmaHandle);\r
- \r
- if( status != NDIS_STATUS_SUCCESS )\r
- {\r
- ipoib_destroy_adapter( p_adapter );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("NdisMRegisterScatterGatherDma returned 0x%.8x.\n", status) );\r
- return status;\r
- }\r
-\r
- \r
- \r
-#endif\r
-#endif //if 0\r
-\r
-\r
-\r
-#if IPOIB_USE_DMA\r
-\r
- InitNdisScatterGatherDma(p_adapter, h_adapter);\r
-\r
-\r
-\r
-#endif\r
- /* Create the adapter adapter */\r
- ib_status = ipoib_start_adapter( p_adapter );\r
- if( ib_status != IB_SUCCESS )\r
- {\r
- ASSERT(FALSE);\r
- NdisWriteErrorLogEntry( h_adapter,\r
- NDIS_ERROR_CODE_HARDWARE_FAILURE, 0 );\r
-#if IPOIB_USE_DMA\r
- NdisMDeregisterScatterGatherDma(p_adapter->NdisMiniportDmaHandle);\r
-#endif\r
- ipoib_destroy_adapter( p_adapter );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ipoib_start_adapter returned status %d.\n", ib_status ) );\r
- return NDIS_STATUS_FAILURE;\r
- }\r
- \r
- ipoib_ref_ibat();\r
- \r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
- return status;\r
- }\r
-\r
-\r
-//! Deallocates resources when the NIC is removed and halts the NIC..\r
-//TODO: Dispatch or Passive ?\r
-/* IRQL = DISPATCH_LEVEL\r
-\r
-@param adapter_context The adapter context allocated at start\r
-*/\r
-void\r
-ipoib_halt_ex(\r
- IN NDIS_HANDLE adapter_context,\r
- IN NDIS_HALT_ACTION HaltAction )\r
-{\r
- ipoib_adapter_t *p_adapter;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-\r
- UNUSED_PARAM(HaltAction);\r
-//return; \r
- ipoib_deref_ibat();\r
-\r
- CL_ASSERT( adapter_context );\r
- p_adapter = (ipoib_adapter_t*)adapter_context;\r
-\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
- ("Port %016I64x (CA %016I64x port %d) halting\n",\r
- p_adapter->guids.port_guid.guid, p_adapter->guids.ca_guid,\r
- p_adapter->guids.port_num) );\r
-\r
-#if IPOIB_USE_DMA\r
- if (p_adapter->NdisMiniportDmaHandle != NULL)\r
- {\r
- NdisMDeregisterScatterGatherDma(p_adapter->NdisMiniportDmaHandle);\r
- p_adapter->NdisMiniportDmaHandle = NULL;\r
- }\r
-#endif\r
- ipoib_destroy_adapter( p_adapter );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
-}\r
-\r
-\r
-//! Reports the state of the NIC, or monitors the responsiveness of an underlying device driver.\r
-/* IRQL = DISPATCH_LEVEL\r
-\r
-@param adapter_context The adapter context allocated at start\r
-@return TRUE if the driver determines that its NIC is not operating\r
-*/\r
-BOOLEAN\r
-ipoib_check_for_hang(\r
- IN NDIS_HANDLE adapter_context )\r
-{\r
- ipoib_adapter_t *p_adapter;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-//return FALSE;\r
- CL_ASSERT( adapter_context );\r
- p_adapter = (ipoib_adapter_t*)adapter_context;\r
-\r
- if( p_adapter->reset )\r
- {\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
- return FALSE;\r
- }\r
- if (p_adapter->hung) {\r
- ipoib_resume_oids(p_adapter);\r
- }\r
-\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
- return (p_adapter->hung? TRUE:FALSE);\r
-}\r
-\r
-\r
-/*++\r
-Routine Description:\r
- The routine sets an NDIS_OFFLOAD structure indicates the current offload \r
- capabilities that are provided by the miniport adapter \r
-\r
-Arguments:\r
- pPort - a pointer to port object\r
- offload - reference to NDIS_OFFLOAD object that should be filled\r
-\r
-Return Value:\r
- None.\r
-\r
---*/\r
-//TODO\r
-#if 0\r
-static\r
-void\r
-__ipoib_get_offload_config(\r
- ipoib_port_t *pPort,\r
- NDIS_OFFLOAD *p_offload\r
- )\r
-{\r
- NDIS_STATUS Status;\r
- ULONG TxChksumOffload = ((MP_GET_PORT_CONFIG(pPort, TxChksumOffload) == TRUE) ? NDIS_OFFLOAD_SET_ON : NDIS_OFFLOAD_SET_OFF);\r
- ULONG RxChksumOffload = ((MP_GET_PORT_CONFIG(pPort, RxChksumOffload) == TRUE) ? NDIS_OFFLOAD_SET_ON : NDIS_OFFLOAD_SET_OFF);\r
- BOOLEAN fLargeSendOffload = MP_GET_PORT_CONFIG(pPort, LargeSendOffload);\r
- ULONG ulEncapsulation = NDIS_ENCAPSULATION_IEEE_802_3 | NDIS_ENCAPSULATION_IEEE_802_3_P_AND_Q;\r
- \r
- NdisZeroMemory(&*p_offload, sizeof(NDIS_OFFLOAD));\r
- *p_offload.Header.Type = NDIS_OBJECT_TYPE_OFFLOAD;\r
- *p_offload.Header.Revision = NDIS_OFFLOAD_REVISION_1; // BUGBUG: do we need to support revision 2? UH 17-May-2008\r
- *p_offload.Header.Size = NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_1;\r
-\r
- *p_offload.Checksum.IPv4Transmit.Encapsulation = ulEncapsulation;\r
- *p_offload.Checksum.IPv4Transmit.IpOptionsSupported = TxChksumOffload;\r
- *p_offload.Checksum.IPv4Transmit.TcpOptionsSupported = TxChksumOffload;\r
- *p_offload.Checksum.IPv4Transmit.TcpChecksum = TxChksumOffload;\r
- *p_offload.Checksum.IPv4Transmit.UdpChecksum = NDIS_OFFLOAD_NOT_SUPPORTED;\r
- *p_offload.Checksum.IPv4Transmit.IpChecksum = TxChksumOffload;\r
-\r
- *p_offload.Checksum.IPv4Receive.Encapsulation = ulEncapsulation;\r
- *p_offload.Checksum.IPv4Receive.IpOptionsSupported = RxChksumOffload;\r
- *p_offload.Checksum.IPv4Receive.TcpOptionsSupported = RxChksumOffload;\r
- *p_offload.Checksum.IPv4Receive.TcpChecksum = RxChksumOffload;\r
- *p_offload.Checksum.IPv4Receive.UdpChecksum = NDIS_OFFLOAD_NOT_SUPPORTED; \r
- *p_offload.Checksum.IPv4Receive.IpChecksum = RxChksumOffload;\r
-\r
- *p_offload.Checksum.IPv6Transmit.Encapsulation = ulEncapsulation;\r
- *p_offload.Checksum.IPv6Transmit.IpExtensionHeadersSupported = TxChksumOffload;\r
- *p_offload.Checksum.IPv6Transmit.TcpOptionsSupported = TxChksumOffload;\r
- *p_offload.Checksum.IPv6Transmit.TcpChecksum = TxChksumOffload;\r
- *p_offload.Checksum.IPv6Transmit.UdpChecksum = NDIS_OFFLOAD_NOT_SUPPORTED;\r
-\r
-\r
- *p_offload.Checksum.IPv6Receive.Encapsulation = ulEncapsulation;\r
- *p_offload.Checksum.IPv6Receive.IpExtensionHeadersSupported = RxChksumOffload;\r
- *p_offload.Checksum.IPv6Receive.TcpOptionsSupported = RxChksumOffload;\r
- *p_offload.Checksum.IPv6Receive.TcpChecksum = RxChksumOffload;\r
- *p_offload.Checksum.IPv6Receive.UdpChecksum = NDIS_OFFLOAD_NOT_SUPPORTED;\r
-\r
- if (fLargeSendOffload)\r
- {\r
- *p_offload.LsoV1.IPv4.Encapsulation = ulEncapsulation;\r
- *p_offload.LsoV1.IPv4.MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE;\r
- *p_offload.LsoV1.IPv4.MinSegmentCount = 1;\r
- *p_offload.LsoV1.IPv4.TcpOptions = NDIS_OFFLOAD_SUPPORTED;\r
- *p_offload.LsoV1.IPv4.IpOptions = NDIS_OFFLOAD_SUPPORTED;\r
- }\r
-}\r
-#endif\r
-\r
-//! Returns information about the capabilities and status of the driver and/or its NIC.\r
-/* IRQL = DISPATCH_LEVEL\r
-\r
-@param adapter_context The adapter context allocated at start\r
-@param oid Object ID representing the query operation to be carried out\r
-@param info_buf Buffer containing any input for this query and location for output\r
-@param info_buf_len Number of bytes available in info_buf\r
-@param p_bytes_written Pointer to number of bytes written into info_buf\r
-@param p_bytes_needed Pointer to number of bytes needed to satisfy this oid\r
-@return NDIS_STATUS_SUCCESS, NDIS_STATUS_PENDING, NDIS_STATUS_INVALID_OID,\r
-NDIS_STATUS_INVALID_LENGTH, NDIS_STATUS_NOT_ACCEPTED, NDIS_STATUS_NOT_SUPPORTED,\r
-NDIS_STATUS_RESOURCES\r
-*/\r
- NDIS_STATUS\r
-ipoib_query_info(\r
- IN NDIS_HANDLE adapter_context,\r
- IN NDIS_OID oid,\r
- IN PVOID info_buf,\r
- IN ULONG info_buf_len,\r
- OUT PULONG p_bytes_written,\r
- OUT PULONG p_bytes_needed )\r
- {\r
- ipoib_adapter_t *p_adapter;\r
- NDIS_STATUS status;\r
- USHORT version;\r
- ULONG info;\r
- PVOID src_buf;\r
- ULONG buf_len;\r
- pending_oid_t oid_info;\r
- uint8_t port_num;\r
- \r
- IPOIB_ENTER( IPOIB_DBG_OID );\r
- \r
- oid_info.oid = oid;\r
- oid_info.p_buf = info_buf;\r
- oid_info.buf_len = info_buf_len;\r
- oid_info.p_bytes_used = p_bytes_written;\r
- oid_info.p_bytes_needed = p_bytes_needed;\r
- \r
- CL_ASSERT( adapter_context );\r
- p_adapter = (ipoib_adapter_t*)adapter_context;\r
-\r
- CL_ASSERT( p_bytes_written );\r
- CL_ASSERT( p_bytes_needed );\r
- CL_ASSERT( !p_adapter->pending_query );\r
- \r
- status = NDIS_STATUS_SUCCESS;\r
- src_buf = &info;\r
- buf_len = sizeof(info);\r
- \r
- port_num = p_adapter->guids.port_num;\r
- \r
- switch( oid )\r
- {\r
- /* Required General */\r
- case OID_GEN_SUPPORTED_LIST:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_GEN_SUPPORTED_LIST\n", port_num) );\r
- src_buf = (PVOID)SUPPORTED_OIDS;\r
- buf_len = sizeof(SUPPORTED_OIDS);\r
- break;\r
- \r
- case OID_GEN_HARDWARE_STATUS:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_GEN_HARDWARE_STATUS\n", port_num) );\r
- cl_obj_lock( &p_adapter->obj );\r
- switch( p_adapter->state )\r
- {\r
- case IB_PNP_PORT_ADD:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d returning NdisHardwareStatusInitializing\n", port_num) );\r
- info = NdisHardwareStatusInitializing;\r
- break;\r
- \r
- case IB_PNP_PORT_ACTIVE:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d returning NdisHardwareStatusReady\n", port_num) );\r
- info = NdisHardwareStatusReady;\r
- break;\r
- \r
- default:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d returning NdisHardwareStatusNotReady\n", port_num) );\r
- info = NdisHardwareStatusNotReady;\r
- }\r
- cl_obj_unlock( &p_adapter->obj );\r
- break;\r
- \r
- case OID_GEN_MEDIA_SUPPORTED:\r
- case OID_GEN_MEDIA_IN_USE:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_GEN_MEDIA_SUPPORTED "\r
- "or OID_GEN_MEDIA_IN_USE\n", port_num) );\r
- info = NdisMedium802_3;\r
- break;\r
- \r
- case OID_GEN_MAXIMUM_FRAME_SIZE:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_GEN_MAXIMUM_FRAME_SIZE\n", port_num) );\r
- if( p_adapter->params.cm_enabled )\r
- {\r
- info = p_adapter->params.cm_payload_mtu;\r
- }\r
- else\r
- {\r
- info = p_adapter->params.payload_mtu;\r
- }\r
- break;\r
- \r
- case OID_GEN_LINK_SPEED:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_GEN_LINK_SPEED\n", port_num) );\r
- if (info_buf_len < buf_len)\r
- {\r
- break;\r
- }\r
- \r
- cl_obj_lock( &p_adapter->obj );\r
- switch( p_adapter->state )\r
- {\r
- case IB_PNP_PORT_ADD:\r
- /* Mark the adapter as pending an OID */\r
- p_adapter->pending_query = TRUE;\r
- \r
- /* Save the request parameters. */\r
- p_adapter->query_oid = oid_info;\r
- \r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d returning NDIS_STATUS_PENDING\n", port_num) );\r
- status = NDIS_STATUS_PENDING;\r
- break;\r
- \r
- case IB_PNP_PORT_REMOVE:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d returning NDIS_STATUS_NOT_ACCEPTED\n", port_num) );\r
- status = NDIS_STATUS_NOT_ACCEPTED;\r
- break;\r
- \r
- default:\r
- CL_ASSERT( p_adapter->p_port );\r
- info = p_adapter->port_rate;\r
- break;\r
- }\r
- cl_obj_unlock( &p_adapter->obj );\r
- break;\r
- \r
- case OID_GEN_TRANSMIT_BUFFER_SPACE:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_GEN_TRANSMIT_BUFFER_SPACE\n", port_num) );\r
- if( p_adapter->params.cm_enabled )\r
- info = p_adapter->params.sq_depth * p_adapter->params.cm_xfer_block_size;\r
- else\r
- info = p_adapter->params.sq_depth * p_adapter->params.xfer_block_size;\r
- break;\r
- \r
- case OID_GEN_RECEIVE_BUFFER_SPACE:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_GEN_TRANSMIT_BUFFER_SPACE "\r
- "or OID_GEN_RECEIVE_BUFFER_SPACE\n", port_num) );\r
- if( p_adapter->params.cm_enabled )\r
- info = p_adapter->params.rq_depth * p_adapter->params.cm_xfer_block_size;\r
- else\r
- info = p_adapter->params.rq_depth * p_adapter->params.xfer_block_size;\r
- break;\r
- \r
- case OID_GEN_MAXIMUM_LOOKAHEAD:\r
- case OID_GEN_CURRENT_LOOKAHEAD:\r
- case OID_GEN_TRANSMIT_BLOCK_SIZE:\r
- case OID_GEN_RECEIVE_BLOCK_SIZE:\r
- case OID_GEN_MAXIMUM_TOTAL_SIZE:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_GEN_MAXIMUM_LOOKAHEAD "\r
- "or OID_GEN_CURRENT_LOOKAHEAD or "\r
- "OID_GEN_TRANSMIT_BLOCK_SIZE or "\r
- "OID_GEN_RECEIVE_BLOCK_SIZE or "\r
- "OID_GEN_MAXIMUM_TOTAL_SIZE\n", port_num) );\r
- if( p_adapter->params.cm_enabled )\r
- info = p_adapter->params.cm_xfer_block_size;\r
- else\r
- info = p_adapter->params.xfer_block_size;\r
- break;\r
- \r
- case OID_GEN_VENDOR_ID:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_GEN_VENDOR_ID\n", port_num) );\r
- src_buf = (void*)VENDOR_ID;\r
- buf_len = sizeof(VENDOR_ID);\r
- break;\r
- \r
- case OID_GEN_VENDOR_DESCRIPTION:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, \r
- ("Port %d received query for OID_GEN_VENDOR_DESCRIPTION\n", port_num) );\r
- src_buf = VENDOR_DESCRIPTION;\r
- buf_len = sizeof(VENDOR_DESCRIPTION);\r
- break;\r
- \r
- case OID_GEN_VENDOR_DRIVER_VERSION:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_GEN_VENDOR_DRIVER_VERSION\n", port_num) );\r
- src_buf = &version;\r
- buf_len = sizeof(version);\r
- //TODO: Figure out what the right version is.\r
- version = 1 << 8 | 1;\r
- break;\r
- \r
- case OID_GEN_PHYSICAL_MEDIUM:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_GEN_PHYSICAL_MEDIUM\n", port_num) );\r
- info = NdisPhysicalMediumUnspecified;\r
- break;\r
- \r
- case OID_GEN_CURRENT_PACKET_FILTER:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_GEN_CURRENT_PACKET_FILTER\n", port_num) );\r
- info = p_adapter->packet_filter;\r
- break;\r
- \r
- case OID_GEN_DRIVER_VERSION:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_GEN_DRIVER_VERSION\n", port_num) );\r
- src_buf = &version;\r
- buf_len = sizeof(version);\r
- version = MAJOR_NDIS_VERSION << 8 | MINOR_NDIS_VERSION;\r
- break;\r
- \r
- case OID_GEN_MAC_OPTIONS:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_GEN_MAC_OPTIONS\n", port_num) );\r
- info = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |\r
- NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |\r
- NDIS_MAC_OPTION_NO_LOOPBACK |\r
- NDIS_MAC_OPTION_FULL_DUPLEX;\r
- //TODO: Figure out if we will support priority and VLANs.\r
- // NDIS_MAC_OPTION_8021P_PRIORITY;\r
- //#ifdef NDIS51_MINIPORT\r
- // info |= NDIS_MAC_OPTION_8021Q_VLAN;\r
- //#endif\r
- break;\r
- \r
- case OID_GEN_MEDIA_CONNECT_STATUS:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_GEN_MEDIA_CONNECT_STATUS\n", port_num) );\r
- cl_obj_lock( &p_adapter->obj );\r
- switch( p_adapter->state )\r
- {\r
- case IB_PNP_PORT_ADD:\r
- case IB_PNP_PORT_INIT:\r
- /*\r
- * Delay reporting media state until we know whether the port is\r
- * either up or down.\r
- */\r
- p_adapter->pending_query = TRUE;\r
- p_adapter->query_oid = oid_info;\r
- \r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d returning NDIS_STATUS_PENDING\n", port_num) );\r
- status = NDIS_STATUS_PENDING;\r
- break;\r
- \r
- case IB_PNP_PORT_ACTIVE:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d returning NdisMediaStateConnected\n", port_num) );\r
- info = NdisMediaStateConnected;\r
- break;\r
- \r
- case IB_PNP_PORT_REMOVE:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d returning NDIS_STATUS_NOT_ACCEPTED\n", port_num) );\r
- status = NDIS_STATUS_NOT_ACCEPTED;\r
- break;\r
- \r
- default:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d returning NdisMediaStateDisconnected\n", port_num) );\r
- info = NdisMediaStateDisconnected;\r
- }\r
- cl_obj_unlock( &p_adapter->obj );\r
- break;\r
- \r
- case OID_GEN_MAXIMUM_SEND_PACKETS:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_GEN_MAXIMUM_SEND_PACKETS\n", port_num) );\r
- info = MINIPORT_MAX_SEND_PACKETS;\r
- break;\r
- \r
- /* Required General Statistics */\r
- case OID_GEN_STATISTICS:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_GEN_STATISTICS\n", port_num) );\r
- src_buf = NULL; \r
- buf_len = sizeof(NDIS_STATISTICS_INFO);\r
- if (info_buf_len < buf_len)\r
- {\r
- break;\r
- } \r
- status = ipoib_get_gen_stat(p_adapter, &oid_info );\r
- break;\r
- \r
- case OID_GEN_XMIT_OK:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_GEN_XMIT_OK\n", port_num) );\r
- src_buf = NULL;\r
- status = ipoib_get_send_stat( p_adapter, IP_STAT_SUCCESS, &oid_info );\r
- break;\r
- \r
- case OID_GEN_RCV_OK:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_GEN_RCV_OK\n", port_num) );\r
- src_buf = NULL;\r
- status = ipoib_get_recv_stat( p_adapter, IP_STAT_SUCCESS, &oid_info );\r
- break;\r
- \r
- case OID_GEN_XMIT_ERROR:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_GEN_XMIT_ERROR\n", port_num) );\r
- src_buf = NULL;\r
- status = ipoib_get_send_stat( p_adapter, IP_STAT_ERROR, &oid_info );\r
- break;\r
- \r
- case OID_GEN_RCV_ERROR:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_GEN_RCV_ERROR\n", port_num) );\r
- src_buf = NULL;\r
- status = ipoib_get_recv_stat( p_adapter, IP_STAT_ERROR, &oid_info );\r
- break;\r
- \r
- case OID_GEN_RCV_NO_BUFFER:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_GEN_RCV_NO_BUFFER\n", port_num) );\r
- src_buf = NULL;\r
- status = ipoib_get_recv_stat( p_adapter, IP_STAT_DROPPED, &oid_info );\r
- break;\r
- \r
- case OID_GEN_DIRECTED_BYTES_XMIT:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_GEN_DIRECTED_BYTES_XMIT\n", port_num) );\r
- src_buf = NULL;\r
- status = ipoib_get_send_stat( p_adapter, IP_STAT_UCAST_BYTES, &oid_info );\r
- break;\r
- \r
- case OID_GEN_DIRECTED_FRAMES_XMIT:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_GEN_DIRECTED_FRAMES_XMIT\n", port_num) );\r
- src_buf = NULL;\r
- status = ipoib_get_send_stat( p_adapter, IP_STAT_UCAST_FRAMES, &oid_info );\r
- break;\r
- \r
- case OID_GEN_MULTICAST_BYTES_XMIT:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_GEN_MULTICAST_BYTES_XMIT\n", port_num) );\r
- src_buf = NULL;\r
- status = ipoib_get_send_stat( p_adapter, IP_STAT_MCAST_BYTES, &oid_info );\r
- break;\r
- \r
- case OID_GEN_MULTICAST_FRAMES_XMIT:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_GEN_MULTICAST_FRAMES_XMIT\n", port_num) );\r
- src_buf = NULL;\r
- status = ipoib_get_send_stat( p_adapter, IP_STAT_MCAST_FRAMES, &oid_info );\r
- break;\r
- \r
- case OID_GEN_BROADCAST_BYTES_XMIT:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_GEN_BROADCAST_BYTES_XMIT\n", port_num) );\r
- src_buf = NULL;\r
- status = ipoib_get_send_stat( p_adapter, IP_STAT_BCAST_BYTES, &oid_info );\r
- break;\r
- \r
- case OID_GEN_BROADCAST_FRAMES_XMIT:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_GEN_BROADCAST_FRAMES_XMIT\n", port_num) );\r
- src_buf = NULL;\r
- status = ipoib_get_send_stat( p_adapter, IP_STAT_BCAST_FRAMES, &oid_info );\r
- break;\r
- \r
- case OID_GEN_DIRECTED_BYTES_RCV:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_GEN_DIRECTED_BYTES_RCV\n", port_num) );\r
- src_buf = NULL;\r
- status = ipoib_get_recv_stat( p_adapter, IP_STAT_UCAST_BYTES, &oid_info );\r
- break;\r
- \r
- case OID_GEN_DIRECTED_FRAMES_RCV:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_GEN_DIRECTED_FRAMES_RCV\n", port_num) );\r
- src_buf = NULL;\r
- status = ipoib_get_recv_stat( p_adapter, IP_STAT_UCAST_FRAMES, &oid_info );\r
- break;\r
- \r
- case OID_GEN_MULTICAST_BYTES_RCV:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_GEN_MULTICAST_BYTES_RCV\n", port_num) );\r
- src_buf = NULL;\r
- status = ipoib_get_recv_stat( p_adapter, IP_STAT_MCAST_BYTES, &oid_info );\r
- break;\r
- \r
- case OID_GEN_MULTICAST_FRAMES_RCV:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_GEN_MULTICAST_FRAMES_RCV\n", port_num) );\r
- src_buf = NULL;\r
- status = ipoib_get_recv_stat( p_adapter, IP_STAT_MCAST_FRAMES, &oid_info );\r
- break;\r
- \r
- case OID_GEN_BROADCAST_BYTES_RCV:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_GEN_BROADCAST_BYTES_RCV\n", port_num) );\r
- src_buf = NULL;\r
- status = ipoib_get_recv_stat( p_adapter, IP_STAT_BCAST_BYTES, &oid_info );\r
- break;\r
- \r
- case OID_GEN_BROADCAST_FRAMES_RCV:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_GEN_BROADCAST_FRAMES_RCV\n", port_num) );\r
- src_buf = NULL;\r
- status = ipoib_get_recv_stat( p_adapter, IP_STAT_BCAST_FRAMES, &oid_info );\r
- break;\r
- \r
- /* Required Ethernet operational characteristics */\r
- case OID_802_3_PERMANENT_ADDRESS:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_802_3_PERMANENT_ADDRESS\n", port_num) );\r
- src_buf = &p_adapter->mac;\r
- buf_len = sizeof(p_adapter->mac);\r
- break;\r
- \r
- case OID_802_3_CURRENT_ADDRESS:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_802_3_CURRENT_ADDRESS\n", port_num) );\r
- src_buf = &p_adapter->params.conf_mac;\r
- buf_len = sizeof(p_adapter->params.conf_mac);\r
- break;\r
- \r
- case OID_802_3_MULTICAST_LIST:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_802_3_MULTICAST_LIST\n", port_num) );\r
- src_buf = p_adapter->mcast_array;\r
- buf_len = p_adapter->mcast_array_size * sizeof(mac_addr_t);\r
- break;\r
- \r
- case OID_802_3_MAXIMUM_LIST_SIZE:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_802_3_MAXIMUM_LIST_SIZE\n", port_num) );\r
- info = MAX_MCAST;\r
- break;\r
- \r
- case OID_802_3_MAC_OPTIONS:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_802_3_MAC_OPTIONS\n", port_num) );\r
- info = 0;\r
- break;\r
- \r
- /* Required Ethernet stats */\r
- case OID_802_3_RCV_ERROR_ALIGNMENT:\r
- case OID_802_3_XMIT_ONE_COLLISION:\r
- case OID_802_3_XMIT_MORE_COLLISIONS:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_802_3_RCV_ERROR_ALIGNMENT or "\r
- "OID_802_3_XMIT_ONE_COLLISION or "\r
- "OID_802_3_XMIT_MORE_COLLISIONS\n", port_num) );\r
- info = 0;\r
- break;\r
- \r
- case OID_TCP_TASK_OFFLOAD:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_TCP_TASK_OFFLOAD\n", port_num) );\r
- src_buf = NULL;\r
- status = __ipoib_get_tcp_task_offload( p_adapter, &oid_info );\r
- break;\r
- \r
- /* Optional General */\r
- case OID_GEN_SUPPORTED_GUIDS:\r
-#ifdef NDIS51_MINIPORT\r
- case OID_GEN_VLAN_ID:\r
-#endif\r
- \r
- /* Optional General Stats */\r
- case OID_GEN_RCV_CRC_ERROR:\r
- case OID_GEN_TRANSMIT_QUEUE_LENGTH:\r
- \r
- /* Optional Ethernet Stats */\r
- case OID_802_3_XMIT_DEFERRED:\r
- case OID_802_3_XMIT_MAX_COLLISIONS:\r
- case OID_802_3_RCV_OVERRUN:\r
- case OID_802_3_XMIT_UNDERRUN:\r
- case OID_802_3_XMIT_HEARTBEAT_FAILURE:\r
- case OID_802_3_XMIT_TIMES_CRS_LOST:\r
- case OID_802_3_XMIT_LATE_COLLISIONS:\r
- case OID_PNP_CAPABILITIES:\r
- status = NDIS_STATUS_NOT_SUPPORTED;\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received an unsupported oid of 0x%.8X!\n", port_num, oid) );\r
- break;\r
- \r
- case OID_GEN_PROTOCOL_OPTIONS:\r
- case OID_GEN_NETWORK_LAYER_ADDRESSES:\r
- case OID_GEN_TRANSPORT_HEADER_OFFSET:\r
- case OID_PNP_ENABLE_WAKE_UP:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("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) );\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Number of OID: 0x%.8X!\n", oid) );\r
- status = NDIS_STATUS_SUCCESS; \r
- break;\r
- \r
- case OID_PNP_QUERY_POWER:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_TCP_TASK_OFFLOAD\n", port_num) );\r
- // Status is pre-set in this routine to Success\r
- status = NDIS_STATUS_SUCCESS; \r
- break;\r
- \r
- case OID_TCP_OFFLOAD_CURRENT_CONFIG:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_PNP_QUERY_POWER\n", port_num) );\r
- //ulBytesAvailable = ulInfoLen = sizeof(NDIS_OFFLOAD);\r
- if (info_buf_len < sizeof(NDIS_OFFLOAD))\r
- {\r
- status = NDIS_STATUS_BUFFER_TOO_SHORT;\r
- *p_bytes_needed = sizeof(NDIS_OFFLOAD) ;\r
- break;\r
- }\r
- \r
- //ipoib_offload_config(pPort, &offload);\r
- //pInfo = &offload;\r
- break;\r
- \r
- default:\r
- status = NDIS_STATUS_INVALID_OID;\r
- // IPOIB_PRINT( TRACE_LEVEL_ERROR,IPOIB_DBG_OID,\r
- // ("Port %d received an invalid oid of 0x%.8X!\n", port_num, oid) );\r
- break;\r
- }\r
- \r
- /*\r
- * Complete the request as if it was handled asynchronously to maximize\r
- * code reuse for when we really handle the requests asynchronously.\r
- * Note that this requires the QueryInformation entry point to always\r
- * return NDIS_STATUS_PENDING\r
- */\r
- if( status != NDIS_STATUS_PENDING )\r
- {\r
- ipoib_complete_query(\r
- p_adapter, &oid_info, status, src_buf, buf_len );\r
- return status;\r
- }\r
- \r
- IPOIB_EXIT( IPOIB_DBG_OID );\r
- return NDIS_STATUS_PENDING;\r
- }\r
- \r
-\r
-static void\r
-ipoib_complete_query(\r
- IN ipoib_adapter_t* const p_adapter,\r
- IN pending_oid_t* const p_oid_info,\r
- IN const NDIS_STATUS status,\r
- IN const void* const p_buf,\r
- IN const ULONG buf_len )\r
-{\r
- NDIS_STATUS oid_status = status;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_OID );\r
-\r
- CL_ASSERT( status != NDIS_STATUS_PENDING );\r
-\r
- if( status == NDIS_STATUS_SUCCESS )\r
- {\r
- if( p_oid_info->buf_len < buf_len )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Insufficient buffer space. "\r
- "Returning NDIS_STATUS_INVALID_LENGTH.\n") );\r
- oid_status = NDIS_STATUS_INVALID_LENGTH;\r
- *p_oid_info->p_bytes_needed = buf_len;\r
- *p_oid_info->p_bytes_used = 0;\r
- }\r
- else if( p_oid_info->p_buf )\r
- {\r
- /* Only copy if we have a distinct source buffer. */\r
- if( p_buf )\r
- {\r
- NdisMoveMemory( p_oid_info->p_buf, p_buf, buf_len );\r
- *p_oid_info->p_bytes_used = buf_len;\r
- }\r
- }\r
- else\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Returning NDIS_NOT_ACCEPTED") );\r
- oid_status = NDIS_STATUS_NOT_ACCEPTED;\r
- }\r
- }\r
- else\r
- {\r
- *p_oid_info->p_bytes_used = 0;\r
- }\r
-\r
- if (p_adapter->query_oid.p_pending_oid)\r
- {\r
- NdisMOidRequestComplete(p_adapter->h_adapter,p_adapter->query_oid.p_pending_oid,oid_status); \r
- p_adapter->query_oid.p_pending_oid = NULL;\r
- }\r
- p_adapter->pending_query = FALSE;\r
-\r
- IPOIB_EXIT( IPOIB_DBG_OID );\r
-}\r
-\r
-\r
-static NDIS_STATUS\r
-__ipoib_get_tcp_task_offload(\r
- IN ipoib_adapter_t* p_adapter,\r
- OUT pending_oid_t *pNdisRequest )\r
-{\r
-#ifndef NDIS60_MINIPORT\r
- NDIS_TASK_OFFLOAD_HEADER *p_offload_hdr;\r
- NDIS_TASK_OFFLOAD *p_offload_task;\r
- NDIS_TASK_TCP_IP_CHECKSUM *p_offload_chksum;\r
-\r
- NDIS_TASK_TCP_LARGE_SEND *p_offload_lso;\r
- ULONG buf_len;\r
-\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received query for OID_TCP_TASK_OFFLOAD\n",\r
- p_adapter->guids.port_num) );\r
-\r
- buf_len = sizeof(NDIS_TASK_OFFLOAD_HEADER) +\r
- offsetof( NDIS_TASK_OFFLOAD, TaskBuffer ) +\r
- sizeof(NDIS_TASK_TCP_IP_CHECKSUM) +\r
- (p_adapter->params.lso ? \r
- sizeof(NDIS_TASK_OFFLOAD) + sizeof(NDIS_TASK_TCP_LARGE_SEND)\r
- : 0);\r
-\r
- pNdisRequest->DATA.QUERY_INFORMATION.BytesNeeded = buf_len;\r
-\r
- if( pNdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength < buf_len )\r
- return NDIS_STATUS_INVALID_LENGTH;\r
-\r
- p_offload_hdr = (NDIS_TASK_OFFLOAD_HEADER*)pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;\r
- if( p_offload_hdr->Version != NDIS_TASK_OFFLOAD_VERSION )\r
- return NDIS_STATUS_INVALID_DATA;\r
-\r
- if( p_offload_hdr->EncapsulationFormat.Encapsulation !=\r
- IEEE_802_3_Encapsulation )\r
- {\r
- return NDIS_STATUS_INVALID_DATA;\r
- }\r
-\r
- p_offload_hdr->OffsetFirstTask = sizeof(NDIS_TASK_OFFLOAD_HEADER);\r
- p_offload_task = (NDIS_TASK_OFFLOAD*)(p_offload_hdr + 1);\r
- p_offload_task->Version = NDIS_TASK_OFFLOAD_VERSION;\r
- p_offload_task->Size = sizeof(NDIS_TASK_OFFLOAD);\r
- p_offload_task->Task = TcpIpChecksumNdisTask;\r
- p_offload_task->OffsetNextTask = 0;\r
- p_offload_task->TaskBufferLength = sizeof(NDIS_TASK_TCP_IP_CHECKSUM);\r
- p_offload_chksum =\r
- (NDIS_TASK_TCP_IP_CHECKSUM*)p_offload_task->TaskBuffer;\r
- \r
- p_offload_chksum->V4Transmit.IpOptionsSupported =\r
- p_offload_chksum->V4Transmit.TcpOptionsSupported =\r
- p_offload_chksum->V4Transmit.TcpChecksum =\r
- p_offload_chksum->V4Transmit.UdpChecksum =\r
- p_offload_chksum->V4Transmit.IpChecksum =\r
- !!(p_adapter->params.send_chksum_offload);\r
-\r
- p_offload_chksum->V4Receive.IpOptionsSupported =\r
- p_offload_chksum->V4Receive.TcpOptionsSupported =\r
- p_offload_chksum->V4Receive.TcpChecksum =\r
- p_offload_chksum->V4Receive.UdpChecksum =\r
- p_offload_chksum->V4Receive.IpChecksum =\r
- !!(p_adapter->params.recv_chksum_offload);\r
-\r
- p_offload_chksum->V6Transmit.IpOptionsSupported = FALSE;\r
- p_offload_chksum->V6Transmit.TcpOptionsSupported = FALSE;\r
- p_offload_chksum->V6Transmit.TcpChecksum = FALSE;\r
- p_offload_chksum->V6Transmit.UdpChecksum = FALSE;\r
-\r
- p_offload_chksum->V6Receive.IpOptionsSupported = FALSE;\r
- p_offload_chksum->V6Receive.TcpOptionsSupported = FALSE;\r
- p_offload_chksum->V6Receive.TcpChecksum = FALSE;\r
- p_offload_chksum->V6Receive.UdpChecksum = FALSE;\r
-\r
-\r
- if (p_adapter->params.lso) {\r
- // set the previous pointer to the correct place\r
- p_offload_task->OffsetNextTask = FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer) +\r
- p_offload_task->TaskBufferLength;\r
- // set the LSO packet\r
- p_offload_task = (PNDIS_TASK_OFFLOAD)\r
- ((PUCHAR)p_offload_task + p_offload_task->OffsetNextTask);\r
-\r
- p_offload_task->Version = NDIS_TASK_OFFLOAD_VERSION;\r
- p_offload_task->Size = sizeof(NDIS_TASK_OFFLOAD);\r
- p_offload_task->Task = TcpLargeSendNdisTask;\r
- p_offload_task->OffsetNextTask = 0;\r
- p_offload_task->TaskBufferLength = sizeof(NDIS_TASK_TCP_LARGE_SEND);\r
-\r
- p_offload_lso = (PNDIS_TASK_TCP_LARGE_SEND) p_offload_task->TaskBuffer;\r
-\r
- p_offload_lso->Version = 0;\r
- //TODO optimal size: 60000, 64000 or 65536\r
- //TODO LSO_MIN_SEG_COUNT to be 1\r
- p_offload_lso->MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE; \r
-#define LSO_MIN_SEG_COUNT 2\r
- p_offload_lso->MinSegmentCount = LSO_MIN_SEG_COUNT;\r
- p_offload_lso->TcpOptions = TRUE;\r
- p_offload_lso->IpOptions = TRUE;\r
- }\r
-\r
- pNdisRequest->DATA.QUERY_INFORMATION.BytesWritten = buf_len\r
-\r
- return NDIS_STATUS_SUCCESS;\r
-#endif\r
- UNUSED_PARAM(p_adapter);\r
- UNUSED_PARAM(pNdisRequest);\r
- return NDIS_STATUS_NOT_SUPPORTED;\r
-\r
-}\r
-\r
-\r
-static NDIS_STATUS\r
-__ipoib_set_tcp_task_offload(\r
- IN ipoib_adapter_t* p_adapter,\r
- IN void* const p_info_buf,\r
- IN ULONG* const p_info_len )\r
-{\r
-#ifndef NDIS60_MINIPORT\r
- NDIS_TASK_OFFLOAD_HEADER *p_offload_hdr;\r
- NDIS_TASK_OFFLOAD *p_offload_task;\r
- NDIS_TASK_TCP_IP_CHECKSUM *p_offload_chksum;\r
-\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received set for OID_TCP_TASK_OFFLOAD\n",\r
- p_adapter->guids.port_num) );\r
-\r
- p_offload_hdr = (NDIS_TASK_OFFLOAD_HEADER*)p_info_buf;\r
-\r
- if( *p_info_len < sizeof(NDIS_TASK_OFFLOAD_HEADER) )\r
- return NDIS_STATUS_INVALID_LENGTH;\r
-\r
- if( p_offload_hdr->Version != NDIS_TASK_OFFLOAD_VERSION )\r
- return NDIS_STATUS_INVALID_DATA;\r
-\r
- if( p_offload_hdr->Size != sizeof(NDIS_TASK_OFFLOAD_HEADER) )\r
- return NDIS_STATUS_INVALID_LENGTH;\r
-\r
- if( !p_offload_hdr->OffsetFirstTask )\r
- return NDIS_STATUS_SUCCESS;\r
-\r
- if( p_offload_hdr->EncapsulationFormat.Encapsulation !=\r
- IEEE_802_3_Encapsulation )\r
- {\r
- return NDIS_STATUS_INVALID_DATA;\r
- }\r
-\r
- p_offload_task = (NDIS_TASK_OFFLOAD*)\r
- (((UCHAR*)p_offload_hdr) + p_offload_hdr->OffsetFirstTask);\r
-\r
- if( *p_info_len < sizeof(NDIS_TASK_OFFLOAD_HEADER) +\r
- offsetof( NDIS_TASK_OFFLOAD, TaskBuffer ) +\r
- sizeof(NDIS_TASK_TCP_IP_CHECKSUM) )\r
- {\r
- return NDIS_STATUS_INVALID_LENGTH;\r
- }\r
-\r
- if( p_offload_task->Version != NDIS_TASK_OFFLOAD_VERSION )\r
- return NDIS_STATUS_INVALID_DATA;\r
- p_offload_chksum =\r
- (NDIS_TASK_TCP_IP_CHECKSUM*)p_offload_task->TaskBuffer;\r
-\r
- if( !p_adapter->params.send_chksum_offload &&\r
- (p_offload_chksum->V4Transmit.IpOptionsSupported ||\r
- p_offload_chksum->V4Transmit.TcpOptionsSupported ||\r
- p_offload_chksum->V4Transmit.TcpChecksum ||\r
- p_offload_chksum->V4Transmit.UdpChecksum ||\r
- p_offload_chksum->V4Transmit.IpChecksum) )\r
- {\r
- return NDIS_STATUS_NOT_SUPPORTED;\r
- }\r
-\r
- if( !p_adapter->params.recv_chksum_offload &&\r
- (p_offload_chksum->V4Receive.IpOptionsSupported ||\r
- p_offload_chksum->V4Receive.TcpOptionsSupported ||\r
- p_offload_chksum->V4Receive.TcpChecksum ||\r
- p_offload_chksum->V4Receive.UdpChecksum ||\r
- p_offload_chksum->V4Receive.IpChecksum) )\r
- {\r
- return NDIS_STATUS_NOT_SUPPORTED;\r
- }\r
-\r
- return NDIS_STATUS_SUCCESS;\r
-#endif \r
- UNUSED_PARAM(p_adapter);\r
- UNUSED_PARAM(p_info_buf);\r
- UNUSED_PARAM(p_info_len);\r
- return NDIS_STATUS_NOT_SUPPORTED;\r
-}\r
-\r
-\r
-//! Issues a hardware reset to the NIC and/or resets the driver's software state.\r
-/* Tear down the connection and start over again. This is only called when there is a problem.\r
-For example, if a send, query info, or set info had a time out. MiniportCheckForHang will\r
-be called first.\r
-IRQL = DISPATCH_LEVEL\r
-\r
-@param p_addr_resetPointer to BOOLLEAN that is set to TRUE if the NDIS\r
-library should call MiniportSetInformation to restore addressing information to the current values.\r
-@param adapter_context The adapter context allocated at start\r
-@return NDIS_STATUS_SUCCESS, NDIS_STATUS_PENDING, NDIS_STATUS_NOT_RESETTABLE,\r
-NDIS_STATUS_RESET_IN_PROGRESS, NDIS_STATUS_SOFT_ERRORS, NDIS_STATUS_HARD_ERRORS\r
-*/\r
-NDIS_STATUS\r
-ipoib_reset(\r
- IN NDIS_HANDLE adapter_context,\r
- OUT PBOOLEAN p_addr_reset)\r
-{\r
- ipoib_adapter_t* p_adapter;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-//return NDIS_STATUS_SUCCESS;\r
- CL_ASSERT( p_addr_reset );\r
- CL_ASSERT( adapter_context );\r
- p_adapter = (ipoib_adapter_t*)adapter_context;\r
-\r
- switch( ipoib_reset_adapter( p_adapter ) )\r
- {\r
- case IB_NOT_DONE:\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
- return NDIS_STATUS_PENDING;\r
-\r
- case IB_SUCCESS:\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
- *p_addr_reset = TRUE;\r
- return NDIS_STATUS_SUCCESS;\r
-\r
- case IB_INVALID_STATE:\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
- return NDIS_STATUS_RESET_IN_PROGRESS;\r
-\r
- default:\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
- return NDIS_STATUS_HARD_ERRORS;\r
- }\r
-}\r
-\r
-\r
-//! Request changes in the state information that the miniport driver maintains\r
-/* For example, this is used to set multicast addresses and the packet filter.\r
-IRQL = DISPATCH_LEVEL\r
-\r
-@param adapter_context The adapter context allocated at start\r
-@param oid Object ID representing the set operation to be carried out\r
-@param info_buf Buffer containing input for this set and location for any output\r
-@param info_buf_len Number of bytes available in info_buf\r
-@param p_bytes_read Pointer to number of bytes read from info_buf\r
-@param p_bytes_needed Pointer to number of bytes needed to satisfy this oid\r
-@return NDIS_STATUS_SUCCESS, NDIS_STATUS_PENDING, NDIS_STATUS_INVALID_OID,\r
-NDIS_STATUS_INVALID_LENGTH, NDIS_STATUS_INVALID_DATA, NDIS_STATUS_NOT_ACCEPTED,\r
-NDIS_STATUS_NOT_SUPPORTED, NDIS_STATUS_RESOURCES\r
-*/\r
-NDIS_STATUS\r
-ipoib_set_info(\r
- IN NDIS_HANDLE adapter_context,\r
- IN NDIS_OID oid,\r
- IN PVOID info_buf,\r
- IN ULONG info_buf_len,\r
- OUT PULONG p_bytes_read,\r
- OUT PULONG p_bytes_needed )\r
-{\r
- ipoib_adapter_t* p_adapter;\r
- NDIS_STATUS status;\r
-\r
- ULONG buf_len;\r
- uint8_t port_num;\r
-\r
- KLOCK_QUEUE_HANDLE hdl;\r
- \r
- IPOIB_ENTER( IPOIB_DBG_OID );\r
-\r
- CL_ASSERT( adapter_context );\r
- p_adapter = (ipoib_adapter_t*)adapter_context;\r
-\r
- CL_ASSERT( p_bytes_read );\r
- CL_ASSERT( p_bytes_needed );\r
- CL_ASSERT( !p_adapter->pending_set );\r
-\r
- status = NDIS_STATUS_SUCCESS;\r
- *p_bytes_needed = 0;\r
- buf_len = sizeof(ULONG);\r
-\r
- port_num = p_adapter->guids.port_num;\r
- \r
- cl_obj_lock( &p_adapter->obj );\r
-\r
- if( p_adapter->state == IB_PNP_PORT_REMOVE )\r
- {\r
- *p_bytes_read = 0;\r
- cl_obj_unlock( &p_adapter->obj );\r
- return NDIS_STATUS_NOT_ACCEPTED;\r
- }\r
-\r
- cl_obj_unlock( &p_adapter->obj );\r
-\r
- switch( oid )\r
- {\r
- /* Required General */\r
- case OID_GEN_CURRENT_PACKET_FILTER:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received set for OID_GEN_CURRENT_PACKET_FILTER\n", port_num));\r
- if( info_buf_len < sizeof(p_adapter->packet_filter) )\r
- {\r
- status = NDIS_STATUS_INVALID_LENGTH;\r
- }\r
- else if( !info_buf )\r
- {\r
- status = NDIS_STATUS_INVALID_DATA;\r
- }\r
- else\r
- {\r
- KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
- cl_obj_lock( &p_adapter->obj );\r
- switch( p_adapter->state )\r
- {\r
- case IB_PNP_PORT_ADD:\r
- p_adapter->set_oid.oid = oid;\r
- p_adapter->set_oid.p_buf = info_buf;\r
- p_adapter->set_oid.buf_len = info_buf_len;\r
- p_adapter->set_oid.p_bytes_used = p_bytes_read;\r
- p_adapter->set_oid.p_bytes_needed = p_bytes_needed;\r
- p_adapter->pending_set = TRUE;\r
- status = NDIS_STATUS_PENDING;\r
- break;\r
-\r
- case IB_PNP_PORT_REMOVE:\r
- status = NDIS_STATUS_NOT_ACCEPTED;\r
- break;\r
-\r
- default:\r
- if( !p_adapter->packet_filter && (*(uint32_t*)info_buf) )\r
- {\r
- cl_qlist_insert_tail(\r
- &g_ipoib.adapter_list, &p_adapter->entry );\r
-\r
- /*\r
- * Filter was zero, now non-zero. Register IP addresses\r
- * with SA.\r
- */\r
- ipoib_reg_addrs( p_adapter );\r
- }\r
- else if( p_adapter->packet_filter && !(*(uint32_t*)info_buf) )\r
- {\r
- /*\r
- * Filter was non-zero, now zero. Deregister IP addresses.\r
- */\r
- ipoib_dereg_addrs( p_adapter );\r
-\r
- ASSERT( cl_qlist_count( &g_ipoib.adapter_list ) );\r
- cl_qlist_remove_item(\r
- &g_ipoib.adapter_list, &p_adapter->entry );\r
- }\r
-\r
- p_adapter->packet_filter = *(uint32_t*)info_buf;\r
- }\r
- cl_obj_unlock( &p_adapter->obj );\r
- KeReleaseInStackQueuedSpinLock( &hdl );\r
- }\r
- break;\r
-\r
- case OID_GEN_CURRENT_LOOKAHEAD:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received set for OID_GEN_CURRENT_LOOKAHEAD\n", port_num));\r
- if( info_buf_len < buf_len )\r
- status = NDIS_STATUS_INVALID_LENGTH;\r
- break;\r
-\r
- case OID_GEN_PROTOCOL_OPTIONS:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received set for OID_GEN_PROTOCOL_OPTIONS\n", port_num));\r
- if( info_buf_len < buf_len )\r
- status = NDIS_STATUS_INVALID_LENGTH;\r
- break;\r
-\r
- case OID_GEN_NETWORK_LAYER_ADDRESSES:\r
- status = __ipoib_set_net_addr( p_adapter, info_buf, info_buf_len, p_bytes_read, p_bytes_needed);\r
- break;\r
-\r
-#ifdef NDIS51_MINIPORT\r
- case OID_GEN_MACHINE_NAME:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,\r
- ("Port %d received set for OID_GEN_MACHINE_NAME\n", port_num) );\r
- break;\r
-#endif\r
-\r
- /* Required Ethernet operational characteristics */\r
- case OID_802_3_MULTICAST_LIST:\r
- IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,\r
- ("Port %d received set for OID_802_3_MULTICAST_LIST\n", port_num) );\r
- if( info_buf_len > MAX_MCAST * sizeof(mac_addr_t) )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d OID_802_3_MULTICAST_LIST - Multicast list full.\n", port_num) );\r
- status = NDIS_STATUS_MULTICAST_FULL;\r
- *p_bytes_needed = MAX_MCAST * sizeof(mac_addr_t);\r
- }\r
- else if( info_buf_len % sizeof(mac_addr_t) )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d OID_802_3_MULTICAST_LIST - Invalid input buffer.\n", port_num) );\r
- status = NDIS_STATUS_INVALID_DATA;\r
- }\r
- else if( !info_buf && info_buf_len )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d OID_802_3_MULTICAST_LIST - Invalid input buffer.\n", port_num) );\r
- status = NDIS_STATUS_INVALID_DATA;\r
- }\r
- else\r
- {\r
- ipoib_refresh_mcast( p_adapter, (mac_addr_t*)info_buf,\r
- (uint8_t)(info_buf_len / sizeof(mac_addr_t)) );\r
-\r
- buf_len = info_buf_len;\r
- /*\r
- * Note that we don't return pending. It will likely take longer\r
- * for our SA transactions to complete than NDIS will give us\r
- * before reseting the adapter. If an SA failure is encountered,\r
- * the adapter will be marked as hung and we will get reset.\r
- */\r
- status = NDIS_STATUS_SUCCESS;\r
- }\r
- break;\r
-\r
- case OID_TCP_TASK_OFFLOAD:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received set for OID_TCP_TASK_OFFLOAD\n", port_num) );\r
-\r
- buf_len = info_buf_len;\r
- status =\r
- __ipoib_set_tcp_task_offload( p_adapter, info_buf, &buf_len );\r
- break;\r
-\r
- /* Optional General */\r
- case OID_GEN_TRANSPORT_HEADER_OFFSET:\r
-#ifdef NDIS51_MINIPORT\r
- case OID_GEN_RNDIS_CONFIG_PARAMETER:\r
- case OID_GEN_VLAN_ID:\r
-#endif\r
- status = NDIS_STATUS_NOT_SUPPORTED;\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received an unsupported oid of 0x%.8X!\n", port_num, oid));\r
- break;\r
-\r
- case OID_GEN_SUPPORTED_LIST:\r
- case OID_GEN_HARDWARE_STATUS:\r
- case OID_GEN_MEDIA_SUPPORTED:\r
- case OID_GEN_MEDIA_IN_USE:\r
- case OID_GEN_MAXIMUM_FRAME_SIZE:\r
- case OID_GEN_LINK_SPEED:\r
- case OID_GEN_TRANSMIT_BUFFER_SPACE:\r
- case OID_GEN_RECEIVE_BUFFER_SPACE:\r
- case OID_GEN_MAXIMUM_LOOKAHEAD:\r
- case OID_GEN_TRANSMIT_BLOCK_SIZE:\r
- case OID_GEN_RECEIVE_BLOCK_SIZE:\r
- case OID_GEN_MAXIMUM_TOTAL_SIZE:\r
- case OID_GEN_VENDOR_ID:\r
- case OID_GEN_VENDOR_DESCRIPTION:\r
- case OID_GEN_VENDOR_DRIVER_VERSION:\r
- case OID_GEN_DRIVER_VERSION:\r
- case OID_GEN_MAC_OPTIONS:\r
- case OID_GEN_MEDIA_CONNECT_STATUS:\r
- case OID_GEN_MAXIMUM_SEND_PACKETS:\r
- case OID_GEN_SUPPORTED_GUIDS:\r
- case OID_GEN_PHYSICAL_MEDIUM:\r
- default:\r
- status = NDIS_STATUS_INVALID_OID;\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received an invalid oid of 0x%.8X!\n", port_num, oid));\r
- break;\r
- }\r
-\r
- if( status == NDIS_STATUS_SUCCESS )\r
- {\r
- *p_bytes_read = buf_len;\r
- }\r
- else\r
- {\r
- if( status == NDIS_STATUS_INVALID_LENGTH )\r
- {\r
- if ( !*p_bytes_needed )\r
- {\r
- *p_bytes_needed = buf_len;\r
- }\r
- }\r
-\r
- *p_bytes_read = 0;\r
- }\r
-\r
- IPOIB_EXIT( IPOIB_DBG_OID );\r
- return status;\r
-}\r
-\r
-#ifdef NNN\r
-NDIS_STATUS\r
-ipoib_set_info(\r
- ipoib_adapter_t* p_adapter,\r
- IN PNDIS_OID_REQUEST pNdisRequest)\r
-{\r
- NDIS_STATUS status;\r
- NDIS_OID oid;\r
- UINT info_buf_len;\r
- UINT buf_len;\r
- uint8_t port_num;\r
- PVOID info_buf;\r
- UINT *p_bytes_needed;\r
- KLOCK_QUEUE_HANDLE hdl;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_OID );\r
-\r
- oid = pNdisRequest->DATA.SET_INFORMATION.Oid;\r
- info_buf = pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;\r
- info_buf_len = pNdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength;\r
- p_bytes_needed = &pNdisRequest->DATA.QUERY_INFORMATION.BytesNeeded;\r
- status = NDIS_STATUS_SUCCESS;\r
-\r
- buf_len = sizeof(UINT);\r
- port_num = p_adapter->guids.port_num;\r
-\r
- switch( oid )\r
- {\r
- /* Required General */\r
- case OID_GEN_CURRENT_PACKET_FILTER:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received set for OID_GEN_CURRENT_PACKET_FILTER\n", port_num));\r
- if( info_buf_len < sizeof(p_adapter->packet_filter) )\r
- {\r
- status = NDIS_STATUS_INVALID_LENGTH;\r
- }\r
- else if( !info_buf )\r
- {\r
- status = NDIS_STATUS_INVALID_DATA;\r
- }\r
- else\r
- {\r
- KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
- cl_obj_lock( &p_adapter->obj );\r
- switch( p_adapter->state )\r
- {\r
- case IB_PNP_PORT_ADD:\r
- p_adapter->p_oid_request = pNdisRequest;\r
- status = NDIS_STATUS_PENDING;\r
- break;\r
-\r
- case IB_PNP_PORT_REMOVE:\r
- status = NDIS_STATUS_NOT_ACCEPTED;\r
- break;\r
-\r
- default:\r
- if( !p_adapter->packet_filter && (*(uint32_t*)info_buf) )\r
- {\r
- cl_qlist_insert_tail(\r
- &g_ipoib.adapter_list, &p_adapter->entry );\r
-\r
- /*\r
- * Filter was zero, now non-zero. Register IP addresses\r
- * with SA.\r
- */\r
- ipoib_reg_addrs( p_adapter );\r
- }\r
- else if( p_adapter->packet_filter && !(*(uint32_t*)info_buf) )\r
- {\r
- /*\r
- * Filter was non-zero, now zero. Deregister IP addresses.\r
- */\r
- ipoib_dereg_addrs( p_adapter );\r
-\r
- ASSERT( cl_qlist_count( &g_ipoib.adapter_list ) );\r
- cl_qlist_remove_item(\r
- &g_ipoib.adapter_list, &p_adapter->entry );\r
- }\r
-\r
- p_adapter->packet_filter = *(uint32_t*)info_buf;\r
- }\r
- cl_obj_unlock( &p_adapter->obj );\r
- KeReleaseInStackQueuedSpinLock( &hdl );\r
- }\r
- break;\r
-\r
- case OID_GEN_CURRENT_LOOKAHEAD:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received set for OID_GEN_CURRENT_LOOKAHEAD\n", port_num));\r
- if( info_buf_len < buf_len )\r
- status = NDIS_STATUS_INVALID_LENGTH;\r
- break;\r
-\r
- case OID_GEN_PROTOCOL_OPTIONS:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received set for OID_GEN_PROTOCOL_OPTIONS\n", port_num));\r
- if( info_buf_len < buf_len )\r
- status = NDIS_STATUS_INVALID_LENGTH;\r
- break;\r
-\r
- case OID_GEN_NETWORK_LAYER_ADDRESSES:\r
- status = __ipoib_set_net_addr( p_adapter, pNdisRequest);\r
- break;\r
-\r
- case OID_GEN_MACHINE_NAME:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,\r
- ("Port %d received set for OID_GEN_MACHINE_NAME\n", port_num) );\r
- break;\r
-\r
-\r
- /* Required Ethernet operational characteristics */\r
- case OID_802_3_MULTICAST_LIST:\r
- IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,\r
- ("Port %d received set for OID_802_3_MULTICAST_LIST\n", port_num) );\r
- if( info_buf_len > MAX_MCAST * sizeof(mac_addr_t) )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d OID_802_3_MULTICAST_LIST - Multicast list full.\n", port_num) );\r
- status = NDIS_STATUS_MULTICAST_FULL;\r
- *p_bytes_needed = MAX_MCAST * sizeof(mac_addr_t);\r
- }\r
- else if( info_buf_len % sizeof(mac_addr_t) )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d OID_802_3_MULTICAST_LIST - Invalid input buffer.\n", port_num) );\r
- status = NDIS_STATUS_INVALID_DATA;\r
- }\r
- else if( !info_buf && info_buf_len )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d OID_802_3_MULTICAST_LIST - Invalid input buffer.\n", port_num) );\r
- status = NDIS_STATUS_INVALID_DATA;\r
- }\r
- else\r
- {\r
- ipoib_refresh_mcast( p_adapter, (mac_addr_t*)info_buf,\r
- (uint8_t)(info_buf_len / sizeof(mac_addr_t)) );\r
-\r
- buf_len = info_buf_len;\r
- /*\r
- * Note that we don't return pending. It will likely take longer\r
- * for our SA transactions to complete than NDIS will give us\r
- * before reseting the adapter. If an SA failure is encountered,\r
- * the adapter will be marked as hung and we will get reset.\r
- */\r
- status = NDIS_STATUS_SUCCESS;\r
- }\r
- break;\r
-\r
- case OID_TCP_TASK_OFFLOAD:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received set for OID_TCP_TASK_OFFLOAD\n", port_num) );\r
-\r
- buf_len = info_buf_len;\r
- status =\r
- __ipoib_set_tcp_task_offload( p_adapter, pNdisRequest );\r
- break;\r
-\r
- /* Optional General */\r
- case OID_GEN_TRANSPORT_HEADER_OFFSET:\r
-#ifdef NDIS51_MINIPORT\r
- case OID_GEN_RNDIS_CONFIG_PARAMETER:\r
- case OID_GEN_VLAN_ID:\r
-#endif\r
- status = NDIS_STATUS_NOT_SUPPORTED;\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received an unsupported oid of 0x%.8X!\n", port_num, oid));\r
- break;\r
-\r
- case OID_GEN_SUPPORTED_LIST:\r
- case OID_GEN_HARDWARE_STATUS:\r
- case OID_GEN_MEDIA_SUPPORTED:\r
- case OID_GEN_MEDIA_IN_USE:\r
- case OID_GEN_MAXIMUM_FRAME_SIZE:\r
- case OID_GEN_LINK_SPEED:\r
- case OID_GEN_TRANSMIT_BUFFER_SPACE:\r
- case OID_GEN_RECEIVE_BUFFER_SPACE:\r
- case OID_GEN_MAXIMUM_LOOKAHEAD:\r
- case OID_GEN_TRANSMIT_BLOCK_SIZE:\r
- case OID_GEN_RECEIVE_BLOCK_SIZE:\r
- case OID_GEN_MAXIMUM_TOTAL_SIZE:\r
- case OID_GEN_VENDOR_ID:\r
- case OID_GEN_VENDOR_DESCRIPTION:\r
- case OID_GEN_VENDOR_DRIVER_VERSION:\r
- case OID_GEN_DRIVER_VERSION:\r
- case OID_GEN_MAC_OPTIONS:\r
- case OID_GEN_MEDIA_CONNECT_STATUS:\r
- case OID_GEN_MAXIMUM_SEND_PACKETS:\r
- case OID_GEN_SUPPORTED_GUIDS:\r
- case OID_GEN_PHYSICAL_MEDIUM:\r
- default:\r
- status = NDIS_STATUS_INVALID_OID;\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received an invalid oid of 0x%.8X!\n", port_num, oid));\r
- break;\r
- }\r
-\r
- if( status == NDIS_STATUS_SUCCESS )\r
- {\r
- pNdisRequest->DATA.SET_INFORMATION.BytesRead = buf_len;\r
- }\r
- else\r
- {\r
- if( status == NDIS_STATUS_INVALID_LENGTH )\r
- {\r
- if ( !*p_bytes_needed )\r
- {\r
- *p_bytes_needed = buf_len;\r
- }\r
- }\r
-\r
- pNdisRequest->DATA.SET_INFORMATION.BytesRead = 0;\r
- }\r
-\r
- IPOIB_EXIT( IPOIB_DBG_OID );\r
- return status;\r
-}\r
-#endif\r
-static NDIS_STATUS\r
-ipoib_oid_handler(\r
- IN NDIS_HANDLE adapter_context,\r
- IN PNDIS_OID_REQUEST pNdisRequest)\r
-{\r
- NDIS_REQUEST_TYPE RequestType;\r
- NDIS_STATUS status = NDIS_STATUS_SUCCESS;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_OID );\r
-\r
- RequestType = pNdisRequest->RequestType;\r
-\r
- switch(RequestType)\r
- {\r
- case NdisRequestSetInformation: \r
- status = ipoib_set_info(adapter_context,\r
- pNdisRequest->DATA.SET_INFORMATION.Oid,\r
- pNdisRequest->DATA.SET_INFORMATION.InformationBuffer,\r
- pNdisRequest->DATA.SET_INFORMATION.InformationBufferLength,\r
- (PULONG)&pNdisRequest->DATA.SET_INFORMATION.BytesRead,\r
- (PULONG)&pNdisRequest->DATA.SET_INFORMATION.BytesNeeded);\r
- break;\r
- \r
- case NdisRequestQueryInformation:\r
- case NdisRequestQueryStatistics:\r
- status = ipoib_query_info(adapter_context,\r
- pNdisRequest->DATA.QUERY_INFORMATION.Oid,\r
- pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer,\r
- pNdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength,\r
- (PULONG)&pNdisRequest->DATA.QUERY_INFORMATION.BytesWritten,\r
- (PULONG)&pNdisRequest->DATA.QUERY_INFORMATION.BytesNeeded);\r
- \r
- break;\r
-\r
- default:\r
- status = NDIS_STATUS_NOT_SUPPORTED;\r
- break;\r
- }\r
- IPOIB_EXIT( IPOIB_DBG_OID );\r
- return status;\r
-}\r
-\r
-//! Transfers some number of packets, specified as an array of packet pointers, over the network. \r
-/* For a deserialized driver, these packets are completed asynchronously\r
-using NdisMSendComplete.\r
-IRQL <= DISPATCH_LEVEL\r
-\r
-@param adapter_context Pointer to ipoib_adapter_t structure with per NIC state\r
-@param packet_array Array of packets to send\r
-@param numPackets Number of packets in the array\r
-*/\r
-void\r
-ipoib_send_net_buffer_list(\r
- IN NDIS_HANDLE adapter_context,\r
- IN PNET_BUFFER_LIST net_buffer_list,\r
- IN NDIS_PORT_NUMBER port_num,\r
- IN ULONG send_flags\r
- )\r
-{\r
- ipoib_adapter_t *p_adapter;\r
- ipoib_port_t *p_port;\r
- ULONG send_complete_flags;\r
- PNET_BUFFER_LIST curr_net_buffer_list;\r
- PNET_BUFFER_LIST next_net_buffer_list;\r
- NDIS_STATUS status = NDIS_STATUS_SUCCESS;\r
- \r
- UNREFERENCED_PARAMETER(port_num);\r
- PERF_DECLARE( SendPackets );\r
- PERF_DECLARE( PortSend );\r
-\r
- IPOIB_ENTER( IPOIB_DBG_SEND );\r
- cl_perf_start( SendPackets );\r
-\r
- CL_ASSERT( adapter_context );\r
- p_adapter = (ipoib_adapter_t*)adapter_context;\r
- p_port = p_adapter->p_port;\r
-\r
- cl_obj_lock( &p_adapter->obj );\r
- if( p_adapter->ipoib_state == IPOIB_PAUSING ||\r
- p_adapter->ipoib_state == IPOIB_PAUSED)\r
- {\r
- status = NDIS_STATUS_PAUSED; \r
- cl_obj_unlock( &p_adapter->obj );\r
- goto compl_status;\r
- }\r
-\r
- if( p_adapter->state != IB_PNP_PORT_ACTIVE || !p_adapter->p_port )\r
- {\r
- cl_obj_unlock( &p_adapter->obj );\r
- status = NDIS_STATUS_FAILURE; \r
- goto compl_status;\r
- }\r
-\r
- p_port = p_adapter->p_port;\r
- ipoib_port_ref( p_port, ref_send_packets );\r
- cl_obj_unlock( &p_adapter->obj );\r
- //IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- // ("Starting NET BUFFER LIST \n") );\r
- for (curr_net_buffer_list = net_buffer_list;\r
- curr_net_buffer_list != NULL;\r
- curr_net_buffer_list = next_net_buffer_list)\r
- {\r
- next_net_buffer_list = NET_BUFFER_LIST_NEXT_NBL(curr_net_buffer_list);\r
- cl_perf_start( PortSend );\r
- \r
- ipoib_port_send( p_port, curr_net_buffer_list, send_flags);\r
- cl_perf_stop( &adapter->perf, PortSend );\r
- }\r
- ipoib_port_deref( p_port, ref_send_packets );\r
-\r
- cl_perf_stop( &p_adapter->perf, SendPackets );\r
-\r
- cl_perf_log( &p_adapter->perf, SendBundle, num_packets );\r
-\r
-compl_status:\r
- if (status != NDIS_STATUS_SUCCESS)\r
- {\r
- //ASSERT(FALSE); //????\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Got bad status \n") );\r
- send_complete_flags = 0;\r
- \r
- for (curr_net_buffer_list = net_buffer_list;\r
- curr_net_buffer_list != NULL;\r
- curr_net_buffer_list = next_net_buffer_list)\r
- {\r
- next_net_buffer_list = NET_BUFFER_LIST_NEXT_NBL(curr_net_buffer_list);\r
- NET_BUFFER_LIST_STATUS(curr_net_buffer_list) = status;\r
- ipoib_inc_send_stat( p_adapter, IP_STAT_DROPPED, 0 );\r
- }\r
-\r
-\r
- if (NDIS_TEST_SEND_AT_DISPATCH_LEVEL(send_flags))\r
- {\r
- NDIS_SET_SEND_COMPLETE_FLAG(send_complete_flags, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL);\r
- }\r
- \r
- NdisMSendNetBufferListsComplete(\r
- p_adapter->h_adapter,\r
- net_buffer_list,\r
- send_complete_flags); \r
- }\r
- IPOIB_EXIT( IPOIB_DBG_SEND );\r
-}\r
-\r
-void\r
-ipoib_pnp_notify(\r
- IN NDIS_HANDLE adapter_context,\r
- IN PNET_DEVICE_PNP_EVENT pnp_event)\r
-{\r
- ipoib_adapter_t *p_adapter;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_PNP );\r
-\r
- p_adapter = (ipoib_adapter_t*)adapter_context;\r
-\r
- IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_PNP, ("Event %d\n", pnp_event->DevicePnPEvent) );\r
- if( pnp_event->DevicePnPEvent != NdisDevicePnPEventPowerProfileChanged )\r
- {\r
- cl_obj_lock( &p_adapter->obj );\r
- p_adapter->state = IB_PNP_PORT_REMOVE;\r
- cl_obj_unlock( &p_adapter->obj );\r
-\r
- ipoib_resume_oids( p_adapter );\r
- }\r
-\r
- IPOIB_EXIT( IPOIB_DBG_PNP );\r
-}\r
-\r
-\r
-VOID\r
-ipoib_shutdown_ex(\r
- IN NDIS_HANDLE adapter_context,\r
- IN NDIS_SHUTDOWN_ACTION shutdown_action)\r
-{\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
- UNUSED_PARAM( adapter_context );\r
- UNUSED_PARAM( shutdown_action );\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
-}\r
-\r
-\r
-void\r
-ipoib_resume_oids(\r
- IN ipoib_adapter_t* const p_adapter )\r
-{\r
- ULONG info;\r
- NDIS_STATUS status;\r
- boolean_t pending_query, pending_set;\r
- pending_oid_t query_oid = {0};\r
- pending_oid_t set_oid = {0};\r
- KLOCK_QUEUE_HANDLE hdl;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-\r
- cl_obj_lock( &p_adapter->obj );\r
- /*\r
- * Set the status depending on our state. Fail OID requests that\r
- * are pending while we reset the adapter.\r
- */\r
- switch( p_adapter->state )\r
- {\r
- case IB_PNP_PORT_ADD:\r
- status = NDIS_STATUS_FAILURE;\r
- break;\r
-\r
- case IB_PNP_PORT_REMOVE:\r
- status = NDIS_STATUS_NOT_ACCEPTED;\r
- break;\r
- \r
- default:\r
- status = NDIS_STATUS_SUCCESS;\r
- }\r
-\r
- pending_query = p_adapter->pending_query;\r
- if( pending_query )\r
- {\r
- query_oid = p_adapter->query_oid;\r
- p_adapter->pending_query = FALSE;\r
- }\r
- pending_set = p_adapter->pending_set;\r
- if( pending_set )\r
- {\r
- set_oid = p_adapter->set_oid;\r
- p_adapter->pending_set = FALSE;\r
- }\r
- cl_obj_unlock( &p_adapter->obj );\r
-\r
- /*\r
- * If we had a pending OID request for OID_GEN_LINK_SPEED,\r
- * complete it now. Note that we hold the object lock since\r
- * NdisMQueryInformationComplete is called at DISPATCH_LEVEL.\r
- */\r
- if( pending_query )\r
- {\r
- switch( query_oid.oid )\r
- {\r
- case OID_GEN_LINK_SPEED:\r
- ipoib_complete_query( p_adapter, &query_oid,\r
- status, &p_adapter->port_rate, sizeof(p_adapter->port_rate) );\r
- break;\r
-\r
- case OID_GEN_MEDIA_CONNECT_STATUS:\r
- info = NdisMediaStateConnected;\r
- ipoib_complete_query( p_adapter, &query_oid,\r
- status, &info, sizeof(info) );\r
- break;\r
-\r
- default:\r
- CL_ASSERT( query_oid.oid == OID_GEN_LINK_SPEED ||\r
- query_oid.oid == OID_GEN_MEDIA_CONNECT_STATUS );\r
- break;\r
- }\r
- }\r
-\r
- if( pending_set )\r
- {\r
- switch( set_oid.oid )\r
- {\r
- case OID_GEN_CURRENT_PACKET_FILTER:\r
- /* Validation already performed in the SetInformation path. */\r
-\r
- KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
- cl_obj_lock( &p_adapter->obj );\r
- if( !p_adapter->packet_filter && (*(PULONG)set_oid.p_buf) )\r
- {\r
- cl_qlist_insert_tail(\r
- &g_ipoib.adapter_list, &p_adapter->entry );\r
- /*\r
- * Filter was zero, now non-zero. Register IP addresses\r
- * with SA.\r
- */\r
- ipoib_reg_addrs( p_adapter );\r
- }\r
- else if( p_adapter->packet_filter && !(*(PULONG)set_oid.p_buf) )\r
- {\r
- /* Filter was non-zero, now zero. Deregister IP addresses. */\r
- ipoib_dereg_addrs( p_adapter );\r
-\r
- ASSERT( cl_qlist_count( &g_ipoib.adapter_list ) );\r
- cl_qlist_remove_item(\r
- &g_ipoib.adapter_list, &p_adapter->entry );\r
- }\r
- p_adapter->packet_filter = *(PULONG)set_oid.p_buf;\r
-\r
- cl_obj_unlock( &p_adapter->obj );\r
- KeReleaseInStackQueuedSpinLock( &hdl );\r
- p_adapter->set_oid.p_pending_oid = NULL;\r
- NdisMOidRequestComplete( p_adapter->h_adapter, set_oid.p_pending_oid, status );\r
- break;\r
-\r
- case OID_GEN_NETWORK_LAYER_ADDRESSES:\r
- status = __ipoib_set_net_addr( p_adapter,\r
- p_adapter->set_oid.p_buf,\r
- p_adapter->set_oid.buf_len,\r
- p_adapter->set_oid.p_bytes_used,\r
- p_adapter->set_oid.p_bytes_needed );\r
-\r
- if( status != NDIS_STATUS_PENDING )\r
- {\r
- p_adapter->set_oid.p_pending_oid = NULL;\r
- NdisMOidRequestComplete( p_adapter->h_adapter, set_oid.p_pending_oid, status );\r
- }\r
- break;\r
-\r
- default:\r
- CL_ASSERT( set_oid.oid && 0 );\r
- break;\r
- }\r
- }\r
-\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
-}\r
-\r
-\r
-static NDIS_STATUS\r
-__ipoib_set_net_addr(\r
- IN ipoib_adapter_t * p_adapter,\r
- IN PVOID info_buf,\r
- IN ULONG info_buf_len,\r
- OUT PULONG p_bytes_read,\r
- OUT PULONG p_bytes_needed )\r
-{\r
- NDIS_STATUS status;\r
- PNETWORK_ADDRESS_LIST p_net_addrs;\r
- PNETWORK_ADDRESS p_net_addr_oid;\r
- PNETWORK_ADDRESS_IP p_ip_addr;\r
-\r
- net_address_item_t *p_addr_item;\r
-\r
- cl_status_t cl_status;\r
-\r
- size_t idx;\r
- LONG i;\r
- ULONG addr_size;\r
- ULONG total_size;\r
-\r
- uint8_t port_num;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_OID );\r
-\r
- status = NDIS_STATUS_SUCCESS;\r
- port_num = p_adapter->guids.port_num;\r
-\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d received set for OID_GEN_NETWORK_LAYER_ADDRESSES\n",\r
- port_num) );\r
-\r
- if( !info_buf )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Port %d - OID_GEN_NETWORK_LAYER_ADDRESSES - "\r
- "NULL buffer\n", port_num) );\r
- IPOIB_EXIT( IPOIB_DBG_OID );\r
- return NDIS_STATUS_INVALID_DATA;\r
- }\r
-\r
- /*\r
- * Must use field offset because the structures define array's of size one\r
- * of a the incorrect type for what is really stored.\r
- */\r
- if( info_buf_len < FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address) )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, \r
- ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - "\r
- "bad length of %d, not enough "\r
- "for NETWORK_ADDRESS_LIST (%d)\n", port_num, info_buf_len,\r
- FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address)) );\r
- *p_bytes_needed = FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address);\r
- IPOIB_EXIT( IPOIB_DBG_OID );\r
- return NDIS_STATUS_INVALID_LENGTH;\r
- }\r
-\r
- p_net_addrs = (PNETWORK_ADDRESS_LIST)info_buf;\r
- if( p_net_addrs->AddressCount == 0)\r
- {\r
- if( p_net_addrs->AddressType == NDIS_PROTOCOL_ID_TCP_IP )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,\r
- ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - "\r
- "clear TCP/IP addresses\n", port_num) );\r
- }\r
- else\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,\r
- ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - "\r
- "Non TCP/IP address type of 0x%.4X on clear\n",\r
- port_num, p_net_addrs->AddressType) );\r
- IPOIB_EXIT( IPOIB_DBG_OID );\r
- return NDIS_STATUS_SUCCESS;\r
- }\r
- }\r
-\r
- addr_size = FIELD_OFFSET(NETWORK_ADDRESS, Address) +\r
- NETWORK_ADDRESS_LENGTH_IP;\r
- total_size = FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address) +\r
- addr_size * p_net_addrs->AddressCount;\r
-\r
- if( info_buf_len < total_size )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - "\r
- "bad length of %d, %d required for %d addresses\n",\r
- port_num, info_buf_len, total_size, p_net_addrs->AddressCount) );\r
- *p_bytes_needed = total_size;\r
- IPOIB_EXIT( IPOIB_DBG_OID );\r
- return NDIS_STATUS_INVALID_LENGTH;\r
- }\r
-\r
- /* Lock lists for duration since SA callbacks can occur on other CPUs */\r
- cl_obj_lock( &p_adapter->obj );\r
-\r
- /* Set the capacity of the vector to accomodate all assinged addresses. */\r
- cl_status = cl_vector_set_capacity(\r
- &p_adapter->ip_vector, p_net_addrs->AddressCount );\r
- if( cl_status != CL_SUCCESS )\r
- {\r
- cl_obj_unlock( &p_adapter->obj );\r
- IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Port %d - OID_GEN_NETWORK_LAYER_ADDRESSES - "\r
- "Failed to set IP vector capacity: %#x\n", port_num,\r
- cl_status) );\r
- IPOIB_EXIT( IPOIB_DBG_OID );\r
- return NDIS_STATUS_RESOURCES;\r
- }\r
-\r
- *p_bytes_read = total_size;\r
-\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - List contains %d addresses\n",\r
- port_num, p_net_addrs->AddressCount));\r
-\r
- /* First look for addresses we had that should be removed */\r
- for( idx = 0; idx != cl_vector_get_size( &p_adapter->ip_vector ); idx++ )\r
- {\r
- p_addr_item = (net_address_item_t*)\r
- cl_vector_get_ptr( &p_adapter->ip_vector, idx );\r
- p_net_addr_oid = (PNETWORK_ADDRESS)p_net_addrs->Address;\r
-\r
- for( i = 0; i < p_net_addrs->AddressCount; ++i, p_net_addr_oid =\r
- (PNETWORK_ADDRESS)((uint8_t *)p_net_addr_oid +\r
- FIELD_OFFSET(NETWORK_ADDRESS, Address) +\r
- p_net_addr_oid->AddressLength) )\r
- {\r
-\r
- if( p_net_addr_oid->AddressType != NDIS_PROTOCOL_ID_TCP_IP )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_OID,\r
- ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Address %d is wrong type of 0x%.4X, "\r
- "should be 0x%.4X\n", port_num, i, p_net_addr_oid->AddressType,\r
- NDIS_PROTOCOL_ID_TCP_IP));\r
- continue;\r
- }\r
-\r
- if( p_net_addr_oid->AddressLength != NETWORK_ADDRESS_LENGTH_IP)\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_OID,\r
- ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Address %d is wrong size of %d, "\r
- "should be %d\n", port_num, i, p_net_addr_oid->AddressLength,\r
- NETWORK_ADDRESS_LENGTH_IP));\r
- continue;\r
- }\r
-\r
- p_ip_addr = (PNETWORK_ADDRESS_IP)p_net_addr_oid->Address;\r
- if( !cl_memcmp( &p_ip_addr->in_addr,\r
- &p_addr_item->address.as_ulong, sizeof(ULONG) ) )\r
- {\r
- break;\r
- }\r
- }\r
-\r
- if( i == p_net_addrs->AddressCount )\r
- {\r
- /* Didn't find a match, delete from SA */\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Deleting Address %d.%d.%d.%d\n",\r
- port_num,\r
- p_addr_item->address.as_bytes[0],\r
- p_addr_item->address.as_bytes[1],\r
- p_addr_item->address.as_bytes[2],\r
- p_addr_item->address.as_bytes[3]));\r
-\r
- if( p_addr_item->p_reg )\r
- {\r
- if( p_addr_item->p_reg->h_reg_svc )\r
- {\r
- p_adapter->p_ifc->dereg_svc(\r
- p_addr_item->p_reg->h_reg_svc, __ipoib_ats_dereg_cb );\r
- }\r
- else\r
- {\r
- cl_free( p_addr_item->p_reg );\r
- }\r
- p_addr_item->p_reg = NULL;\r
- }\r
- p_addr_item->address.as_ulong = 0;\r
- }\r
- }\r
-\r
- /* Now look for new addresses */\r
- p_net_addr_oid = (NETWORK_ADDRESS *)p_net_addrs->Address;\r
- idx = 0;\r
- for( i = 0; i < p_net_addrs->AddressCount; i++, p_net_addr_oid =\r
- (PNETWORK_ADDRESS)((uint8_t *)p_net_addr_oid +\r
- FIELD_OFFSET(NETWORK_ADDRESS, Address) + p_net_addr_oid->AddressLength) )\r
- {\r
-\r
- if( p_net_addr_oid->AddressType != NDIS_PROTOCOL_ID_TCP_IP )\r
- {\r
- IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,\r
- ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Address %d is wrong type of 0x%.4X, "\r
- "should be 0x%.4X\n", port_num, i, p_net_addr_oid->AddressType,\r
- NDIS_PROTOCOL_ID_TCP_IP));\r
- continue;\r
- }\r
-\r
- if( p_net_addr_oid->AddressLength != NETWORK_ADDRESS_LENGTH_IP)\r
- {\r
- IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,\r
- ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Address %d is wrong size of %d, "\r
- "should be %d\n", port_num, i, p_net_addr_oid->AddressLength,\r
- NETWORK_ADDRESS_LENGTH_IP));\r
- continue;\r
- }\r
-\r
- p_ip_addr = (PNETWORK_ADDRESS_IP)p_net_addr_oid->Address;\r
-\r
- /* Size the vector as needed. */\r
- if( cl_vector_get_size( &p_adapter->ip_vector ) <= idx )\r
- cl_vector_set_size( &p_adapter->ip_vector, idx + 1 );\r
-\r
- p_addr_item = cl_vector_get_ptr( &p_adapter->ip_vector, idx );\r
- if( !cl_memcmp( &p_ip_addr->in_addr, &p_addr_item->address.as_ulong,\r
- sizeof(ULONG) ) )\r
- {\r
- idx++;\r
- /* Already have this address - no change needed */\r
- continue;\r
- }\r
-\r
- /*\r
- * Copy the address information, but don't register yet - the port\r
- * could be down.\r
- */\r
- if( p_addr_item->p_reg )\r
- {\r
- /* If in use by some other address, deregister. */\r
- if( p_addr_item->p_reg->h_reg_svc )\r
- {\r
- p_adapter->p_ifc->dereg_svc(\r
- p_addr_item->p_reg->h_reg_svc, __ipoib_ats_dereg_cb );\r
- }\r
- else\r
- {\r
- cl_free( p_addr_item->p_reg );\r
- }\r
- p_addr_item->p_reg = NULL;\r
- }\r
- memcpy ((void *)&p_addr_item->address.as_ulong, (const void *)&p_ip_addr->in_addr, sizeof(ULONG) );\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Adding Address %d.%d.%d.%d\n",\r
- port_num,\r
- p_addr_item->address.as_bytes[0],\r
- p_addr_item->address.as_bytes[1],\r
- p_addr_item->address.as_bytes[2],\r
- p_addr_item->address.as_bytes[3]) );\r
- idx++;\r
- }\r
-\r
- /* Now clear any extra entries that shouldn't be there. */\r
- while( idx < cl_vector_get_size( &p_adapter->ip_vector ) )\r
- {\r
- p_addr_item = (net_address_item_t*)\r
- cl_vector_get_ptr( &p_adapter->ip_vector,\r
- cl_vector_get_size( &p_adapter->ip_vector ) - 1 );\r
-\r
- if( p_addr_item->p_reg )\r
- {\r
- if( p_addr_item->p_reg->h_reg_svc )\r
- {\r
- p_adapter->p_ifc->dereg_svc(\r
- p_addr_item->p_reg->h_reg_svc, __ipoib_ats_dereg_cb );\r
- }\r
- else\r
- {\r
- cl_free( p_addr_item->p_reg );\r
- }\r
- p_addr_item->p_reg = NULL;\r
- p_addr_item->address.as_ulong = 0;\r
- }\r
-\r
- /* No need to check return value - shrinking always succeeds. */\r
- cl_vector_set_size( &p_adapter->ip_vector,\r
- cl_vector_get_size( &p_adapter->ip_vector ) - 1 );\r
- }\r
-\r
- if( p_adapter->state == IB_PNP_PORT_ACTIVE && p_adapter->packet_filter )\r
- ipoib_reg_addrs( p_adapter );\r
-\r
- cl_obj_unlock( &p_adapter->obj );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_OID );\r
- return NDIS_STATUS_SUCCESS;\r
-}\r
-\r
-\r
-/* Object lock is held when this function is called. */\r
-void\r
-ipoib_reg_addrs(\r
- IN ipoib_adapter_t* const p_adapter )\r
-{\r
- net_address_item_t *p_addr_item;\r
-\r
- size_t idx;\r
-\r
- uint8_t port_num;\r
-\r
- ib_api_status_t ib_status;\r
- ib_reg_svc_req_t ib_service;\r
- ib_gid_t port_gid;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_OID );\r
-\r
- if(p_adapter->guids.port_guid.pkey != IB_DEFAULT_PKEY)\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR,IPOIB_DBG_ERROR,\r
- ("ATS Service available for default pkey only\n")); \r
- return;\r
- }\r
- port_num = p_adapter->guids.port_num;\r
-\r
- /* Setup our service call with things common to all calls */\r
- cl_memset( &ib_service, 0, sizeof(ib_service) );\r
-\r
- /* BUGBUG Only register local subnet GID prefix for now */\r
- ib_gid_set_default( &port_gid, p_adapter->guids.port_guid.guid );\r
- ib_service.svc_rec.service_gid = port_gid;\r
-\r
- ib_service.svc_rec.service_pkey = IB_DEFAULT_PKEY;\r
- ib_service.svc_rec.service_lease = IB_INFINITE_SERVICE_LEASE;\r
-\r
- /* Must cast here because the service name is an array of unsigned chars but\r
- * strcpy want a pointer to a signed char */\r
- if ( StringCchCopy( (char *)ib_service.svc_rec.service_name, \r
- sizeof(ib_service.svc_rec.service_name) / sizeof(char), ATS_NAME ) != S_OK) {\r
- ASSERT(FALSE);\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR,IPOIB_DBG_ERROR,\r
- ("Problem copying ATS name: exiting\n"));\r
- return;\r
- }\r
- \r
- /* IP Address in question will be put in below */\r
- ib_service.port_guid = p_adapter->guids.port_guid.guid;\r
- ib_service.timeout_ms = p_adapter->params.sa_timeout;\r
- ib_service.retry_cnt = p_adapter->params.sa_retry_cnt;\r
-\r
- /* Can't set IB_FLAGS_SYNC here because I can't wait at dispatch */\r
- ib_service.flags = 0;\r
-\r
- /* Service context will be put in below */\r
-\r
- ib_service.svc_data_mask = IB_SR_COMPMASK_SID |\r
- IB_SR_COMPMASK_SGID |\r
- IB_SR_COMPMASK_SPKEY |\r
- IB_SR_COMPMASK_SLEASE |\r
- IB_SR_COMPMASK_SNAME |\r
- IB_SR_COMPMASK_SDATA8_12 |\r
- IB_SR_COMPMASK_SDATA8_13 |\r
- IB_SR_COMPMASK_SDATA8_14 |\r
- IB_SR_COMPMASK_SDATA8_15;\r
- ib_service.pfn_reg_svc_cb = __ipoib_ats_reg_cb;\r
-\r
- for( idx = 0; idx < cl_vector_get_size( &p_adapter->ip_vector); idx++ )\r
- {\r
- p_addr_item = (net_address_item_t*)\r
- cl_vector_get_ptr( &p_adapter->ip_vector, idx );\r
-\r
- if( p_addr_item->p_reg )\r
- continue;\r
-\r
- p_addr_item->p_reg = cl_zalloc( sizeof(ats_reg_t) );\r
- if( !p_addr_item->p_reg )\r
- break;\r
-\r
- p_addr_item->p_reg->p_adapter = p_adapter;\r
-\r
- ib_service.svc_context = p_addr_item->p_reg;\r
-\r
- ib_service.svc_rec.service_id =\r
- ATS_SERVICE_ID & CL_HTON64(0xFFFFFFFFFFFFFF00);\r
- /* ATS service IDs start at 0x10000CE100415453 */\r
- ib_service.svc_rec.service_id |= ((uint64_t)(idx + 0x53)) << 56;\r
-\r
- cl_memcpy( &ib_service.svc_rec.service_data8[ATS_IPV4_OFFSET],\r
- p_addr_item->address.as_bytes, IPV4_ADDR_SIZE );\r
-\r
- /* Take a reference for each service request. */\r
- cl_obj_ref(&p_adapter->obj);\r
- ib_status = p_adapter->p_ifc->reg_svc(\r
- p_adapter->h_al, &ib_service, &p_addr_item->p_reg->h_reg_svc );\r
- if( ib_status != IB_SUCCESS )\r
- {\r
- if( ib_status == IB_INVALID_GUID )\r
- {\r
- /* If this occurs, we log the error but do not fail the OID yet */\r
- IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_OID,\r
- ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - "\r
- "Failed to register IP Address "\r
- "of %d.%d.%d.%d with error IB_INVALID_GUID\n",\r
- port_num,\r
- p_addr_item->address.as_bytes[0],\r
- p_addr_item->address.as_bytes[1],\r
- p_addr_item->address.as_bytes[2],\r
- p_addr_item->address.as_bytes[3]) );\r
- }\r
- else\r
- {\r
- /* Fatal error. */\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Failed to register IP Address "\r
- "of %d.%d.%d.%d with error %s\n",\r
- port_num,\r
- p_addr_item->address.as_bytes[0],\r
- p_addr_item->address.as_bytes[1],\r
- p_addr_item->address.as_bytes[2],\r
- p_addr_item->address.as_bytes[3],\r
- p_adapter->p_ifc->get_err_str( ib_status )) );\r
- p_adapter->hung = TRUE;\r
- }\r
- cl_obj_deref(&p_adapter->obj);\r
- cl_free( p_addr_item->p_reg );\r
- p_addr_item->p_reg = NULL;\r
- }\r
- }\r
-\r
- IPOIB_EXIT( IPOIB_DBG_OID );\r
-}\r
-\r
-\r
-/* Object lock is held when this function is called. */\r
-void\r
-ipoib_dereg_addrs(\r
- IN ipoib_adapter_t* const p_adapter )\r
-{\r
- net_address_item_t *p_addr_item;\r
-\r
- size_t idx;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_OID );\r
-\r
- for( idx = 0; idx < cl_vector_get_size( &p_adapter->ip_vector); idx++ )\r
- {\r
- p_addr_item = (net_address_item_t*)\r
- cl_vector_get_ptr( &p_adapter->ip_vector, idx );\r
-\r
- if( !p_addr_item->p_reg )\r
- continue;\r
-\r
- if( p_addr_item->p_reg->h_reg_svc )\r
- {\r
- p_adapter->p_ifc->dereg_svc(\r
- p_addr_item->p_reg->h_reg_svc, __ipoib_ats_dereg_cb );\r
- }\r
- else\r
- {\r
- cl_free( p_addr_item->p_reg );\r
- }\r
- p_addr_item->p_reg = NULL;\r
- }\r
-\r
- IPOIB_EXIT( IPOIB_DBG_OID );\r
-}\r
-\r
-\r
-void\r
-ipoib_cancel_xmit(\r
- IN NDIS_HANDLE adapter_context,\r
- IN PVOID cancel_id )\r
-{\r
-/* ipoib_adapter_t* const p_adapter =\r
- (ipoib_adapter_t* const )adapter_context;\r
- \r
-\r
-if 0\r
- if( p_adapter && p_adapter->p_port )\r
- {\r
- ipoib_port_cancel_xmit( p_adapter->p_port, cancel_id );\r
- }\r
-endif\r
-*/\r
-\r
- UNUSED_PARAM(adapter_context);\r
- UNUSED_PARAM(cancel_id);\r
-\r
- return; //TODO return this functionality\r
-\r
-}\r
-\r
-\r
-static void\r
-__ipoib_ats_reg_cb(\r
- IN ib_reg_svc_rec_t *p_reg_svc_rec )\r
-{\r
- ats_reg_t *p_reg;\r
- uint8_t port_num;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_OID );\r
-\r
- CL_ASSERT( p_reg_svc_rec );\r
- CL_ASSERT( p_reg_svc_rec->svc_context );\r
-\r
- p_reg = (ats_reg_t*)p_reg_svc_rec->svc_context;\r
- port_num = p_reg->p_adapter->guids.port_num;\r
-\r
- cl_obj_lock( &p_reg->p_adapter->obj );\r
-\r
- if( p_reg_svc_rec->req_status == IB_SUCCESS &&\r
- !p_reg_svc_rec->resp_status )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
- ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Registered IP Address "\r
- "of %d.%d.%d.%d\n",\r
- port_num,\r
- p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET],\r
- p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+1],\r
- p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+2],\r
- p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+3]) );\r
- }\r
- else if( p_reg_svc_rec->req_status != IB_CANCELED )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_OID,\r
- ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Failed to register IP Address "\r
- "of %d.%d.%d.%d with error %s\n",\r
- port_num,\r
- p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET],\r
- p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+1],\r
- p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+2],\r
- p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+3],\r
- p_reg->p_adapter->p_ifc->get_err_str( p_reg_svc_rec->resp_status )) );\r
- p_reg->p_adapter->hung = TRUE;\r
- p_reg->h_reg_svc = NULL;\r
- }\r
-\r
- cl_obj_unlock( &p_reg->p_adapter->obj );\r
- cl_obj_deref(&p_reg->p_adapter->obj);\r
-\r
- IPOIB_EXIT( IPOIB_DBG_OID );\r
-}\r
-\r
-\r
-static void\r
-__ipoib_ats_dereg_cb(\r
- IN void *context )\r
-{\r
- cl_free( context );\r
-}\r
-\r
-static NDIS_STATUS \r
-ipoib_pause(\r
- IN NDIS_HANDLE adapter_context, \r
- IN PNDIS_MINIPORT_PAUSE_PARAMETERS pause_parameters)\r
-{\r
- ipoib_adapter_t *p_adapter;\r
- KLOCK_QUEUE_HANDLE hdl;\r
-\r
- UNREFERENCED_PARAMETER(pause_parameters);\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-//return NDIS_STATUS_SUCCESS;\r
- CL_ASSERT(adapter_context);\r
- p_adapter = (ipoib_adapter_t*)adapter_context;\r
- CL_ASSERT(p_adapter->ipoib_state == IPOIB_RUNNING);\r
-\r
- KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
- p_adapter->ipoib_state = IPOIB_PAUSING;\r
- KeReleaseInStackQueuedSpinLock( &hdl );\r
-\r
- //TODO: \r
- ipoib_port_resume(p_adapter->p_port,FALSE);\r
-// ASSERT(FALSE);\r
-\r
- KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
- p_adapter->ipoib_state = IPOIB_PAUSED;\r
- KeReleaseInStackQueuedSpinLock( &hdl );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
- return NDIS_STATUS_SUCCESS;\r
-}\r
-\r
-static NDIS_STATUS \r
-ipoib_restart(\r
- IN NDIS_HANDLE adapter_context, \r
- IN PNDIS_MINIPORT_RESTART_PARAMETERS restart_parameters)\r
-{\r
- ipoib_adapter_t *p_adapter;\r
- KLOCK_QUEUE_HANDLE hdl;\r
- PNDIS_RESTART_ATTRIBUTES NdisRestartAttributes;\r
- PNDIS_RESTART_GENERAL_ATTRIBUTES NdisGeneralAttributes;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
- p_adapter = (ipoib_adapter_t*)adapter_context;\r
-\r
- NdisRestartAttributes = restart_parameters->RestartAttributes;\r
-\r
- if (NdisRestartAttributes != NULL)\r
- {\r
- CL_ASSERT(NdisRestartAttributes->Oid == OID_GEN_MINIPORT_RESTART_ATTRIBUTES);\r
- NdisGeneralAttributes = (PNDIS_RESTART_GENERAL_ATTRIBUTES)NdisRestartAttributes->Data; \r
- //\r
- // Check to see if we need to change any attributes\r
- }\r
-\r
- KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
- p_adapter->ipoib_state = IPOIB_RUNNING;\r
- KeReleaseInStackQueuedSpinLock( &hdl );\r
-\r
-\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
- return NDIS_STATUS_SUCCESS;\r
-}\r
-\r
-/*++\r
-Routine Description:\r
-\r
- This function aborts the request pending in the miniport.\r
-\r
-Arguments:\r
-\r
- MiniportAdapterContext Pointer to the adapter structure\r
- RequestId Specify the request to be cancelled.\r
- \r
-Return Value:\r
- \r
---*/\r
-static void\r
-ipoib_cancel_oid_request(\r
- IN NDIS_HANDLE adapter_context,\r
- IN PVOID requestId\r
- )\r
-{\r
- PNDIS_OID_REQUEST pending_request;\r
- ipoib_adapter_t *p_adapter;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_OID );\r
- p_adapter = (ipoib_adapter_t*)adapter_context;\r
-\r
- cl_obj_lock( &p_adapter->obj );\r
- \r
- if ( p_adapter->query_oid.p_pending_oid &&\r
- p_adapter->query_oid.p_pending_oid->RequestId == requestId)\r
- {\r
- pending_request = p_adapter->query_oid.p_pending_oid;\r
- p_adapter->query_oid.p_pending_oid = NULL;\r
- p_adapter->pending_query = FALSE;\r
- }\r
- else if(p_adapter->set_oid.p_pending_oid && \r
- p_adapter->set_oid.p_pending_oid->RequestId == requestId)\r
- {\r
- pending_request = p_adapter->set_oid.p_pending_oid;\r
- p_adapter->set_oid.p_pending_oid = NULL;\r
- p_adapter->pending_set = FALSE;\r
- }\r
- else\r
- {\r
- cl_obj_unlock( &p_adapter->obj );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("No Pending OID found\n") );\r
- return;\r
- }\r
- cl_obj_unlock( &p_adapter->obj );\r
-\r
- NdisMOidRequestComplete(p_adapter->h_adapter, \r
- pending_request, \r
- NDIS_STATUS_REQUEST_ABORTED);\r
-\r
- IPOIB_EXIT( IPOIB_DBG_OID );\r
-}\r
--- /dev/null
+/*\r
+ * Copyright (c) 2005 SilverStorm Technologies. All rights reserved.\r
+ * Copyright (c) 2006 Mellanox Technologies. All rights reserved.\r
+ * Portions Copyright (c) 2008 Microsoft Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ * - Redistributions of source code must retain the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer.\r
+ *\r
+ * - Redistributions in binary form must reproduce the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer in the documentation and/or other materials\r
+ * provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id: ipoib_driver.c 4506 2009-06-23 14:40:54Z xalex $\r
+ */\r
+\r
+#include "limits.h"\r
+#include "ipoib_driver.h"\r
+#include "ipoib_debug.h"\r
+\r
+#if defined(EVENT_TRACING)\r
+#ifdef offsetof\r
+#undef offsetof\r
+#endif\r
+#include "ipoib_driver.tmh"\r
+#endif\r
+\r
+#include "ipoib_port.h"\r
+#include "ipoib_ibat.h"\r
+#include <complib/cl_bus_ifc.h>\r
+#include <complib/cl_init.h>\r
+#include <initguid.h>\r
+#include <iba/ipoib_ifc.h>\r
+#include "ntstrsafe.h"\r
+#include "strsafe.h"\r
+#include <offload.h>\r
+\r
+\r
+\r
+#define MAJOR_DRIVER_VERSION 2\r
+#define MINOR_DRIVER_VERSION 1\r
+#if defined(NDIS60_MINIPORT)\r
+#define MAJOR_NDIS_VERSION 6\r
+#define MINOR_NDIS_VERSION 0\r
+\r
+#else\r
+#error NDIS Version not defined, try defining NDIS60_MINIPORT\r
+#endif\r
+\r
+PDRIVER_OBJECT g_p_drv_obj;\r
+\r
+\r
+#if 0\r
+static const NDIS_OID SUPPORTED_OIDS[] =\r
+{\r
+ OID_GEN_SUPPORTED_LIST,\r
+ OID_GEN_HARDWARE_STATUS,\r
+ OID_GEN_MEDIA_SUPPORTED,\r
+ OID_GEN_MEDIA_IN_USE,\r
+ OID_GEN_MAXIMUM_LOOKAHEAD,\r
+ OID_GEN_MAXIMUM_FRAME_SIZE,\r
+ OID_GEN_LINK_SPEED,\r
+ OID_GEN_TRANSMIT_BUFFER_SPACE,\r
+ OID_GEN_RECEIVE_BUFFER_SPACE,\r
+ OID_GEN_TRANSMIT_BLOCK_SIZE,\r
+ OID_GEN_RECEIVE_BLOCK_SIZE,\r
+ OID_GEN_VENDOR_ID,\r
+ OID_GEN_VENDOR_DESCRIPTION,\r
+ OID_GEN_CURRENT_PACKET_FILTER,\r
+ OID_GEN_CURRENT_LOOKAHEAD,\r
+ OID_GEN_DRIVER_VERSION,\r
+ OID_GEN_MAXIMUM_TOTAL_SIZE,\r
+ OID_GEN_PROTOCOL_OPTIONS,\r
+ OID_GEN_MAC_OPTIONS,\r
+ OID_GEN_MEDIA_CONNECT_STATUS,\r
+ OID_GEN_MAXIMUM_SEND_PACKETS,\r
+ OID_GEN_NETWORK_LAYER_ADDRESSES,\r
+ OID_GEN_VENDOR_DRIVER_VERSION,\r
+ OID_GEN_PHYSICAL_MEDIUM,\r
+ OID_GEN_XMIT_OK,\r
+ OID_GEN_RCV_OK,\r
+ OID_GEN_XMIT_ERROR,\r
+ OID_GEN_RCV_ERROR,\r
+ OID_GEN_RCV_NO_BUFFER,\r
+ OID_GEN_DIRECTED_BYTES_XMIT,\r
+ OID_GEN_DIRECTED_FRAMES_XMIT,\r
+ OID_GEN_MULTICAST_BYTES_XMIT,\r
+ OID_GEN_MULTICAST_FRAMES_XMIT,\r
+ OID_GEN_BROADCAST_BYTES_XMIT,\r
+ OID_GEN_BROADCAST_FRAMES_XMIT,\r
+ OID_GEN_DIRECTED_BYTES_RCV,\r
+ OID_GEN_DIRECTED_FRAMES_RCV,\r
+ OID_GEN_MULTICAST_BYTES_RCV,\r
+ OID_GEN_MULTICAST_FRAMES_RCV,\r
+ OID_GEN_BROADCAST_BYTES_RCV,\r
+ OID_GEN_BROADCAST_FRAMES_RCV,\r
+ OID_802_3_PERMANENT_ADDRESS,\r
+ OID_802_3_CURRENT_ADDRESS,\r
+ OID_802_3_MULTICAST_LIST,\r
+ OID_802_3_MAXIMUM_LIST_SIZE,\r
+ OID_802_3_MAC_OPTIONS,\r
+ OID_802_3_RCV_ERROR_ALIGNMENT,\r
+ OID_802_3_XMIT_ONE_COLLISION,\r
+ OID_802_3_XMIT_MORE_COLLISIONS,\r
+ OID_TCP_TASK_OFFLOAD\r
+};\r
+#endif\r
+\r
+NDIS_OID NICSupportedOidsTest[] =\r
+{\r
+ OID_GEN_SUPPORTED_LIST,\r
+ OID_GEN_HARDWARE_STATUS,\r
+ OID_GEN_MEDIA_SUPPORTED,\r
+ OID_GEN_MEDIA_IN_USE,\r
+ OID_GEN_MAXIMUM_LOOKAHEAD,\r
+ OID_GEN_MAXIMUM_FRAME_SIZE,\r
+ OID_GEN_TRANSMIT_BUFFER_SPACE,\r
+ OID_GEN_RECEIVE_BUFFER_SPACE,\r
+ OID_GEN_TRANSMIT_BLOCK_SIZE,\r
+ OID_GEN_RECEIVE_BLOCK_SIZE,\r
+ OID_GEN_VENDOR_ID,\r
+ OID_GEN_VENDOR_DESCRIPTION,\r
+ OID_GEN_VENDOR_DRIVER_VERSION,\r
+ OID_GEN_CURRENT_PACKET_FILTER,\r
+ OID_GEN_CURRENT_LOOKAHEAD,\r
+ OID_GEN_DRIVER_VERSION,\r
+ OID_GEN_MAXIMUM_TOTAL_SIZE,\r
+ OID_GEN_MAC_OPTIONS,\r
+ OID_GEN_MAXIMUM_SEND_PACKETS,\r
+ OID_GEN_XMIT_OK,\r
+ OID_GEN_RCV_OK,\r
+ OID_GEN_XMIT_ERROR,\r
+ OID_GEN_RCV_ERROR,\r
+ OID_GEN_RCV_NO_BUFFER,\r
+ OID_GEN_RCV_CRC_ERROR,\r
+ OID_GEN_TRANSMIT_QUEUE_LENGTH,\r
+ OID_802_3_PERMANENT_ADDRESS,\r
+ OID_802_3_CURRENT_ADDRESS,\r
+ OID_802_3_MULTICAST_LIST,\r
+ OID_802_3_MAXIMUM_LIST_SIZE,\r
+ OID_802_3_RCV_ERROR_ALIGNMENT,\r
+ OID_802_3_XMIT_ONE_COLLISION,\r
+ OID_802_3_XMIT_MORE_COLLISIONS,\r
+ OID_802_3_XMIT_DEFERRED,\r
+ OID_802_3_XMIT_MAX_COLLISIONS,\r
+ OID_802_3_RCV_OVERRUN,\r
+ OID_802_3_XMIT_UNDERRUN,\r
+ OID_802_3_XMIT_HEARTBEAT_FAILURE,\r
+ OID_802_3_XMIT_TIMES_CRS_LOST,\r
+ OID_802_3_XMIT_LATE_COLLISIONS,\r
+\r
+#if !BUILD_W2K\r
+ OID_GEN_PHYSICAL_MEDIUM,\r
+#endif\r
+\r
+ OID_TCP_TASK_OFFLOAD,\r
+ \r
+/* powermanagement */\r
+\r
+ OID_PNP_CAPABILITIES,\r
+ OID_PNP_SET_POWER,\r
+ OID_PNP_QUERY_POWER,\r
+ OID_PNP_ADD_WAKE_UP_PATTERN,\r
+ OID_PNP_REMOVE_WAKE_UP_PATTERN,\r
+ OID_PNP_ENABLE_WAKE_UP,\r
+\r
+\r
+/* custom oid WMI support */\r
+// OID_CUSTOM_PERF_COUNTERS,\r
+ // OID_CUSTOM_STRING,\r
+\r
+ OID_GEN_RECEIVE_SCALE_CAPABILITIES,\r
+ OID_GEN_RECEIVE_SCALE_PARAMETERS,\r
+\r
+//\r
+// new and required for NDIS 6 miniports\r
+//\r
+ OID_GEN_LINK_PARAMETERS,\r
+ OID_GEN_INTERRUPT_MODERATION,\r
+ OID_GEN_STATISTICS,\r
+\r
+/* Offload */\r
+ OID_TCP_OFFLOAD_CURRENT_CONFIG,\r
+ OID_TCP_OFFLOAD_PARAMETERS,\r
+ OID_TCP_OFFLOAD_HARDWARE_CAPABILITIES,\r
+ OID_OFFLOAD_ENCAPSULATION,\r
+\r
+/* Header - Data seperation */\r
+ // OID_GEN_HD_SPLIT_PARAMETERS,\r
+ // OID_GEN_HD_SPLIT_CURRENT_CONFIG,\r
+ \r
+/* VLAN */\r
+ // OID_ADD_VALN_ID,\r
+ // OID_DELETE_VLAN_ID,\r
+\r
+/* Set MAC */\r
+ // OID_SET_MAC_ADDRESS\r
+\r
+};\r
+\r
+static const NDIS_OID SUPPORTED_OIDS[] =\r
+{\r
+ OID_GEN_SUPPORTED_LIST,\r
+ OID_GEN_HARDWARE_STATUS,\r
+ OID_GEN_MEDIA_SUPPORTED,\r
+ OID_GEN_MEDIA_IN_USE,\r
+ OID_GEN_MAXIMUM_LOOKAHEAD,\r
+ OID_GEN_MAXIMUM_FRAME_SIZE,\r
+ OID_GEN_TRANSMIT_BUFFER_SPACE,\r
+ OID_GEN_RECEIVE_BUFFER_SPACE,\r
+ OID_GEN_TRANSMIT_BLOCK_SIZE,\r
+ OID_GEN_RECEIVE_BLOCK_SIZE,\r
+ OID_GEN_VENDOR_ID,\r
+ OID_GEN_VENDOR_DESCRIPTION,\r
+ OID_GEN_VENDOR_DRIVER_VERSION,\r
+ OID_GEN_CURRENT_PACKET_FILTER,\r
+ OID_GEN_CURRENT_LOOKAHEAD,\r
+ OID_GEN_DRIVER_VERSION,\r
+ OID_GEN_MAXIMUM_TOTAL_SIZE,\r
+ OID_GEN_MAC_OPTIONS,\r
+ OID_GEN_MAXIMUM_SEND_PACKETS,\r
+ OID_GEN_XMIT_OK,\r
+ OID_GEN_RCV_OK,\r
+ OID_GEN_XMIT_ERROR,\r
+ OID_GEN_RCV_ERROR,\r
+ OID_GEN_RCV_NO_BUFFER,\r
+ OID_GEN_RCV_CRC_ERROR,\r
+ OID_GEN_TRANSMIT_QUEUE_LENGTH,\r
+ OID_802_3_PERMANENT_ADDRESS,\r
+ OID_802_3_CURRENT_ADDRESS,\r
+ OID_802_3_MULTICAST_LIST,\r
+ OID_802_3_MAXIMUM_LIST_SIZE,\r
+ OID_802_3_RCV_ERROR_ALIGNMENT,\r
+ OID_802_3_XMIT_ONE_COLLISION,\r
+ OID_802_3_XMIT_MORE_COLLISIONS,\r
+ OID_802_3_XMIT_DEFERRED,\r
+ OID_802_3_XMIT_MAX_COLLISIONS,\r
+ OID_802_3_RCV_OVERRUN,\r
+ OID_802_3_XMIT_UNDERRUN,\r
+ OID_802_3_XMIT_HEARTBEAT_FAILURE,\r
+ OID_802_3_XMIT_TIMES_CRS_LOST,\r
+ OID_802_3_XMIT_LATE_COLLISIONS,\r
+\r
+#if !BUILD_W2K\r
+ OID_GEN_PHYSICAL_MEDIUM,\r
+#endif\r
+\r
+ OID_TCP_TASK_OFFLOAD,\r
+ \r
+/* powermanagement */\r
+\r
+ OID_PNP_CAPABILITIES,\r
+ OID_PNP_SET_POWER,\r
+ OID_PNP_QUERY_POWER,\r
+ OID_PNP_ADD_WAKE_UP_PATTERN,\r
+ OID_PNP_REMOVE_WAKE_UP_PATTERN,\r
+ OID_PNP_ENABLE_WAKE_UP,\r
+\r
+#if 0\r
+/* custom oid WMI support */\r
+ OID_CUSTOM_PERF_COUNTERS,\r
+ OID_CUSTOM_STRING,\r
+#endif\r
+\r
+ OID_GEN_RECEIVE_SCALE_CAPABILITIES,\r
+ OID_GEN_RECEIVE_SCALE_PARAMETERS,\r
+ \r
+\r
+//\r
+// new and required for NDIS 6 miniports\r
+//\r
+ OID_GEN_LINK_PARAMETERS,\r
+ OID_GEN_INTERRUPT_MODERATION,\r
+ OID_GEN_STATISTICS,\r
+\r
+/* Offload */\r
+ OID_TCP_OFFLOAD_CURRENT_CONFIG,\r
+ OID_TCP_OFFLOAD_PARAMETERS,\r
+ OID_TCP_OFFLOAD_HARDWARE_CAPABILITIES,\r
+ OID_OFFLOAD_ENCAPSULATION,\r
+ \r
+#if 0\r
+\r
+/* Header - Data seperation */\r
+ OID_GEN_HD_SPLIT_PARAMETERS,\r
+ OID_GEN_HD_SPLIT_CURRENT_CONFIG,\r
+\r
+/* VLAN */\r
+ OID_ADD_VALN_ID,\r
+ OID_DELETE_VLAN_ID,\r
+\r
+\r
+/* Set MAC */\r
+ OID_SET_MAC_ADDRESS\r
+#endif\r
+\r
+};\r
+\r
+static const unsigned char VENDOR_ID[] = {0x00, 0x06, 0x6A, 0x00};\r
+\r
+#define VENDOR_DESCRIPTION "Internet Protocol over InfiniBand"\r
+\r
+#define IB_INFINITE_SERVICE_LEASE 0xFFFFFFFF\r
+\r
+//The mask is 8 bit and can't contain more than 6 non-zero bits\r
+#define MAX_GUID_MAX 0xFC\r
+\r
+\r
+/* Global driver debug level */\r
+uint32_t g_ipoib_dbg_level = TRACE_LEVEL_ERROR;\r
+uint32_t g_ipoib_dbg_flags = 0x00000fff;\r
+ipoib_globals_t g_ipoib = {0};\r
+NDIS_HANDLE g_IpoibMiniportDriverHandle = NULL;\r
+NDIS_HANDLE g_IpoibDriverContext = NULL;\r
+\r
+\r
+\r
+typedef struct _IPOIB_REG_ENTRY\r
+{\r
+ NDIS_STRING RegName; // variable name text\r
+ BOOLEAN bRequired; // 1 -> required, 0 -> optional\r
+ UINT FieldOffset; // offset in parent struct\r
+ UINT FieldSize; // size (in bytes) of the field\r
+ UINT Default; // default value to use\r
+ UINT Min; // minimum value allowed\r
+ UINT Max; // maximum value allowed\r
+} IPOIB_REG_ENTRY, *PIPOIB_REG_ENTRY;\r
+\r
+IPOIB_REG_ENTRY HCARegTable[] = {\r
+ // reg value name If Required Offset in parentr struct Field size Default Min Max\r
+ {NDIS_STRING_CONST("GUIDMask"), 0, IPOIB_OFFSET(guid_mask), IPOIB_SIZE(guid_mask), 0, 0, MAX_GUID_MAX},\r
+ /* GUIDMask should be the first element */\r
+ {NDIS_STRING_CONST("RqDepth"), 1, IPOIB_OFFSET(rq_depth), IPOIB_SIZE(rq_depth), 512, 128, 1024},\r
+ {NDIS_STRING_CONST("RqLowWatermark"), 0, IPOIB_OFFSET(rq_low_watermark), IPOIB_SIZE(rq_low_watermark), 4, 2, 8},\r
+ {NDIS_STRING_CONST("SqDepth"), 1, IPOIB_OFFSET(sq_depth), IPOIB_SIZE(sq_depth), 512, 128, 1024},\r
+ {NDIS_STRING_CONST("SendChksum"), 1, IPOIB_OFFSET(send_chksum_offload), IPOIB_SIZE(send_chksum_offload),CSUM_ENABLED,CSUM_DISABLED,CSUM_BYPASS},\r
+ {NDIS_STRING_CONST("RecvChksum"), 1, IPOIB_OFFSET(recv_chksum_offload), IPOIB_SIZE(recv_chksum_offload),CSUM_ENABLED,CSUM_DISABLED,CSUM_BYPASS},\r
+ {NDIS_STRING_CONST("SaTimeout"), 1, IPOIB_OFFSET(sa_timeout), IPOIB_SIZE(sa_timeout), 1000, 250, UINT_MAX},\r
+ {NDIS_STRING_CONST("SaRetries"), 1, IPOIB_OFFSET(sa_retry_cnt), IPOIB_SIZE(sa_retry_cnt), 10, 1, UINT_MAX},\r
+ {NDIS_STRING_CONST("RecvRatio"), 1, IPOIB_OFFSET(recv_pool_ratio), IPOIB_SIZE(recv_pool_ratio), 1, 1, 10},\r
+ {NDIS_STRING_CONST("PayloadMtu"), 1, IPOIB_OFFSET(payload_mtu), IPOIB_SIZE(payload_mtu), 2044, 512, MAX_UD_PAYLOAD_MTU},\r
+ {NDIS_STRING_CONST("lso"), 0, IPOIB_OFFSET(lso), IPOIB_SIZE(lso), 0, 0, 1},\r
+ {NDIS_STRING_CONST("MCLeaveRescan"), 1, IPOIB_OFFSET(mc_leave_rescan), IPOIB_SIZE(mc_leave_rescan), 260, 1, 3600},\r
+ {NDIS_STRING_CONST("BCJoinRetry"), 1, IPOIB_OFFSET(bc_join_retry), IPOIB_SIZE(bc_join_retry), 50, 0, 1000},\r
+ {NDIS_STRING_CONST("CmEnabled"), 0, IPOIB_OFFSET(cm_enabled), IPOIB_SIZE(cm_enabled), FALSE, FALSE, TRUE},\r
+ {NDIS_STRING_CONST("CmPayloadMtu"), 1, IPOIB_OFFSET(cm_payload_mtu), IPOIB_SIZE(cm_payload_mtu), MAX_CM_PAYLOAD_MTU, 512, MAX_CM_PAYLOAD_MTU}\r
+\r
+}; \r
+\r
+#define IPOIB_NUM_REG_PARAMS (sizeof (HCARegTable) / sizeof(IPOIB_REG_ENTRY))\r
+\r
+\r
+void\r
+ipoib_create_log(\r
+ NDIS_HANDLE h_adapter,\r
+ UINT ind,\r
+ ULONG eventLogMsgId)\r
+\r
+{\r
+#define cMaxStrLen 40\r
+#define cArrLen 3\r
+\r
+ PWCHAR logMsgArray[cArrLen]; \r
+ WCHAR strVal[cMaxStrLen];\r
+ NDIS_STRING AdapterInstanceName;\r
+\r
+ IPOIB_INIT_NDIS_STRING(&AdapterInstanceName);\r
+ if (NdisMQueryAdapterInstanceName(&AdapterInstanceName, h_adapter)!= NDIS_STATUS_SUCCESS ){\r
+ ASSERT(FALSE);\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR,IPOIB_DBG_ERROR, ("[IPoIB] Init:Failed to retreive adapter name.\n"));\r
+ return;\r
+ }\r
+ logMsgArray[0] = AdapterInstanceName.Buffer;\r
+ \r
+ if (RtlStringCbPrintfW(strVal, sizeof(strVal), L"0x%x", HCARegTable[ind].Default) != STATUS_SUCCESS) {\r
+ ASSERT(FALSE);\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR,IPOIB_DBG_ERROR,\r
+ ("[IPoIB] Init: Problem copying string value: exiting\n")); \r
+ return;\r
+ }\r
+ \r
+ logMsgArray[0] = AdapterInstanceName.Buffer;\r
+ logMsgArray[1] = HCARegTable[ind].RegName.Buffer;\r
+ logMsgArray[2] = strVal;\r
+ \r
+ NdisWriteEventLogEntry(g_p_drv_obj, eventLogMsgId, 0, cArrLen, &logMsgArray, 0, NULL);\r
+\r
+}\r
+\r
+\r
+extern "C"\r
+NTSTATUS\r
+DriverEntry(\r
+ IN PDRIVER_OBJECT p_drv_obj,\r
+ IN PUNICODE_STRING p_reg_path );\r
+\r
+VOID\r
+ipoib_unload(\r
+ IN PDRIVER_OBJECT p_drv_obj );\r
+\r
+NDIS_STATUS\r
+ipoib_initialize_ex(\r
+ IN NDIS_HANDLE h_adapter,\r
+ IN NDIS_HANDLE config_context,\r
+ IN PNDIS_MINIPORT_INIT_PARAMETERS MiniportInitParameters);\r
+\r
+NDIS_STATUS \r
+MPInitializeTest(\r
+ IN NDIS_HANDLE MiniportAdapterHandle,\r
+ IN NDIS_HANDLE MiniportDriverContext,\r
+ IN PNDIS_MINIPORT_INIT_PARAMETERS MiniportInitParameters\r
+ );\r
+\r
+\r
+\r
+BOOLEAN\r
+ipoib_check_for_hang(\r
+ IN NDIS_HANDLE adapter_context );\r
+\r
+void\r
+ipoib_halt_ex(\r
+ IN NDIS_HANDLE adapter_context,\r
+ IN NDIS_HALT_ACTION HaltAction);\r
+\r
+NDIS_STATUS\r
+ipoib_query_info(\r
+ IN NDIS_HANDLE adapter_context,\r
+ IN NDIS_OID oid,\r
+ IN PVOID info_buf,\r
+ IN ULONG info_buf_len,\r
+ OUT PULONG p_bytes_written,\r
+ OUT PULONG p_bytes_needed );\r
+\r
+\r
+\r
+NDIS_STATUS\r
+ipoib_reset(\r
+ IN NDIS_HANDLE adapter_context,\r
+ OUT PBOOLEAN p_addr_reset);\r
+\r
+NDIS_STATUS\r
+ipoib_set_info(\r
+ IN NDIS_HANDLE adapter_context,\r
+ IN NDIS_OID oid,\r
+ IN PVOID info_buf,\r
+ IN ULONG info_buf_length,\r
+ OUT PULONG p_bytes_read,\r
+ OUT PULONG p_bytes_needed );\r
+\r
+//NDIS60\r
+void\r
+ipoib_send_net_buffer_list(\r
+ IN NDIS_HANDLE adapter_context,\r
+ IN PNET_BUFFER_LIST net_buffer_list,\r
+ IN NDIS_PORT_NUMBER port_num,\r
+ IN ULONG send_flags);\r
+\r
+void\r
+ipoib_pnp_notify(\r
+ IN NDIS_HANDLE adapter_context,\r
+ IN PNET_DEVICE_PNP_EVENT pnp_event);\r
+\r
+VOID\r
+ipoib_shutdown_ex(\r
+ IN NDIS_HANDLE adapter_context,\r
+ IN NDIS_SHUTDOWN_ACTION shutdown_action);\r
+\r
+\r
+void\r
+ipoib_cancel_xmit(\r
+ IN NDIS_HANDLE adapter_context,\r
+ IN PVOID cancel_id );\r
+\r
+\r
+static void\r
+ipoib_complete_query(\r
+ IN ipoib_adapter_t* const p_adapter,\r
+ IN pending_oid_t* const p_oid_info,\r
+ IN const NDIS_STATUS status,\r
+ IN const void* const p_buf,\r
+ IN const ULONG buf_len );\r
+\r
+static NDIS_STATUS\r
+__ipoib_set_net_addr(\r
+ IN ipoib_adapter_t * p_adapter,\r
+ IN PVOID info_buf,\r
+ IN ULONG info_buf_len,\r
+ OUT PULONG p_bytes_read,\r
+ OUT PULONG p_bytes_needed );\r
+\r
+static NDIS_STATUS\r
+__ipoib_get_tcp_task_offload(\r
+ IN ipoib_adapter_t* p_adapter,\r
+ OUT pending_oid_t *pNdisRequest);\r
+\r
+static void\r
+__ipoib_ats_reg_cb(\r
+ IN ib_reg_svc_rec_t *p_reg_svc_rec );\r
+\r
+static void\r
+__ipoib_ats_dereg_cb(\r
+ IN void *context );\r
+\r
+static NTSTATUS\r
+__ipoib_read_registry(\r
+ IN UNICODE_STRING* const p_registry_path );\r
+\r
+static NDIS_STATUS\r
+ipoib_set_options(\r
+ IN NDIS_HANDLE NdisMiniportDriverHandle,\r
+ IN NDIS_HANDLE MiniportDriverContext);\r
+\r
+static NDIS_STATUS\r
+ipoib_oid_handler(\r
+ IN NDIS_HANDLE adapter_context,\r
+ IN PNDIS_OID_REQUEST pNdisRequest);\r
+\r
+static void\r
+ipoib_cancel_oid_request(\r
+ IN NDIS_HANDLE adapter_context,\r
+ IN PVOID requestId);\r
+ \r
+static NDIS_STATUS \r
+ipoib_pause(\r
+ IN NDIS_HANDLE adapter_context, \r
+ IN PNDIS_MINIPORT_PAUSE_PARAMETERS pause_parameters);\r
+\r
+static NDIS_STATUS \r
+ipoib_restart(\r
+ IN NDIS_HANDLE adapter_context, \r
+ IN PNDIS_MINIPORT_RESTART_PARAMETERS restart_parameters);\r
+\r
+\r
+\r
+//! Standard Windows Device Driver Entry Point\r
+/*! DriverEntry is the first routine called after a driver is loaded, and\r
+is responsible for initializing the driver. On W2k this occurs when the PnP\r
+Manager matched a PnP ID to one in an INF file that references this driver.\r
+Any not success return value will cause the driver to fail to load.\r
+IRQL = PASSIVE_LEVEL\r
+\r
+@param p_drv_obj Pointer to Driver Object for this device driver\r
+@param p_registry_path Pointer to unicode string containing path to this driver's registry area\r
+@return STATUS_SUCCESS, NDIS_STATUS_BAD_CHARACTERISTICS, NDIS_STATUS_BAD_VERSION,\r
+NDIS_STATUS_RESOURCES, or NDIS_STATUS_FAILURE\r
+*/\r
+extern "C" \r
+NTSTATUS\r
+DriverEntry(\r
+ IN PDRIVER_OBJECT p_drv_obj,\r
+ IN PUNICODE_STRING p_registry_path )\r
+{\r
+ NDIS_STATUS status;\r
+ NDIS_MINIPORT_DRIVER_CHARACTERISTICS characteristics;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+ g_p_drv_obj = p_drv_obj;\r
+\r
+#ifdef _DEBUG_\r
+ PAGED_CODE();\r
+#endif\r
+#if defined(EVENT_TRACING)\r
+ WPP_INIT_TRACING(p_drv_obj, p_registry_path);\r
+#endif\r
+ status = CL_INIT;\r
+ if( !NT_SUCCESS( status ) )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("cl_init failed.\n") );\r
+ return status;\r
+ }\r
+\r
+ __ipoib_read_registry(p_registry_path);\r
+ \r
+ KeInitializeSpinLock( &g_ipoib.lock );\r
+ cl_qlist_init( &g_ipoib.adapter_list );\r
+\r
+ NdisZeroMemory(&characteristics, sizeof(characteristics));\r
+\r
+ characteristics.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_DRIVER_CHARACTERISTICS,\r
+ characteristics.Header.Size = sizeof(NDIS_MINIPORT_DRIVER_CHARACTERISTICS);\r
+ characteristics.Header.Revision = NDIS_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_1;\r
+\r
+ characteristics.MajorNdisVersion = MAJOR_NDIS_VERSION;\r
+ characteristics.MinorNdisVersion = MINOR_NDIS_VERSION;\r
+ characteristics.MajorDriverVersion = MAJOR_DRIVER_VERSION;\r
+ characteristics.MinorDriverVersion = MINOR_DRIVER_VERSION;\r
+\r
+\r
+ characteristics.CheckForHangHandlerEx = ipoib_check_for_hang;\r
+ characteristics.HaltHandlerEx = ipoib_halt_ex;\r
+ characteristics.InitializeHandlerEx = ipoib_initialize_ex;// MPInitializeTest\r
+ characteristics.OidRequestHandler = ipoib_oid_handler;\r
+ characteristics.CancelOidRequestHandler = ipoib_cancel_oid_request;\r
+ characteristics.ResetHandlerEx = ipoib_reset;\r
+ characteristics.DevicePnPEventNotifyHandler = ipoib_pnp_notify;\r
+ characteristics.ReturnNetBufferListsHandler = ipoib_return_net_buffer_list;\r
+ characteristics.SendNetBufferListsHandler = ipoib_send_net_buffer_list;\r
+\r
+ characteristics.SetOptionsHandler = ipoib_set_options;\r
+ characteristics.PauseHandler = ipoib_pause;\r
+ characteristics.RestartHandler = ipoib_restart;\r
+ characteristics.UnloadHandler = ipoib_unload;\r
+ characteristics.CancelSendHandler = ipoib_cancel_xmit;\r
+ characteristics.ShutdownHandlerEx = ipoib_shutdown_ex;\r
+\r
+\r
+\r
+//TODO NDIS60 set g_ prefix to global variables\r
+ status = NdisMRegisterMiniportDriver(\r
+ p_drv_obj, p_registry_path,(PNDIS_HANDLE)&g_IpoibDriverContext, &characteristics,&g_IpoibMiniportDriverHandle );\r
+ if( status != NDIS_STATUS_SUCCESS )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, \r
+ ("NdisMRegisterMiniportDriver failed with status of %d\n", status) );\r
+ CL_DEINIT;\r
+ }\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+ return status;\r
+}\r
+\r
+static NDIS_STATUS\r
+ipoib_set_options(\r
+ IN NDIS_HANDLE NdisMiniportDriverHandle,\r
+ IN NDIS_HANDLE MiniportDriverContext\r
+ )\r
+{\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+ UNREFERENCED_PARAMETER(NdisMiniportDriverHandle);\r
+ UNREFERENCED_PARAMETER(MiniportDriverContext);\r
+ \r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+ return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+static NTSTATUS\r
+__ipoib_read_registry(\r
+ IN UNICODE_STRING* const p_registry_path )\r
+{\r
+ NTSTATUS status;\r
+ /* Remember the terminating entry in the table below. */\r
+ RTL_QUERY_REGISTRY_TABLE table[4];\r
+ UNICODE_STRING param_path;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+ RtlInitUnicodeString( ¶m_path, NULL );\r
+ param_path.MaximumLength = p_registry_path->Length + \r
+ sizeof(L"\\Parameters");\r
+ param_path.Buffer = (PWCH) cl_zalloc( param_path.MaximumLength );\r
+ if( !param_path.Buffer )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, \r
+ ("Failed to allocate parameters path buffer.\n") );\r
+ return STATUS_INSUFFICIENT_RESOURCES;\r
+ }\r
+\r
+ RtlAppendUnicodeStringToString( ¶m_path, p_registry_path );\r
+ RtlAppendUnicodeToString( ¶m_path, L"\\Parameters" );\r
+\r
+ /*\r
+ * Clear the table. This clears all the query callback pointers,\r
+ * and sets up the terminating table entry.\r
+ */\r
+ cl_memclr( table, sizeof(table) );\r
+\r
+ /* Setup the table entries. */\r
+ table[0].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
+ table[0].Name = L"DebugLevel";\r
+ table[0].EntryContext = &g_ipoib_dbg_level;\r
+ table[0].DefaultType = REG_DWORD;\r
+ table[0].DefaultData = &g_ipoib_dbg_level;\r
+ table[0].DefaultLength = sizeof(ULONG);\r
+\r
+ table[1].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
+ table[1].Name = L"DebugFlags";\r
+ table[1].EntryContext = &g_ipoib_dbg_flags;\r
+ table[1].DefaultType = REG_DWORD;\r
+ table[1].DefaultData = &g_ipoib_dbg_flags;\r
+ table[1].DefaultLength = sizeof(ULONG);\r
+\r
+ table[2].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
+ table[2].Name = L"bypass_check_bcast_rate";\r
+ table[2].EntryContext = &g_ipoib.bypass_check_bcast_rate;\r
+ table[2].DefaultType = REG_DWORD;\r
+ table[2].DefaultData = &g_ipoib.bypass_check_bcast_rate;\r
+ table[2].DefaultLength = sizeof(ULONG);\r
+\r
+ /* Have at it! */\r
+ status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE, \r
+ param_path.Buffer, table, NULL, NULL );\r
+\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("debug level %d debug flags 0x%.8x\n",\r
+ g_ipoib_dbg_level,\r
+ g_ipoib_dbg_flags));\r
+\r
+#if DBG\r
+ if( g_ipoib_dbg_flags & IPOIB_DBG_ERR )\r
+ g_ipoib_dbg_flags |= CL_DBG_ERROR;\r
+#endif\r
+\r
+ cl_free( param_path.Buffer );\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+ return status;\r
+}\r
+\r
+\r
+VOID\r
+ipoib_unload(\r
+ IN PDRIVER_OBJECT p_drv_obj )\r
+{\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+ UNREFERENCED_PARAMETER(p_drv_obj);\r
+ #if defined(EVENT_TRACING)\r
+ WPP_CLEANUP(p_drv_obj);\r
+ #endif\r
+ //NDIS6.0\r
+ NdisMDeregisterMiniportDriver(g_IpoibMiniportDriverHandle);\r
+ UNREFERENCED_PARAMETER( p_drv_obj );\r
+ CL_DEINIT;\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+\r
+NDIS_STATUS\r
+ipoib_get_adapter_params(\r
+ IN OUT ipoib_adapter_t *p_adapter,\r
+ OUT PUCHAR *p_mac,\r
+ OUT UINT *p_len)\r
+{\r
+ NDIS_STATUS status;\r
+ NDIS_HANDLE h_config;\r
+ NDIS_CONFIGURATION_OBJECT config_obj;\r
+ NDIS_CONFIGURATION_PARAMETER *p_param;\r
+ UINT value;\r
+ PIPOIB_REG_ENTRY pRegEntry;\r
+ UINT i;\r
+ PUCHAR structPointer;\r
+ \r
+ int sq_depth_step = 128;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+ config_obj.Header.Type = NDIS_OBJECT_TYPE_CONFIGURATION_OBJECT;\r
+ config_obj.Header.Revision = NDIS_CONFIGURATION_OBJECT_REVISION_1;\r
+ config_obj.Header.Size = sizeof(NDIS_CONFIGURATION_OBJECT);\r
+ config_obj.NdisHandle = p_adapter->h_adapter;\r
+ config_obj.Flags = 0;\r
+\r
+ status = NdisOpenConfigurationEx( &config_obj, &h_config);\r
+ if( status != NDIS_STATUS_SUCCESS )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("NdisOpenConfigurationEx returned 0x%.8x\n", status) );\r
+ return status;\r
+ }\r
+\r
+ // read all the registry values \r
+ for (i = 0, pRegEntry = HCARegTable; i < IPOIB_NUM_REG_PARAMS; ++i)\r
+ {\r
+ // initialize pointer to appropriate place inside 'params'\r
+ structPointer = (PUCHAR) &p_adapter->params + pRegEntry[i].FieldOffset;\r
+\r
+ // Get the configuration value for a specific parameter. Under NT the\r
+ // parameters are all read in as DWORDs.\r
+ NdisReadConfiguration(\r
+ &status,\r
+ &p_param,\r
+ h_config,\r
+ &pRegEntry[i].RegName,\r
+ NdisParameterInteger);\r
+\r
+ // If the parameter was present, then check its value for validity.\r
+ if (status == NDIS_STATUS_SUCCESS)\r
+ {\r
+ // Check that param value is not too small or too large\r
+ if (p_param->ParameterData.IntegerData < pRegEntry[i].Min ||\r
+ p_param->ParameterData.IntegerData > pRegEntry[i].Max)\r
+ {\r
+ value = pRegEntry[i].Default;\r
+ ipoib_create_log(p_adapter->h_adapter, i, EVENT_IPOIB_WRONG_PARAMETER_WRN);\r
+ 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)); \r
+\r
+ }\r
+ else\r
+ {\r
+ value = p_param->ParameterData.IntegerData;\r
+ IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_INIT, ("Read configuration. Registry %S, Value= 0x%x\n", pRegEntry[i].RegName.Buffer, value));\r
+ }\r
+ }\r
+\r
+ else\r
+ {\r
+ value = pRegEntry[i].Default;\r
+ status = NDIS_STATUS_SUCCESS;\r
+ if (pRegEntry[i].bRequired)\r
+ {\r
+ ipoib_create_log(p_adapter->h_adapter, i, EVENT_IPOIB_WRONG_PARAMETER_ERR);\r
+ 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));\r
+ }\r
+ else\r
+ {\r
+ ipoib_create_log(p_adapter->h_adapter, i, EVENT_IPOIB_WRONG_PARAMETER_INFO);\r
+ IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_INIT, ("Read configuration. Registry %S value not found, Value= 0x%x\n", pRegEntry[i].RegName.Buffer, value));\r
+ }\r
+\r
+ }\r
+ //\r
+ // Store the value in the adapter structure.\r
+ //\r
+ switch(pRegEntry[i].FieldSize)\r
+ {\r
+ case 1:\r
+ *((PUCHAR) structPointer) = (UCHAR) value;\r
+ break;\r
+\r
+ case 2:\r
+ *((PUSHORT) structPointer) = (USHORT) value;\r
+ break;\r
+\r
+ case 4:\r
+ *((PULONG) structPointer) = (ULONG) value;\r
+ break;\r
+\r
+ default:\r
+ IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, ("Bogus field size %d\n", pRegEntry[i].FieldSize));\r
+ break;\r
+ }\r
+ }\r
+\r
+ // Send queue depth needs to be a power of two\r
+ //static const INT sq_depth_step = 128;\r
+\r
+ if (p_adapter->params.sq_depth % sq_depth_step) {\r
+ static const c_sq_ind = 2;\r
+ p_adapter->params.sq_depth = sq_depth_step *(\r
+ p_adapter->params.sq_depth / sq_depth_step + !!( (p_adapter->params.sq_depth % sq_depth_step) > (sq_depth_step/2) ));\r
+ ipoib_create_log(p_adapter->h_adapter, c_sq_ind, EVENT_IPOIB_WRONG_PARAMETER_WRN);\r
+ 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 ));\r
+\r
+ }\r
+\r
+\r
+ // Adjusting the low watermark parameter\r
+ p_adapter->params.rq_low_watermark =\r
+ p_adapter->params.rq_depth / p_adapter->params.rq_low_watermark;\r
+ \r
+ /* disable CM if LSO is active */\r
+ if( p_adapter->params.cm_enabled )\r
+ {\r
+ p_adapter->params.cm_enabled = !p_adapter->params.lso;\r
+ if( !p_adapter->params.cm_enabled )\r
+ {\r
+ NdisWriteErrorLogEntry( p_adapter->h_adapter,\r
+ EVENT_IPOIB_CONNECTED_MODE_ERR, 1, 0xbadc0de0 );\r
+ }\r
+ }\r
+\r
+ if( p_adapter->params.cm_enabled )\r
+ {\r
+ p_adapter->params.cm_xfer_block_size = \r
+ (sizeof(eth_hdr_t) + p_adapter->params.cm_payload_mtu);\r
+ }\r
+\r
+ p_adapter->params.xfer_block_size = \r
+ (sizeof(eth_hdr_t) + p_adapter->params.payload_mtu);\r
+\r
+ NdisReadNetworkAddress( &status, (PVOID *) p_mac, p_len, h_config );\r
+\r
+ NdisCloseConfiguration( h_config );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+ return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+\r
+NDIS_STATUS\r
+ipoib_get_adapter_guids(\r
+ IN NDIS_HANDLE* const h_adapter,\r
+ IN OUT ipoib_adapter_t *p_adapter )\r
+{\r
+ NTSTATUS status;\r
+ ib_al_ifc_data_t data;\r
+ IO_STACK_LOCATION io_stack, *p_fwd_io_stack;\r
+ DEVICE_OBJECT *p_pdo;\r
+ IRP *p_irp;\r
+ KEVENT event;\r
+ IO_STATUS_BLOCK io_status;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+ NdisMGetDeviceProperty( h_adapter, &p_pdo, NULL, NULL, NULL, NULL );\r
+\r
+ /* Query for our interface */\r
+ data.size = sizeof(ipoib_ifc_data_t);\r
+ data.version = IPOIB_INTERFACE_DATA_VERSION;\r
+ data.type = &GUID_IPOIB_INTERFACE_DATA;\r
+ data.p_data = &p_adapter->guids;\r
+\r
+ io_stack.MinorFunction = IRP_MN_QUERY_INTERFACE;\r
+ io_stack.Parameters.QueryInterface.Version = AL_INTERFACE_VERSION;\r
+ io_stack.Parameters.QueryInterface.Size = sizeof(ib_al_ifc_t);\r
+ io_stack.Parameters.QueryInterface.Interface =\r
+ (INTERFACE*)p_adapter->p_ifc;\r
+ io_stack.Parameters.QueryInterface.InterfaceSpecificData = &data;\r
+ io_stack.Parameters.QueryInterface.InterfaceType = \r
+ &GUID_IB_AL_INTERFACE;\r
+\r
+ KeInitializeEvent( &event, NotificationEvent, FALSE );\r
+\r
+ /* Build the IRP for the HCA. */\r
+ p_irp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP, p_pdo,\r
+ NULL, 0, NULL, &event, &io_status );\r
+ if( !p_irp )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed to allocate query interface IRP.\n") );\r
+ return STATUS_INSUFFICIENT_RESOURCES;\r
+ }\r
+\r
+ /* Copy the request query parameters. */\r
+ p_fwd_io_stack = IoGetNextIrpStackLocation( p_irp );\r
+ p_fwd_io_stack->MinorFunction = IRP_MN_QUERY_INTERFACE;\r
+ p_fwd_io_stack->Parameters.QueryInterface =\r
+ io_stack.Parameters.QueryInterface;\r
+ p_irp->IoStatus.Status = STATUS_NOT_SUPPORTED;\r
+\r
+ /* Send the IRP. */\r
+ status = IoCallDriver( p_pdo, p_irp );\r
+ if( status == STATUS_PENDING )\r
+ {\r
+ KeWaitForSingleObject( &event, Executive, KernelMode,\r
+ FALSE, NULL );\r
+ status = io_status.Status;\r
+ }\r
+\r
+ if( !NT_SUCCESS( status ) )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Query interface for IPOIB interface returned %08x.\n", status) );\r
+ return status;\r
+ }\r
+\r
+ /*\r
+ * Dereference the interface now so that the bus driver doesn't fail a\r
+ * query remove IRP. We will always get unloaded before the bus driver\r
+ * since we're a child device.\r
+ */\r
+ if (p_adapter->p_ifc)\r
+ p_adapter->p_ifc->wdm.InterfaceDereference(\r
+ p_adapter->p_ifc->wdm.Context );\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+ return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+\r
+//! Initialization function called for each IOC discovered\r
+/* The MiniportInitialize function is a required function that sets up a\r
+NIC (or virtual NIC) for network I/O operations, claims all hardware\r
+resources necessary to the NIC in the registry, and allocates resources\r
+the driver needs to carry out network I/O operations.\r
+IRQL = PASSIVE_LEVEL\r
+\r
+@param p_open_status Pointer to a status field set if this function returns NDIS_STATUS_OPEN_ERROR\r
+@param p_selected_medium_index Pointer to unsigned integer noting index into medium_array for this NIC\r
+@param medium_array Array of mediums for this NIC\r
+@param medium_array_size Number of elements in medium_array\r
+@param h_adapter Handle assigned by NDIS for this NIC\r
+@param wrapper_config_context Handle used for Ndis initialization functions\r
+@return NDIS_STATUS_SUCCESS, NDIS_STATUS_UNSUPPORTED_MEDIA, NDIS_STATUS_RESOURCES,\r
+NDIS_STATUS_NOT_SUPPORTED \r
+*/\r
+\r
+/*void foo1(int i)\r
+{\r
+ char temp[5200];\r
+ if (i ==0) return;\r
+ cl_msg_out("i = %d\n", i);\r
+ foo1(i-1);\r
+ \r
+}*/\r
+ \r
+NDIS_STATUS\r
+SetDeviceRegistrationAttributes(\r
+ ipoib_adapter_t *p_adapter,\r
+ NDIS_HANDLE h_adapter\r
+ )\r
+{\r
+ NDIS_MINIPORT_ADD_DEVICE_REGISTRATION_ATTRIBUTES atr;\r
+ NTSTATUS Status;\r
+\r
+ NdisZeroMemory(&atr, sizeof(NDIS_MINIPORT_ADD_DEVICE_REGISTRATION_ATTRIBUTES));\r
+\r
+ //\r
+ // setting registration attributes\r
+ //\r
+ atr.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADD_DEVICE_REGISTRATION_ATTRIBUTES;\r
+ atr.Header.Revision = NDIS_MINIPORT_ADD_DEVICE_REGISTRATION_ATTRIBUTES_REVISION_1;\r
+ atr.Header.Size = NDIS_SIZEOF_MINIPORT_ADD_DEVICE_REGISTRATION_ATTRIBUTES_REVISION_1;\r
+\r
+\r
+ atr.MiniportAddDeviceContext = (NDIS_HANDLE)p_adapter;\r
+ atr.Flags = 0; \r
+\r
+ Status = NdisMSetMiniportAttributes(h_adapter,\r
+ (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&atr);\r
+\r
+ return Status;\r
+}\r
+\r
+//NDIS 6.1\r
+#if 0\r
+NDIS_STATUS\r
+SetHardwareAssistAttributes(\r
+ ipoib_adapter_t *p_adapter,\r
+ NDIS_HANDLE h_adapter\r
+ )\r
+{\r
+ NDIS_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES atr;\r
+ NTSTATUS Status;\r
+\r
+ NdisZeroMemory(&atr, sizeof(NDIS_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES));\r
+\r
+ //\r
+ // setting registration attributes\r
+ //\r
+ atr.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES;\r
+ atr.Header.Revision = NDIS_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES_REVISION_1;\r
+ atr.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES_REVISION_1;\r
+\r
+ NDIS_HD_SPLIT_ATTRIBUTES nhsa;\r
+ NdisZeroMemory(&nhsa, sizeof(nhsa));\r
+\r
+ nhsa.Header.Type = NDIS_OBJECT_TYPE_HD_SPLIT_ATTRIBUTES;\r
+ nhsa.Header.Revision = NDIS_OFFLOAD_REVISION_1;\r
+ nhsa.Header.Size = NDIS_SIZEOF_HD_SPLIT_ATTRIBUTES_REVISION_1;\r
+\r
+ // BUGBUG: We are just cheating here ...\r
+ nhsa.HardwareCapabilities = NDIS_HD_SPLIT_CAPS_SUPPORTS_HEADER_DATA_SPLIT;\r
+#if 0\r
+ ... Only supported on B0\r
+\r
+ NDIS_HD_SPLIT_CAPS_SUPPORTS_IPV4_OPTIONS |\r
+ NDIS_HD_SPLIT_CAPS_SUPPORTS_IPV6_EXTENSION_HEADERS |\r
+ NDIS_HD_SPLIT_CAPS_SUPPORTS_TCP_OPTIONS;\r
+#endif\r
+\r
+ // The bellow should be left zero\r
+ if (pPort->Config.HeaderDataSplit) {\r
+ nhsa.CurrentCapabilities = NDIS_HD_SPLIT_CAPS_SUPPORTS_HEADER_DATA_SPLIT;\r
+ } else {\r
+ nhsa.CurrentCapabilities = 0;\r
+ }\r
+\r
+ nhsa.HDSplitFlags = 0;\r
+ nhsa.BackfillSize = 0;\r
+ nhsa.MaxHeaderSize = 0; \r
+\r
+ atr.HDSplitAttributes = &nhsa;\r
+\r
+ Status = NdisMSetMiniportAttributes(h_adapter,\r
+ (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&atr);\r
+\r
+ if (nhsa.HDSplitFlags & NDIS_HD_SPLIT_ENABLE_HEADER_DATA_SPLIT) {\r
+ ASSERT(pPort->Config.HeaderDataSplit == TRUE);\r
+ pPort->Config.HeaderDataSplit = TRUE;\r
+ } \r
+ else {\r
+ ASSERT(pPort->Config.HeaderDataSplit == FALSE);\r
+ pPort->Config.HeaderDataSplit = FALSE;\r
+ }\r
+\r
+ return Status;\r
+}\r
+#endif\r
+\r
+/*++\r
+Routine Description:\r
+ the routine sets attributes that are associated with a miniport adapter.\r
+\r
+Arguments:\r
+ pPort - Pointer to port object\r
+\r
+Return Value:\r
+ NDIS_STATUS\r
+\r
+Note:\r
+ Should be called in PASSIVE_LEVEL\r
+ \r
+--*/\r
+NDIS_STATUS\r
+SetAdapterRegistrationAttributes(\r
+ ipoib_adapter_t *p_adapter,\r
+ NDIS_HANDLE h_adapter\r
+ )\r
+ {\r
+ NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES atr;\r
+ NTSTATUS Status;\r
+\r
+ NdisZeroMemory(&atr, sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES));\r
+\r
+ /* setting registration attributes */\r
+\r
+ atr.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES;\r
+ atr.Header.Revision = NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;\r
+ atr.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;\r
+ //TODO NDIS60 Port or adapter\r
+ atr.MiniportAdapterContext = (NDIS_HANDLE)p_adapter; //(NDIS_HANDLE)pPort->p_adapter;\r
+ atr.AttributeFlags = NDIS_MINIPORT_ATTRIBUTES_BUS_MASTER;\r
+ atr.CheckForHangTimeInSeconds = 10;\r
+ atr.InterfaceType = NdisInterfacePci ; // ???? UH\r
+ //TODO NDIS60 PNP or PCI ?\r
+ //RegistrationAttributes.InterfaceType = NdisInterfacePNPBus;\r
+\r
+ Status = NdisMSetMiniportAttributes(h_adapter,\r
+ (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&atr);\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/*++\r
+Routine Description:\r
+ the routine sets generic attributes that are associated with a miniport \r
+ adapter.\r
+\r
+Arguments:\r
+ pPort - Pointer to port object\r
+\r
+Return Value:\r
+ NDIS_STATUS\r
+\r
+Note:\r
+ Should be called in PASSIVE_LEVEL\r
+ \r
+--*/\r
+NDIS_STATUS\r
+SetGenericAttributes(\r
+ ipoib_adapter_t *p_adapter,\r
+ NDIS_HANDLE h_adapter\r
+ )\r
+{\r
+ NDIS_STATUS Status;\r
+\r
+ NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES gat;\r
+ NdisZeroMemory(&gat, sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES));\r
+\r
+ /* set up generic attributes */\r
+\r
+ gat.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES;\r
+ gat.Header.Revision = NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1;\r
+ gat.Header.Size = sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES);\r
+\r
+ gat.MediaType = NdisMedium802_3; \r
+ gat.MaxXmitLinkSpeed = IPOIB_MEDIA_MAX_SPEED;\r
+ gat.MaxRcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED;\r
+ gat.XmitLinkSpeed = IPOIB_MEDIA_MAX_SPEED; //TODO NDIS60 NDIS_LINK_SPEED_UNKNOWN\r
+ gat.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED; // TODO NDIS60 NDIS_LINK_SPEED_UNKNOWN ???\r
+\r
+ gat.MediaConnectState = MediaConnectStateConnected; //TODO NDIS60 Check the current state\r
+ gat.MediaDuplexState = MediaDuplexStateFull;\r
+\r
+ gat.MtuSize = MAX_IB_MTU;\r
+ gat.LookaheadSize = MAX_XFER_BLOCK_SIZE;\r
+ gat.MacOptions = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | \r
+ NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |\r
+ NDIS_MAC_OPTION_NO_LOOPBACK |\r
+ NDIS_MAC_OPTION_FULL_DUPLEX;\r
+ //NDIS_MAC_OPTION_8021P_PRIORITY; //TODO NDIS60\r
+ // DT: Enable for Header Data Split WHQL\r
+ // | NDIS_MAC_OPTION_8021Q_VLAN;\r
+\r
+ gat.SupportedPacketFilters = NDIS_PACKET_TYPE_DIRECTED |\r
+ NDIS_PACKET_TYPE_MULTICAST |\r
+ //NDIS_PACKET_TYPE_ALL_MULTICAST |\r
+ NDIS_PACKET_TYPE_BROADCAST;\r
+ \r
+ gat.MaxMulticastListSize = MAX_MCAST;\r
+\r
+ gat.MacAddressLength = HW_ADDR_LEN;\r
+ \r
+ NdisMoveMemory(gat.PermanentMacAddress,\r
+ p_adapter->mac.addr,\r
+ HW_ADDR_LEN);\r
+\r
+ NdisMoveMemory(gat.CurrentMacAddress,\r
+ p_adapter->params.conf_mac.addr,\r
+ HW_ADDR_LEN);\r
+\r
+\r
+ gat.PhysicalMediumType = NdisPhysicalMedium802_3;\r
+ gat.AccessType = NET_IF_ACCESS_BROADCAST; \r
+\r
+ gat.SupportedOidList = (PNDIS_OID)SUPPORTED_OIDS;\r
+ gat.SupportedOidListLength = sizeof(SUPPORTED_OIDS);\r
+\r
+\r
+ gat.DirectionType = NET_IF_DIRECTION_SENDRECEIVE; \r
+ gat.ConnectionType = NET_IF_CONNECTION_DEDICATED; \r
+ gat.IfType = IF_TYPE_ETHERNET_CSMACD; \r
+ gat.IfConnectorPresent = TRUE; \r
+ //TODO NDIS60 This value is absent for ETH driver\r
+ gat.AccessType = NET_IF_ACCESS_BROADCAST; // NET_IF_ACCESS_BROADCAST for a typical ethernet adapter\r
+\r
+\r
+ //TODO NDIS60 is it possible to reduce unsupported statistics\r
+ gat.SupportedStatistics = \r
+ NDIS_STATISTICS_XMIT_OK_SUPPORTED |\r
+ NDIS_STATISTICS_RCV_OK_SUPPORTED |\r
+ NDIS_STATISTICS_XMIT_ERROR_SUPPORTED |\r
+ NDIS_STATISTICS_RCV_ERROR_SUPPORTED |\r
+ NDIS_STATISTICS_RCV_CRC_ERROR_SUPPORTED |\r
+ NDIS_STATISTICS_RCV_NO_BUFFER_SUPPORTED |\r
+ NDIS_STATISTICS_TRANSMIT_QUEUE_LENGTH_SUPPORTED;\r
+\r
+ //SupportedStatistics = NDIS_STATISTICS_XMIT_OK_SUPPORTED |\r
+ // NDIS_STATISTICS_GEN_STATISTICS_SUPPORTED;\r
+\r
+\r
+ //\r
+ // Set power management capabilities\r
+ //\r
+ gat.PowerManagementCapabilities = NULL;\r
+#if 0\r
+ NDIS_PNP_CAPABILITIES PowerManagementCapabilities;\r
+ NdisZeroMemory(&PowerManagementCapabilities, sizeof(NDIS_PNP_CAPABILITIES));\r
+ if (MPIsPoMgmtSupported(pPort))\r
+ {\r
+ MPFillPoMgmtCaps(pPort, &PowerManagementCapabilities, &Status, &unUsed);\r
+ ASSERT(NT_SUCCESS(Status)); \r
+ gat.PowerManagementCapabilities = &PowerManagementCapabilities;\r
+ } \r
+ else\r
+ {\r
+ \r
+ }\r
+#endif\r
+\r
+ //\r
+ // Set RSS attributes\r
+ //\r
+ gat.RecvScaleCapabilities = NULL;\r
+#if 0\r
+ NDIS_RECEIVE_SCALE_CAPABILITIES RssCapabilities;\r
+ NdisZeroMemory(&RssCapabilities, sizeof(PNDIS_RECEIVE_SCALE_CAPABILITIES));\r
+ Status = MPFillRssCapabilities(pPort, &RssCapabilities, &unUsed);\r
+ if (NT_SUCCESS(Status)) \r
+ {\r
+ gat.RecvScaleCapabilities = &RssCapabilities;\r
+ } \r
+ else\r
+ {\r
+ //\r
+ // do not fail the call because of failure to get PM caps\r
+ //\r
+ Status = NDIS_STATUS_SUCCESS;\r
+ gat.RecvScaleCapabilities = NULL;\r
+ }\r
+#endif\r
+\r
+ Status = NdisMSetMiniportAttributes(h_adapter,\r
+ (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&gat);\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/*++\r
+Routine Description:\r
+ The routine sets an NDIS_OFFLOAD structure indicates the current offload \r
+ capabilities that are provided by the miniport adapter \r
+ \r
+Arguments:\r
+ pPort - a pointer to port object\r
+ offload - reference to NDIS_OFFLOAD object that should be filled\r
+\r
+Return Value:\r
+ None.\r
+ \r
+--*/\r
+static\r
+void\r
+OffloadConfig(\r
+ ipoib_adapter_t *p_adapter,\r
+ NDIS_OFFLOAD *p_offload\r
+ )\r
+{ \r
+\r
+ ULONG ulEncapsulation = NDIS_ENCAPSULATION_IEEE_802_3 | NDIS_ENCAPSULATION_IEEE_802_3_P_AND_Q;\r
+\r
+ NdisZeroMemory(p_offload, NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_1);\r
+\r
+ p_offload->Header.Type = NDIS_OBJECT_TYPE_OFFLOAD;\r
+ p_offload->Header.Revision = NDIS_OFFLOAD_REVISION_1; // BUGBUG: do we need to support revision 2? UH 17-May-2008\r
+ p_offload->Header.Size = NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_1;\r
+\r
+ p_offload->Checksum.IPv4Transmit.Encapsulation = ulEncapsulation;\r
+ p_offload->Checksum.IPv4Transmit.IpOptionsSupported = \r
+ p_offload->Checksum.IPv4Transmit.TcpOptionsSupported = \r
+ p_offload->Checksum.IPv4Transmit.TcpChecksum = \r
+ p_offload->Checksum.IPv4Transmit.UdpChecksum = \r
+ p_offload->Checksum.IPv4Transmit.IpChecksum =!!(p_adapter->params.send_chksum_offload);\r
+\r
+ p_offload->Checksum.IPv4Receive.Encapsulation = ulEncapsulation;\r
+ p_offload->Checksum.IPv4Receive.IpOptionsSupported = \r
+ p_offload->Checksum.IPv4Receive.TcpOptionsSupported = \r
+ p_offload->Checksum.IPv4Receive.TcpChecksum = \r
+ p_offload->Checksum.IPv4Receive.UdpChecksum = \r
+ p_offload->Checksum.IPv4Receive.IpChecksum = !!(p_adapter->params.recv_chksum_offload); //TODO NDIS60\r
+\r
+\r
+ p_offload->Checksum.IPv6Transmit.Encapsulation = ulEncapsulation;\r
+ p_offload->Checksum.IPv6Transmit.IpExtensionHeadersSupported = \r
+ p_offload->Checksum.IPv6Transmit.TcpOptionsSupported =\r
+ p_offload->Checksum.IPv6Transmit.TcpChecksum = \r
+ p_offload->Checksum.IPv6Transmit.UdpChecksum = FALSE;\r
+\r
+\r
+ p_offload->Checksum.IPv6Receive.Encapsulation = ulEncapsulation;\r
+ p_offload->Checksum.IPv6Receive.IpExtensionHeadersSupported = \r
+ p_offload->Checksum.IPv6Receive.TcpOptionsSupported = \r
+ p_offload->Checksum.IPv6Receive.TcpChecksum = \r
+ p_offload->Checksum.IPv6Receive.UdpChecksum = FALSE;\r
+\r
+ if (p_adapter->params.lso)\r
+ {\r
+ p_offload->LsoV1.IPv4.Encapsulation = ulEncapsulation;\r
+ p_offload->LsoV1.IPv4.MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE;\r
+#define LSO_MIN_SEG_COUNT 2\r
+ p_offload->LsoV1.IPv4.MinSegmentCount = LSO_MIN_SEG_COUNT;\r
+ \r
+ \r
+ p_offload->LsoV1.IPv4.TcpOptions = NDIS_OFFLOAD_SUPPORTED;\r
+ p_offload->LsoV1.IPv4.IpOptions = NDIS_OFFLOAD_SUPPORTED;\r
+\r
+ p_offload->LsoV2.IPv4.Encapsulation = ulEncapsulation;\r
+ p_offload->LsoV2.IPv4.MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE;\r
+ p_offload->LsoV2.IPv4.MinSegmentCount = LSO_MIN_SEG_COUNT;\r
+\r
+ p_offload->LsoV2.IPv6.Encapsulation = ulEncapsulation;\r
+ p_offload->LsoV2.IPv6.MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE;\r
+ p_offload->LsoV2.IPv6.MinSegmentCount = LSO_MIN_SEG_COUNT;\r
+\r
+ p_offload->LsoV2.IPv6.IpExtensionHeadersSupported = NDIS_OFFLOAD_NOT_SUPPORTED;\r
+ p_offload->LsoV2.IPv6.TcpOptionsSupported = NDIS_OFFLOAD_SUPPORTED;\r
+ }\r
+\r
+}\r
+\r
+\r
+/*++\r
+Routine Description:\r
+ The routine sets an NDIS_OFFLOAD structure that indicates all the task \r
+ offload capabilites that are supported by the NIC. These capabilities include\r
+ capabilities that are currently disabled by standardized keywords in the registry. \r
+ \r
+Arguments:\r
+ offload - reference to NDIS_OFFLOAD object that should be filled\r
+\r
+Return Value:\r
+ None.\r
+ \r
+--*/\r
+static\r
+void\r
+OffloadCapabilities(\r
+ NDIS_OFFLOAD *p_offload\r
+ )\r
+{ \r
+ ULONG ulEncapsulation = NDIS_ENCAPSULATION_IEEE_802_3 | NDIS_ENCAPSULATION_IEEE_802_3_P_AND_Q ;\r
+ NdisZeroMemory(p_offload, NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_1); \r
+\r
+ p_offload->Header.Type = NDIS_OBJECT_TYPE_OFFLOAD;\r
+ p_offload->Header.Revision = NDIS_OFFLOAD_REVISION_1; // BUGBUG: do we need to support revision 2? UH 17-May-2008\r
+ p_offload->Header.Size = NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_1;\r
+\r
+ p_offload->Checksum.IPv4Transmit.Encapsulation = ulEncapsulation;\r
+ p_offload->Checksum.IPv4Transmit.IpOptionsSupported = TRUE;\r
+ p_offload->Checksum.IPv4Transmit.TcpOptionsSupported = TRUE;\r
+ p_offload->Checksum.IPv4Transmit.TcpChecksum = TRUE;\r
+ p_offload->Checksum.IPv4Transmit.UdpChecksum = TRUE;\r
+ p_offload->Checksum.IPv4Transmit.IpChecksum = TRUE;\r
+\r
+ p_offload->Checksum.IPv4Receive.Encapsulation = ulEncapsulation;\r
+ p_offload->Checksum.IPv4Receive.IpOptionsSupported = TRUE;\r
+ p_offload->Checksum.IPv4Receive.TcpOptionsSupported = TRUE;\r
+ p_offload->Checksum.IPv4Receive.TcpChecksum = TRUE;\r
+ p_offload->Checksum.IPv4Receive.UdpChecksum = TRUE; \r
+ p_offload->Checksum.IPv4Receive.IpChecksum = TRUE;\r
+\r
+\r
+ //\r
+ // BUGBUG::\r
+ // During a HW bug that didn't handle correctly packets with \r
+ // IPv6 Extension Headers -> we set IpExtensionHeadersSupported to TRUE\r
+ //\r
+ p_offload->Checksum.IPv6Transmit.Encapsulation = ulEncapsulation;\r
+ p_offload->Checksum.IPv6Transmit.IpExtensionHeadersSupported = TRUE;\r
+ p_offload->Checksum.IPv6Transmit.TcpOptionsSupported = TRUE;\r
+ p_offload->Checksum.IPv6Transmit.TcpChecksum = TRUE;\r
+ p_offload->Checksum.IPv6Transmit.UdpChecksum = TRUE;\r
+\r
+\r
+ p_offload->Checksum.IPv6Receive.Encapsulation = ulEncapsulation;\r
+ p_offload->Checksum.IPv6Receive.IpExtensionHeadersSupported = TRUE;\r
+ p_offload->Checksum.IPv6Receive.TcpOptionsSupported = TRUE;\r
+ p_offload->Checksum.IPv6Receive.TcpChecksum = TRUE;\r
+ p_offload->Checksum.IPv6Receive.UdpChecksum = TRUE;\r
+\r
+ p_offload->LsoV1.IPv4.Encapsulation = ulEncapsulation;\r
+ p_offload->LsoV1.IPv4.MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE;\r
+ p_offload->LsoV1.IPv4.MinSegmentCount = 2;\r
+ p_offload->LsoV1.IPv4.TcpOptions = NDIS_OFFLOAD_SUPPORTED;\r
+ p_offload->LsoV1.IPv4.IpOptions = NDIS_OFFLOAD_SUPPORTED;\r
+\r
+ p_offload->LsoV2.IPv4.Encapsulation = ulEncapsulation;\r
+ p_offload->LsoV2.IPv4.MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE;\r
+ p_offload->LsoV2.IPv4.MinSegmentCount = 2;\r
+\r
+ p_offload->LsoV2.IPv6.Encapsulation = ulEncapsulation;\r
+ p_offload->LsoV2.IPv6.MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE;\r
+ p_offload->LsoV2.IPv6.MinSegmentCount = 2;\r
+\r
+ p_offload->LsoV2.IPv6.IpExtensionHeadersSupported = NDIS_OFFLOAD_NOT_SUPPORTED;\r
+ p_offload->LsoV2.IPv6.TcpOptionsSupported = NDIS_OFFLOAD_SUPPORTED;\r
+\r
+ }\r
+\r
+\r
+/*++\r
+Routine Description:\r
+ The routine sets offload attributes that are associated with a miniport \r
+ adapter.\r
+\r
+Arguments:\r
+ pPort - Pointer to port object\r
+\r
+Return Value:\r
+ NDIS_STATUS\r
+\r
+Note:\r
+ Should be called in PASSIVE_LEVEL\r
+ \r
+--*/\r
+NDIS_STATUS\r
+SetOffloadAttributes(\r
+ ipoib_adapter_t *p_adapter,\r
+ NDIS_HANDLE h_adapter\r
+ )\r
+{\r
+ NDIS_STATUS Status;\r
+ NDIS_OFFLOAD offload,hwOffload;\r
+ //ULONG ulEncapsulation = NDIS_ENCAPSULATION_IEEE_802_3 | NDIS_ENCAPSULATION_IEEE_802_3_P_AND_Q;\r
+\r
+ NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES oat; \r
+ NdisZeroMemory(&oat, sizeof(NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES));\r
+\r
+ oat.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES;\r
+ oat.Header.Revision = NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES_REVISION_1;\r
+ oat.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES_REVISION_1;\r
+\r
+\r
+ OffloadConfig(p_adapter, &offload);\r
+\r
+\r
+ OffloadCapabilities(&hwOffload);\r
+\r
+ oat.DefaultOffloadConfiguration = &offload;\r
+ oat.HardwareOffloadCapabilities = &hwOffload;\r
+\r
+ Status = NdisMSetMiniportAttributes(h_adapter,\r
+ (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&oat);\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/*++\r
+\r
+Routine Description:\r
+ An NDIS 6.0 miniport driver must call NdisMSetMiniportAttributes\r
+ at least twice. The first call is to register itself with NDIS.\r
+ The second call is to register the miniport driver's general\r
+ attributes with NDIS.\r
+\r
+ NdisMSetMiniportAttributes takes a parameter of type\r
+ NDIS_MINIPORT_ADAPTER_ATTRIBUTES, which is a union of several miniport\r
+ adapter attributes. Miniport drivers must first call\r
+ NdisMSetMiniportAttributes and pass in an\r
+ NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES structure\r
+ that contains the pointer to its own context area, attribute flags,\r
+ check-for-hang time, and interface type.\r
+\r
+ All NDIS 6.0 miniport drivers are deserialized by default.\r
+\r
+Arguments:\r
+ pPort - Pointer to port object\r
+\r
+Return Value:\r
+ NDIS_STATUS\r
+\r
+Note:\r
+ Should be called in PASSIVE_LEVEL\r
+ \r
+--*/\r
+ NDIS_STATUS\r
+ SetAttributes(\r
+ ipoib_adapter_t *p_adapter,\r
+ NDIS_HANDLE h_adapter\r
+ )\r
+ {\r
+ NTSTATUS Status;\r
+\r
+\r
+ Status = SetDeviceRegistrationAttributes(p_adapter, h_adapter);\r
+ if (Status != NDIS_STATUS_SUCCESS)\r
+ {\r
+ //ETH_PRINT(TRACE_LEVEL_ERROR, ETH_INIT, "Set device registration failed Error=0x%x\n", Status);\r
+ return Status;\r
+ }\r
+\r
+\r
+ Status = SetAdapterRegistrationAttributes(p_adapter, h_adapter);\r
+ if (Status != NDIS_STATUS_SUCCESS)\r
+ {\r
+ //ETH_PRINT(TRACE_LEVEL_ERROR, ETH_INIT, "Set adapter attributes failed Error=0x%x\n", Status);\r
+ return Status;\r
+ }\r
+\r
+ Status = SetOffloadAttributes(p_adapter, h_adapter);\r
+ if (Status != NDIS_STATUS_SUCCESS)\r
+ {\r
+ //ETH_PRINT(TRACE_LEVEL_ERROR, ETH_INIT, "Set OFFLOAD attributes failed Error=0x%x\n", Status);\r
+ return Status;\r
+ }\r
+ \r
+#if 0\r
+ if(!pPort->Config.fWHQL)\r
+ {\r
+ Status = SetHardwareAssistAttributes(pPort);\r
+ if (Status != NDIS_STATUS_SUCCESS)\r
+ {\r
+ //ETH_PRINT(TRACE_LEVEL_ERROR, ETH_INIT, "Set Hardware Assist Attributes failed Error=0x%x\n", Status);\r
+ return Status;\r
+ }\r
+ }\r
+#endif\r
+\r
+ Status = SetGenericAttributes(p_adapter, h_adapter);\r
+ if (Status != NDIS_STATUS_SUCCESS)\r
+ {\r
+ //ETH_PRINT(TRACE_LEVEL_ERROR, ETH_INIT, "Set generic attributes failed Error=0x%x\n", Status);\r
+ return Status;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+\r
+NDIS_STATUS\r
+InitNdisScatterGatherDma(\r
+ ipoib_adapter_t *p_adapter,\r
+ NDIS_HANDLE h_adapter\r
+ )\r
+{\r
+ NDIS_STATUS status;\r
+ NDIS_SG_DMA_DESCRIPTION DmaDescription;\r
+ \r
+ NdisZeroMemory(&DmaDescription, sizeof(DmaDescription));\r
+\r
+ DmaDescription.Header.Type = NDIS_OBJECT_TYPE_SG_DMA_DESCRIPTION;\r
+ DmaDescription.Header.Revision = NDIS_SG_DMA_DESCRIPTION_REVISION_1;\r
+ DmaDescription.Header.Size = sizeof(NDIS_SG_DMA_DESCRIPTION);\r
+ DmaDescription.Flags = NDIS_SG_DMA_64_BIT_ADDRESS; \r
+ //\r
+ // Even if offload is enabled, the packet size for mapping shouldn't change\r
+ //\r
+ DmaDescription.MaximumPhysicalMapping = LARGE_SEND_OFFLOAD_SIZE + LSO_MAX_HEADER;\r
+\r
+ DmaDescription.ProcessSGListHandler = ipoib_process_sg_list;\r
+ DmaDescription.SharedMemAllocateCompleteHandler = NULL;\r
+\r
+ DmaDescription.Header.Type = NDIS_OBJECT_TYPE_SG_DMA_DESCRIPTION;\r
+ DmaDescription.Header.Revision = NDIS_SG_DMA_DESCRIPTION_REVISION_1;\r
+ DmaDescription.Header.Size = sizeof(NDIS_SG_DMA_DESCRIPTION);//NDIS_SIZEOF_SG_DMA_DESCRIPTION_REVISION_1;\r
+\r
+ DmaDescription.Flags = NDIS_SG_DMA_64_BIT_ADDRESS;\r
+ //DmaDescription.MaximumPhysicalMapping = pPort->p_adapter->params.xfer_block_size;\r
+\r
+ DmaDescription.ProcessSGListHandler = ipoib_process_sg_list;\r
+ DmaDescription.SharedMemAllocateCompleteHandler = NULL;\r
+ \r
+ status = NdisMRegisterScatterGatherDma(\r
+ h_adapter,\r
+ &DmaDescription,\r
+ &p_adapter->NdisMiniportDmaHandle);\r
+\r
+ if( status != NDIS_STATUS_SUCCESS )\r
+ {\r
+ //TODO NDIS60\r
+ //ipoib_destroy_adapter( p_adapter );\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("NdisMRegisterScatterGatherDma returned 0x%.8x.\n", status) );\r
+ \r
+ }\r
+ //NDIS sets this value before it returns from NdisMRegisterScatterGatherDma. \r
+ //Miniport drivers should use this size to preallocate memory for each scatter/gather list. \r
+ p_adapter->sg_list_size = DmaDescription.ScatterGatherListSize ;\r
+ \r
+ return status;\r
+}\r
+\r
+\r
+NDIS_STATUS \r
+MPInitializeTest(\r
+ IN NDIS_HANDLE MiniportAdapterHandle,\r
+ IN NDIS_HANDLE MiniportDriverContext,\r
+ IN PNDIS_MINIPORT_INIT_PARAMETERS MiniportInitParameters\r
+ )\r
+/*++\r
+Routine Description:\r
+\r
+ MiniportInitialize handler\r
+\r
+Arguments:\r
+\r
+ MiniportAdapterHandle The handle NDIS uses to refer to us\r
+ MiniportDriverContext Handle passed to NDIS when we registered the driver\r
+ MiniportInitParameters Initialization parameters\r
+ \r
+Return Value:\r
+\r
+ NDIS_STATUS_SUCCESS unless something goes wrong\r
+\r
+--*/\r
+{\r
+\r
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;\r
+ //PMP_PORT pPort = NULL;\r
+ ipoib_adapter_t *p_adapter;\r
+// NDIS_MINIPORT_INTERRUPT_CHARACTERISTICS Interrupt;\r
+ NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES RegistrationAttributes;\r
+ NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES GeneralAttributes;\r
+ //NDIS_TIMER_CHARACTERISTICS Timer; \r
+ NDIS_PNP_CAPABILITIES PowerManagementCapabilities; \r
+ //PMP_ADAPTER Adapter = NULL;\r
+ //PVOID NetworkAddress;\r
+// UINT index;\r
+// UINT uiPnpCommandValue;\r
+// ULONG ulInfoLen;\r
+ //ULONG InterruptVersion;\r
+// LARGE_INTEGER liDueTime;\r
+ //BOOLEAN isTimerAlreadyInQueue = FALSE;\r
+// uint8_t portId;\r
+ ib_api_status_t ib_status;\r
+#if 0 \r
+#if DBG\r
+ LARGE_INTEGER TS, TD, TE;\r
+#endif\r
+#endif\r
+\r
+ cl_dbg_out ("====> MPInitialize\n");\r
+\r
+ UNREFERENCED_PARAMETER(MiniportDriverContext);\r
+ UNREFERENCED_PARAMETER(MiniportInitParameters);\r
+ \r
+\r
+\r
+ \r
+\r
+ {\r
+\r
+ ib_status = ipoib_create_adapter( MiniportAdapterHandle, &p_adapter );\r
+ if( ib_status != IB_SUCCESS )\r
+ {\r
+ ASSERT(FALSE);\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ipoib_create_adapter returned status %d.\n", ib_status ) );\r
+ return NDIS_STATUS_FAILURE;\r
+ }\r
+\r
+ \r
+\r
+ NdisZeroMemory(&RegistrationAttributes, sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES));\r
+ NdisZeroMemory(&GeneralAttributes, sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES));\r
+\r
+ //\r
+ // setting registration attributes\r
+ //\r
+ RegistrationAttributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES;\r
+ RegistrationAttributes.Header.Revision = NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;\r
+ RegistrationAttributes.Header.Size = sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES);\r
+\r
+ RegistrationAttributes.MiniportAdapterContext = (NDIS_HANDLE)p_adapter;\r
+ RegistrationAttributes.AttributeFlags = NDIS_MINIPORT_ATTRIBUTES_HARDWARE_DEVICE | \r
+ NDIS_MINIPORT_ATTRIBUTES_BUS_MASTER;\r
+ \r
+ RegistrationAttributes.CheckForHangTimeInSeconds = 2;\r
+ RegistrationAttributes.InterfaceType = NdisInterfacePci;\r
+\r
+ Status = NdisMSetMiniportAttributes(MiniportAdapterHandle,\r
+ (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&RegistrationAttributes);\r
+\r
+ if (Status != NDIS_STATUS_SUCCESS)\r
+ {\r
+ //break;\r
+ return Status;\r
+ }\r
+\r
+#if 0 \r
+ //\r
+ // Read the registry parameters\r
+ //\r
+ Status = NICReadRegParameters(Adapter);\r
+ \r
+ if (Status != NDIS_STATUS_SUCCESS) \r
+ {\r
+ break;\r
+ }\r
+\r
+ \r
+ //\r
+ // Find the physical adapter\r
+ //\r
+ Status = MpFindAdapter(Adapter, MiniportInitParameters->AllocatedResources);\r
+ if (Status != NDIS_STATUS_SUCCESS)\r
+ {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Map bus-relative IO range to system IO space\r
+ //\r
+ Status = NdisMRegisterIoPortRange(\r
+ (PVOID *)&Adapter->PortOffset,\r
+ Adapter->AdapterHandle,\r
+ Adapter->IoBaseAddress,\r
+ Adapter->IoRange);\r
+ if (Status != NDIS_STATUS_SUCCESS)\r
+ {\r
+ DBGPRINT(MP_ERROR, ("NdisMRegisterioPortRange failed\n"));\r
+ \r
+ NdisWriteErrorLogEntry(\r
+ Adapter->AdapterHandle,\r
+ NDIS_ERROR_CODE_BAD_IO_BASE_ADDRESS,\r
+ 0);\r
+ \r
+ break;\r
+ }\r
+ \r
+ //\r
+ // Read additional info from NIC such as MAC address\r
+ //\r
+ Status = NICReadAdapterInfo(Adapter);\r
+ if (Status != NDIS_STATUS_SUCCESS) \r
+ {\r
+ break;\r
+ }\r
+\r
+#endif\r
+ //\r
+ // set up generic attributes\r
+ //\r
+ \r
+\r
+ GeneralAttributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES;\r
+ GeneralAttributes.Header.Revision = NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1;\r
+ GeneralAttributes.Header.Size = sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES);\r
+\r
+ GeneralAttributes.MediaType = NdisMedium802_3;\r
+\r
+ GeneralAttributes.MtuSize = DEFAULT_MTU;\r
+#define LINE_SPEED_10_GBTS 10000000000\r
+ GeneralAttributes.MaxXmitLinkSpeed = LINE_SPEED_10_GBTS;\r
+ GeneralAttributes.MaxRcvLinkSpeed = LINE_SPEED_10_GBTS;\r
+ GeneralAttributes.XmitLinkSpeed = NDIS_LINK_SPEED_UNKNOWN;\r
+ GeneralAttributes.RcvLinkSpeed = NDIS_LINK_SPEED_UNKNOWN;\r
+ GeneralAttributes.MediaConnectState = MediaConnectStateUnknown;\r
+ GeneralAttributes.MediaDuplexState = MediaDuplexStateUnknown;\r
+ GeneralAttributes.LookaheadSize = MAX_XFER_BLOCK_SIZE;\r
+#if 0\r
+ MPFillPoMgmtCaps (Adapter, \r
+ &PowerManagementCapabilities, \r
+ &Status,\r
+ &ulInfoLen);\r
+#endif\r
+ NdisZeroMemory(&PowerManagementCapabilities, sizeof(NDIS_PNP_CAPABILITIES));\r
+ Status = NDIS_STATUS_NOT_SUPPORTED;\r
+ // ulInfoLen = 0;\r
+\r
+ if (Status == NDIS_STATUS_SUCCESS)\r
+ {\r
+ GeneralAttributes.PowerManagementCapabilities = &PowerManagementCapabilities;\r
+ }\r
+ else\r
+ {\r
+ GeneralAttributes.PowerManagementCapabilities = NULL;\r
+ }\r
+\r
+ //\r
+ // do not fail the call because of failure to get PM caps\r
+ //\r
+ Status = NDIS_STATUS_SUCCESS;\r
+\r
+ GeneralAttributes.MacOptions = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | \r
+ NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |\r
+ NDIS_MAC_OPTION_NO_LOOPBACK;\r
+\r
+ GeneralAttributes.SupportedPacketFilters = NDIS_PACKET_TYPE_DIRECTED |\r
+ NDIS_PACKET_TYPE_MULTICAST |\r
+ NDIS_PACKET_TYPE_ALL_MULTICAST |\r
+ NDIS_PACKET_TYPE_BROADCAST;\r
+ \r
+ GeneralAttributes.MaxMulticastListSize = MAX_MCAST;\r
+ GeneralAttributes.MacAddressLength = HW_ADDR_LEN;\r
+ NdisMoveMemory(GeneralAttributes.PermanentMacAddress,\r
+ p_adapter->mac.addr,\r
+ HW_ADDR_LEN);\r
+\r
+ NdisMoveMemory(GeneralAttributes.CurrentMacAddress,\r
+ p_adapter->params.conf_mac.addr,\r
+ HW_ADDR_LEN);\r
+ GeneralAttributes.RecvScaleCapabilities = NULL;\r
+ GeneralAttributes.AccessType = NET_IF_ACCESS_BROADCAST; // NET_IF_ACCESS_BROADCAST for a typical ethernet adapter\r
+ GeneralAttributes.DirectionType = NET_IF_DIRECTION_SENDRECEIVE; // NET_IF_DIRECTION_SENDRECEIVE for a typical ethernet adapter\r
+ GeneralAttributes.ConnectionType = NET_IF_CONNECTION_DEDICATED; // NET_IF_CONNECTION_DEDICATED for a typical ethernet adapter\r
+ GeneralAttributes.IfType = IF_TYPE_ETHERNET_CSMACD; // IF_TYPE_ETHERNET_CSMACD for a typical ethernet adapter (regardless of speed)\r
+ GeneralAttributes.IfConnectorPresent = TRUE; // RFC 2665 TRUE if physical adapter\r
+\r
+ GeneralAttributes.SupportedStatistics = NDIS_STATISTICS_XMIT_OK_SUPPORTED |\r
+ NDIS_STATISTICS_RCV_OK_SUPPORTED |\r
+ NDIS_STATISTICS_XMIT_ERROR_SUPPORTED |\r
+ NDIS_STATISTICS_RCV_ERROR_SUPPORTED |\r
+ NDIS_STATISTICS_RCV_CRC_ERROR_SUPPORTED |\r
+ NDIS_STATISTICS_RCV_NO_BUFFER_SUPPORTED |\r
+ NDIS_STATISTICS_TRANSMIT_QUEUE_LENGTH_SUPPORTED |\r
+ NDIS_STATISTICS_GEN_STATISTICS_SUPPORTED;\r
+ \r
+ GeneralAttributes.SupportedOidList = NICSupportedOidsTest;\r
+ GeneralAttributes.SupportedOidListLength = sizeof(NICSupportedOidsTest);\r
+\r
+ Status = NdisMSetMiniportAttributes(MiniportAdapterHandle,\r
+ (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&GeneralAttributes);\r
+\r
+\r
+#if 0 \r
+ //\r
+ // Allocate all other memory blocks including shared memory\r
+ //\r
+ Status = NICAllocAdapterMemory(Adapter);\r
+ if (Status != NDIS_STATUS_SUCCESS) \r
+ {\r
+ break;\r
+ }\r
+ //\r
+ // Init send data structures\r
+ //\r
+ NICInitSend(Adapter);\r
+\r
+ //\r
+ // Init receive data structures\r
+ //\r
+ Status = NICInitRecv(Adapter);\r
+ if (Status != NDIS_STATUS_SUCCESS)\r
+ {\r
+ break;\r
+ }\r
+ //\r
+ // Map bus-relative registers to virtual system-space\r
+ // \r
+ Status = NdisMMapIoSpace(\r
+ (PVOID *) &(Adapter->CSRAddress),\r
+ Adapter->AdapterHandle,\r
+ Adapter->MemPhysAddress,\r
+ NIC_MAP_IOSPACE_LENGTH);\r
+ if (Status != NDIS_STATUS_SUCCESS)\r
+ {\r
+ DBGPRINT(MP_ERROR, ("NdisMMapIoSpace failed\n"));\r
+ \r
+ NdisWriteErrorLogEntry(\r
+ Adapter->AdapterHandle,\r
+ NDIS_ERROR_CODE_RESOURCE_CONFLICT,\r
+ 1,\r
+ ERRLOG_MAP_IO_SPACE);\r
+ \r
+ break;\r
+ }\r
+\r
+ DBGPRINT(MP_INFO, ("CSRAddress="PTR_FORMAT"\n", Adapter->CSRAddress));\r
+\r
+ //\r
+ // Disable interrupts here which is as soon as possible\r
+ //\r
+ NICDisableInterrupt(Adapter);\r
+#endif\r
+ \r
+ //\r
+ // Register the interrupt\r
+ //\r
+ //\r
+ \r
+ //\r
+ // the embeded NDIS interrupt structure is already zero'ed out\r
+ // as part of the adapter structure\r
+ //\r
+ #if 0\r
+ NdisZeroMemory(&Interrupt, sizeof(NDIS_MINIPORT_INTERRUPT_CHARACTERISTICS));\r
+ \r
+ Interrupt.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_INTERRUPT;\r
+ Interrupt.Header.Revision = NDIS_MINIPORT_INTERRUPT_REVISION_1;\r
+ Interrupt.Header.Size = sizeof(NDIS_MINIPORT_INTERRUPT_CHARACTERISTICS);\r
+\r
+ Interrupt.InterruptHandler = MPIsr;\r
+ Interrupt.InterruptDpcHandler = MPHandleInterrupt;\r
+ Interrupt.DisableInterruptHandler = NULL;\r
+ Interrupt.EnableInterruptHandler = NULL;\r
+\r
+\r
+\r
+ Status = NdisMRegisterInterruptEx(Adapter->AdapterHandle,\r
+ Adapter,\r
+ &Interrupt,\r
+ &Adapter->NdisInterruptHandle\r
+ );\r
+ \r
+ \r
+ if (Status != NDIS_STATUS_SUCCESS)\r
+ {\r
+ DBGPRINT(MP_ERROR, ("NdisMRegisterInterrupt failed\n"));\r
+ \r
+ NdisWriteErrorLogEntry(\r
+ Adapter->AdapterHandle,\r
+ NDIS_ERROR_CODE_INTERRUPT_CONNECT,\r
+ 0);\r
+ \r
+ break;\r
+ }\r
+ \r
+ //\r
+ // If the driver support MSI\r
+ //\r
+ Adapter->InterruptType = Interrupt.InterruptType;\r
+\r
+ if (Adapter->InterruptType == NDIS_CONNECT_MESSAGE_BASED)\r
+ {\r
+ Adapter->MessageInfoTable = Interrupt.MessageInfoTable;\r
+ }\r
+ \r
+ //\r
+ // If the driver supports MSI, here it should what kind of interrupt is granted. If MSI is granted,\r
+ // the driver can check Adapter->MessageInfoTable to get MSI information\r
+ //\r
+ \r
+ \r
+ MP_SET_FLAG(Adapter, fMP_ADAPTER_INTERRUPT_IN_USE);\r
+\r
+ //\r
+ // Test our adapter hardware\r
+ //\r
+ Status = NICSelfTest(Adapter);\r
+ if (Status != NDIS_STATUS_SUCCESS)\r
+ {\r
+ break;\r
+ }\r
+ \r
+ //\r
+ // Init the hardware and set up everything\r
+ //\r
+ Status = NICInitializeAdapter(Adapter);\r
+ if (Status != NDIS_STATUS_SUCCESS)\r
+ {\r
+ break;\r
+ }\r
+ \r
+ //\r
+ // initial state is paused\r
+ //\r
+ Adapter->AdapterState = NicPaused;\r
+ \r
+ //\r
+ // Set the link detection flag\r
+ //\r
+ MP_SET_FLAG(Adapter, fMP_ADAPTER_LINK_DETECTION);\r
+ \r
+ //\r
+ // Increment the reference count so halt handler will wait \r
+ //\r
+ MP_INC_REF(Adapter); \r
+\r
+ //\r
+ // Enable the interrupt\r
+ //\r
+ NICEnableInterrupt(Adapter);\r
+\r
+ \r
+ NdisZeroMemory(&Timer, sizeof(NDIS_TIMER_CHARACTERISTICS));\r
+ \r
+ Timer.Header.Type = NDIS_OBJECT_TYPE_TIMER_CHARACTERISTICS;\r
+ Timer.Header.Revision = NDIS_TIMER_CHARACTERISTICS_REVISION_1;\r
+ Timer.Header.Size = sizeof(NDIS_TIMER_CHARACTERISTICS);\r
+\r
+ Timer.AllocationTag = NIC_TAG;\r
+ Timer.TimerFunction = MpLinkDetectionDpc;\r
+ Timer.FunctionContext = Adapter;\r
+\r
+ //\r
+ // Minimize init-time\r
+ //\r
+ Status = NdisAllocateTimerObject(\r
+ Adapter->AdapterHandle,\r
+ &Timer,\r
+ &Adapter->LinkDetectionTimerHandle);\r
+\r
+ if (Status != NDIS_STATUS_SUCCESS)\r
+ {\r
+ break;\r
+ }\r
+\r
+ liDueTime.QuadPart = NIC_LINK_DETECTION_DELAY;\r
+ isTimerAlreadyInQueue =NdisSetTimerObject(Adapter->LinkDetectionTimerHandle, liDueTime, 0, NULL);\r
+ ASSERT(!isTimerAlreadyInQueue);\r
+#endif \r
+ } \r
+#if 0\r
+ if (Adapter && (Status != NDIS_STATUS_SUCCESS))\r
+ {\r
+ //\r
+ // Undo everything if it failed\r
+ //\r
+ MP_DEC_REF(Adapter);\r
+ MpFreeAdapter(Adapter);\r
+ }\r
+\r
+ DBGPRINT_S(Status, ("<==== MPInitialize, Status=%x\n", Status));\r
+#endif\r
+ /* Create the adapter adapter */\r
+ ib_status = ipoib_start_adapter( p_adapter );\r
+ if( ib_status != IB_SUCCESS )\r
+ {\r
+ ASSERT(FALSE);\r
+\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ipoib_start_adapter returned status %d.\n", ib_status ) );\r
+ return NDIS_STATUS_FAILURE;\r
+ }\r
+ \r
+ ipoib_ref_ibat();\r
+ return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+\r
+\r
+NDIS_STATUS\r
+ipoib_initialize_ex(\r
+ IN NDIS_HANDLE h_adapter,\r
+ IN NDIS_HANDLE config_context,\r
+ IN PNDIS_MINIPORT_INIT_PARAMETERS MiniportInitParameters)\r
+ {\r
+ NDIS_STATUS status;\r
+ ib_api_status_t ib_status;\r
+ ipoib_adapter_t *p_adapter;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+ \r
+#ifdef _DEBUG_\r
+ PAGED_CODE();\r
+#endif\r
+ \r
+ UNUSED_PARAM( config_context );\r
+ UNUSED_PARAM( MiniportInitParameters );\r
+ \r
+ /* Create the adapter adapter */\r
+ ib_status = ipoib_create_adapter( h_adapter, &p_adapter );\r
+ if( ib_status != IB_SUCCESS )\r
+ {\r
+ ASSERT(FALSE);\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ipoib_create_adapter returned status %d.\n", ib_status ) );\r
+ return NDIS_STATUS_FAILURE;\r
+ }\r
+ p_adapter->ipoib_state = IPOIB_PAUSED;\r
+ status = SetAttributes(p_adapter, h_adapter);\r
+ if (status != NDIS_STATUS_SUCCESS) {\r
+ ASSERT(FALSE);\r
+ }\r
+\r
+#if IPOIB_USE_DMA\r
+ InitNdisScatterGatherDma(p_adapter, h_adapter);\r
+#endif\r
+\r
+ /* Create the adapter adapter */\r
+ ib_status = ipoib_start_adapter( p_adapter );\r
+ if( ib_status != IB_SUCCESS )\r
+ {\r
+ ASSERT(FALSE);\r
+ NdisWriteErrorLogEntry( h_adapter,\r
+ NDIS_ERROR_CODE_HARDWARE_FAILURE, 0 );\r
+#if IPOIB_USE_DMA\r
+ NdisMDeregisterScatterGatherDma(p_adapter->NdisMiniportDmaHandle);\r
+#endif\r
+ ipoib_destroy_adapter( p_adapter );\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ipoib_start_adapter returned status %d.\n", ib_status ) );\r
+ return NDIS_STATUS_FAILURE;\r
+ }\r
+ \r
+ ipoib_ref_ibat();\r
+ \r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+ return status;\r
+ }\r
+\r
+\r
+//! Deallocates resources when the NIC is removed and halts the NIC..\r
+//TODO: Dispatch or Passive ?\r
+/* IRQL = DISPATCH_LEVEL\r
+\r
+@param adapter_context The adapter context allocated at start\r
+*/\r
+void\r
+ipoib_halt_ex(\r
+ IN NDIS_HANDLE adapter_context,\r
+ IN NDIS_HALT_ACTION HaltAction )\r
+{\r
+ ipoib_adapter_t *p_adapter;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+ UNUSED_PARAM(HaltAction);\r
+//return; \r
+ ipoib_deref_ibat();\r
+\r
+ CL_ASSERT( adapter_context );\r
+ p_adapter = (ipoib_adapter_t*)adapter_context;\r
+\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+ ("Port %016I64x (CA %016I64x port %d) halting\n",\r
+ p_adapter->guids.port_guid.guid, p_adapter->guids.ca_guid,\r
+ p_adapter->guids.port_num) );\r
+\r
+#if IPOIB_USE_DMA\r
+ if (p_adapter->NdisMiniportDmaHandle != NULL)\r
+ {\r
+ NdisMDeregisterScatterGatherDma(p_adapter->NdisMiniportDmaHandle);\r
+ p_adapter->NdisMiniportDmaHandle = NULL;\r
+ }\r
+#endif\r
+ ipoib_destroy_adapter( p_adapter );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+//! Reports the state of the NIC, or monitors the responsiveness of an underlying device driver.\r
+/* IRQL = DISPATCH_LEVEL\r
+\r
+@param adapter_context The adapter context allocated at start\r
+@return TRUE if the driver determines that its NIC is not operating\r
+*/\r
+BOOLEAN\r
+ipoib_check_for_hang(\r
+ IN NDIS_HANDLE adapter_context )\r
+{\r
+ ipoib_adapter_t *p_adapter;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+//return FALSE;\r
+ CL_ASSERT( adapter_context );\r
+ p_adapter = (ipoib_adapter_t*)adapter_context;\r
+\r
+ if( p_adapter->reset )\r
+ {\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+ return FALSE;\r
+ }\r
+ if (p_adapter->hung) {\r
+ ipoib_resume_oids(p_adapter);\r
+ }\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+ return (p_adapter->hung? TRUE:FALSE);\r
+}\r
+\r
+\r
+/*++\r
+Routine Description:\r
+ The routine sets an NDIS_OFFLOAD structure indicates the current offload \r
+ capabilities that are provided by the miniport adapter \r
+\r
+Arguments:\r
+ pPort - a pointer to port object\r
+ offload - reference to NDIS_OFFLOAD object that should be filled\r
+\r
+Return Value:\r
+ None.\r
+\r
+--*/\r
+//TODO\r
+#if 0\r
+static\r
+void\r
+__ipoib_get_offload_config(\r
+ ipoib_port_t *pPort,\r
+ NDIS_OFFLOAD *p_offload\r
+ )\r
+{\r
+ NDIS_STATUS Status;\r
+ ULONG TxChksumOffload = ((MP_GET_PORT_CONFIG(pPort, TxChksumOffload) == TRUE) ? NDIS_OFFLOAD_SET_ON : NDIS_OFFLOAD_SET_OFF);\r
+ ULONG RxChksumOffload = ((MP_GET_PORT_CONFIG(pPort, RxChksumOffload) == TRUE) ? NDIS_OFFLOAD_SET_ON : NDIS_OFFLOAD_SET_OFF);\r
+ BOOLEAN fLargeSendOffload = MP_GET_PORT_CONFIG(pPort, LargeSendOffload);\r
+ ULONG ulEncapsulation = NDIS_ENCAPSULATION_IEEE_802_3 | NDIS_ENCAPSULATION_IEEE_802_3_P_AND_Q;\r
+ \r
+ NdisZeroMemory(&*p_offload, sizeof(NDIS_OFFLOAD));\r
+ *p_offload.Header.Type = NDIS_OBJECT_TYPE_OFFLOAD;\r
+ *p_offload.Header.Revision = NDIS_OFFLOAD_REVISION_1; // BUGBUG: do we need to support revision 2? UH 17-May-2008\r
+ *p_offload.Header.Size = NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_1;\r
+\r
+ *p_offload.Checksum.IPv4Transmit.Encapsulation = ulEncapsulation;\r
+ *p_offload.Checksum.IPv4Transmit.IpOptionsSupported = TxChksumOffload;\r
+ *p_offload.Checksum.IPv4Transmit.TcpOptionsSupported = TxChksumOffload;\r
+ *p_offload.Checksum.IPv4Transmit.TcpChecksum = TxChksumOffload;\r
+ *p_offload.Checksum.IPv4Transmit.UdpChecksum = NDIS_OFFLOAD_NOT_SUPPORTED;\r
+ *p_offload.Checksum.IPv4Transmit.IpChecksum = TxChksumOffload;\r
+\r
+ *p_offload.Checksum.IPv4Receive.Encapsulation = ulEncapsulation;\r
+ *p_offload.Checksum.IPv4Receive.IpOptionsSupported = RxChksumOffload;\r
+ *p_offload.Checksum.IPv4Receive.TcpOptionsSupported = RxChksumOffload;\r
+ *p_offload.Checksum.IPv4Receive.TcpChecksum = RxChksumOffload;\r
+ *p_offload.Checksum.IPv4Receive.UdpChecksum = NDIS_OFFLOAD_NOT_SUPPORTED; \r
+ *p_offload.Checksum.IPv4Receive.IpChecksum = RxChksumOffload;\r
+\r
+ *p_offload.Checksum.IPv6Transmit.Encapsulation = ulEncapsulation;\r
+ *p_offload.Checksum.IPv6Transmit.IpExtensionHeadersSupported = TxChksumOffload;\r
+ *p_offload.Checksum.IPv6Transmit.TcpOptionsSupported = TxChksumOffload;\r
+ *p_offload.Checksum.IPv6Transmit.TcpChecksum = TxChksumOffload;\r
+ *p_offload.Checksum.IPv6Transmit.UdpChecksum = NDIS_OFFLOAD_NOT_SUPPORTED;\r
+\r
+\r
+ *p_offload.Checksum.IPv6Receive.Encapsulation = ulEncapsulation;\r
+ *p_offload.Checksum.IPv6Receive.IpExtensionHeadersSupported = RxChksumOffload;\r
+ *p_offload.Checksum.IPv6Receive.TcpOptionsSupported = RxChksumOffload;\r
+ *p_offload.Checksum.IPv6Receive.TcpChecksum = RxChksumOffload;\r
+ *p_offload.Checksum.IPv6Receive.UdpChecksum = NDIS_OFFLOAD_NOT_SUPPORTED;\r
+\r
+ if (fLargeSendOffload)\r
+ {\r
+ *p_offload.LsoV1.IPv4.Encapsulation = ulEncapsulation;\r
+ *p_offload.LsoV1.IPv4.MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE;\r
+ *p_offload.LsoV1.IPv4.MinSegmentCount = 1;\r
+ *p_offload.LsoV1.IPv4.TcpOptions = NDIS_OFFLOAD_SUPPORTED;\r
+ *p_offload.LsoV1.IPv4.IpOptions = NDIS_OFFLOAD_SUPPORTED;\r
+ }\r
+}\r
+#endif\r
+\r
+//! Returns information about the capabilities and status of the driver and/or its NIC.\r
+/* IRQL = DISPATCH_LEVEL\r
+\r
+@param adapter_context The adapter context allocated at start\r
+@param oid Object ID representing the query operation to be carried out\r
+@param info_buf Buffer containing any input for this query and location for output\r
+@param info_buf_len Number of bytes available in info_buf\r
+@param p_bytes_written Pointer to number of bytes written into info_buf\r
+@param p_bytes_needed Pointer to number of bytes needed to satisfy this oid\r
+@return NDIS_STATUS_SUCCESS, NDIS_STATUS_PENDING, NDIS_STATUS_INVALID_OID,\r
+NDIS_STATUS_INVALID_LENGTH, NDIS_STATUS_NOT_ACCEPTED, NDIS_STATUS_NOT_SUPPORTED,\r
+NDIS_STATUS_RESOURCES\r
+*/\r
+ NDIS_STATUS\r
+ipoib_query_info(\r
+ IN NDIS_HANDLE adapter_context,\r
+ IN NDIS_OID oid,\r
+ IN PVOID info_buf,\r
+ IN ULONG info_buf_len,\r
+ OUT PULONG p_bytes_written,\r
+ OUT PULONG p_bytes_needed )\r
+ {\r
+ ipoib_adapter_t *p_adapter;\r
+ NDIS_STATUS status;\r
+ USHORT version;\r
+ ULONG info;\r
+ PVOID src_buf;\r
+ ULONG buf_len;\r
+ pending_oid_t oid_info;\r
+ uint8_t port_num;\r
+ \r
+ IPOIB_ENTER( IPOIB_DBG_OID );\r
+ \r
+ oid_info.oid = oid;\r
+ oid_info.p_buf = info_buf;\r
+ oid_info.buf_len = info_buf_len;\r
+ oid_info.p_bytes_used = p_bytes_written;\r
+ oid_info.p_bytes_needed = p_bytes_needed;\r
+ \r
+ CL_ASSERT( adapter_context );\r
+ p_adapter = (ipoib_adapter_t*)adapter_context;\r
+\r
+ CL_ASSERT( p_bytes_written );\r
+ CL_ASSERT( p_bytes_needed );\r
+ CL_ASSERT( !p_adapter->pending_query );\r
+ \r
+ status = NDIS_STATUS_SUCCESS;\r
+ src_buf = &info;\r
+ buf_len = sizeof(info);\r
+ \r
+ port_num = p_adapter->guids.port_num;\r
+ \r
+ switch( oid )\r
+ {\r
+ /* Required General */\r
+ case OID_GEN_SUPPORTED_LIST:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_GEN_SUPPORTED_LIST\n", port_num) );\r
+ src_buf = (PVOID)SUPPORTED_OIDS;\r
+ buf_len = sizeof(SUPPORTED_OIDS);\r
+ break;\r
+ \r
+ case OID_GEN_HARDWARE_STATUS:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_GEN_HARDWARE_STATUS\n", port_num) );\r
+ cl_obj_lock( &p_adapter->obj );\r
+ switch( p_adapter->state )\r
+ {\r
+ case IB_PNP_PORT_ADD:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d returning NdisHardwareStatusInitializing\n", port_num) );\r
+ info = NdisHardwareStatusInitializing;\r
+ break;\r
+ \r
+ case IB_PNP_PORT_ACTIVE:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d returning NdisHardwareStatusReady\n", port_num) );\r
+ info = NdisHardwareStatusReady;\r
+ break;\r
+ \r
+ default:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d returning NdisHardwareStatusNotReady\n", port_num) );\r
+ info = NdisHardwareStatusNotReady;\r
+ }\r
+ cl_obj_unlock( &p_adapter->obj );\r
+ break;\r
+ \r
+ case OID_GEN_MEDIA_SUPPORTED:\r
+ case OID_GEN_MEDIA_IN_USE:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_GEN_MEDIA_SUPPORTED "\r
+ "or OID_GEN_MEDIA_IN_USE\n", port_num) );\r
+ info = NdisMedium802_3;\r
+ break;\r
+ \r
+ case OID_GEN_MAXIMUM_FRAME_SIZE:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_GEN_MAXIMUM_FRAME_SIZE\n", port_num) );\r
+ if( p_adapter->params.cm_enabled )\r
+ {\r
+ info = p_adapter->params.cm_payload_mtu;\r
+ }\r
+ else\r
+ {\r
+ info = p_adapter->params.payload_mtu;\r
+ }\r
+ break;\r
+ \r
+ case OID_GEN_LINK_SPEED:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_GEN_LINK_SPEED\n", port_num) );\r
+ if (info_buf_len < buf_len)\r
+ {\r
+ break;\r
+ }\r
+ \r
+ cl_obj_lock( &p_adapter->obj );\r
+ switch( p_adapter->state )\r
+ {\r
+ case IB_PNP_PORT_ADD:\r
+ /* Mark the adapter as pending an OID */\r
+ p_adapter->pending_query = TRUE;\r
+ \r
+ /* Save the request parameters. */\r
+ p_adapter->query_oid = oid_info;\r
+ \r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d returning NDIS_STATUS_PENDING\n", port_num) );\r
+ status = NDIS_STATUS_PENDING;\r
+ break;\r
+ \r
+ case IB_PNP_PORT_REMOVE:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d returning NDIS_STATUS_NOT_ACCEPTED\n", port_num) );\r
+ status = NDIS_STATUS_NOT_ACCEPTED;\r
+ break;\r
+ \r
+ default:\r
+ CL_ASSERT( p_adapter->p_port );\r
+ info = p_adapter->port_rate;\r
+ break;\r
+ }\r
+ cl_obj_unlock( &p_adapter->obj );\r
+ break;\r
+ \r
+ case OID_GEN_TRANSMIT_BUFFER_SPACE:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_GEN_TRANSMIT_BUFFER_SPACE\n", port_num) );\r
+ if( p_adapter->params.cm_enabled )\r
+ info = p_adapter->params.sq_depth * p_adapter->params.cm_xfer_block_size;\r
+ else\r
+ info = p_adapter->params.sq_depth * p_adapter->params.xfer_block_size;\r
+ break;\r
+ \r
+ case OID_GEN_RECEIVE_BUFFER_SPACE:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_GEN_TRANSMIT_BUFFER_SPACE "\r
+ "or OID_GEN_RECEIVE_BUFFER_SPACE\n", port_num) );\r
+ if( p_adapter->params.cm_enabled )\r
+ info = p_adapter->params.rq_depth * p_adapter->params.cm_xfer_block_size;\r
+ else\r
+ info = p_adapter->params.rq_depth * p_adapter->params.xfer_block_size;\r
+ break;\r
+ \r
+ case OID_GEN_MAXIMUM_LOOKAHEAD:\r
+ case OID_GEN_CURRENT_LOOKAHEAD:\r
+ case OID_GEN_TRANSMIT_BLOCK_SIZE:\r
+ case OID_GEN_RECEIVE_BLOCK_SIZE:\r
+ case OID_GEN_MAXIMUM_TOTAL_SIZE:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_GEN_MAXIMUM_LOOKAHEAD "\r
+ "or OID_GEN_CURRENT_LOOKAHEAD or "\r
+ "OID_GEN_TRANSMIT_BLOCK_SIZE or "\r
+ "OID_GEN_RECEIVE_BLOCK_SIZE or "\r
+ "OID_GEN_MAXIMUM_TOTAL_SIZE\n", port_num) );\r
+ if( p_adapter->params.cm_enabled )\r
+ info = p_adapter->params.cm_xfer_block_size;\r
+ else\r
+ info = p_adapter->params.xfer_block_size;\r
+ break;\r
+ \r
+ case OID_GEN_VENDOR_ID:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_GEN_VENDOR_ID\n", port_num) );\r
+ src_buf = (void*)VENDOR_ID;\r
+ buf_len = sizeof(VENDOR_ID);\r
+ break;\r
+ \r
+ case OID_GEN_VENDOR_DESCRIPTION:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, \r
+ ("Port %d received query for OID_GEN_VENDOR_DESCRIPTION\n", port_num) );\r
+ src_buf = VENDOR_DESCRIPTION;\r
+ buf_len = sizeof(VENDOR_DESCRIPTION);\r
+ break;\r
+ \r
+ case OID_GEN_VENDOR_DRIVER_VERSION:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_GEN_VENDOR_DRIVER_VERSION\n", port_num) );\r
+ src_buf = &version;\r
+ buf_len = sizeof(version);\r
+ //TODO: Figure out what the right version is.\r
+ version = 1 << 8 | 1;\r
+ break;\r
+ \r
+ case OID_GEN_PHYSICAL_MEDIUM:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_GEN_PHYSICAL_MEDIUM\n", port_num) );\r
+ info = NdisPhysicalMediumUnspecified;\r
+ break;\r
+ \r
+ case OID_GEN_CURRENT_PACKET_FILTER:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_GEN_CURRENT_PACKET_FILTER\n", port_num) );\r
+ info = p_adapter->packet_filter;\r
+ break;\r
+ \r
+ case OID_GEN_DRIVER_VERSION:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_GEN_DRIVER_VERSION\n", port_num) );\r
+ src_buf = &version;\r
+ buf_len = sizeof(version);\r
+ version = MAJOR_NDIS_VERSION << 8 | MINOR_NDIS_VERSION;\r
+ break;\r
+ \r
+ case OID_GEN_MAC_OPTIONS:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_GEN_MAC_OPTIONS\n", port_num) );\r
+ info = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |\r
+ NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |\r
+ NDIS_MAC_OPTION_NO_LOOPBACK |\r
+ NDIS_MAC_OPTION_FULL_DUPLEX;\r
+ //TODO: Figure out if we will support priority and VLANs.\r
+ // NDIS_MAC_OPTION_8021P_PRIORITY;\r
+ //#ifdef NDIS51_MINIPORT\r
+ // info |= NDIS_MAC_OPTION_8021Q_VLAN;\r
+ //#endif\r
+ break;\r
+ \r
+ case OID_GEN_MEDIA_CONNECT_STATUS:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_GEN_MEDIA_CONNECT_STATUS\n", port_num) );\r
+ cl_obj_lock( &p_adapter->obj );\r
+ switch( p_adapter->state )\r
+ {\r
+ case IB_PNP_PORT_ADD:\r
+ case IB_PNP_PORT_INIT:\r
+ /*\r
+ * Delay reporting media state until we know whether the port is\r
+ * either up or down.\r
+ */\r
+ p_adapter->pending_query = TRUE;\r
+ p_adapter->query_oid = oid_info;\r
+ \r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d returning NDIS_STATUS_PENDING\n", port_num) );\r
+ status = NDIS_STATUS_PENDING;\r
+ break;\r
+ \r
+ case IB_PNP_PORT_ACTIVE:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d returning NdisMediaStateConnected\n", port_num) );\r
+ info = NdisMediaStateConnected;\r
+ break;\r
+ \r
+ case IB_PNP_PORT_REMOVE:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d returning NDIS_STATUS_NOT_ACCEPTED\n", port_num) );\r
+ status = NDIS_STATUS_NOT_ACCEPTED;\r
+ break;\r
+ \r
+ default:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d returning NdisMediaStateDisconnected\n", port_num) );\r
+ info = NdisMediaStateDisconnected;\r
+ }\r
+ cl_obj_unlock( &p_adapter->obj );\r
+ break;\r
+ \r
+ case OID_GEN_MAXIMUM_SEND_PACKETS:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_GEN_MAXIMUM_SEND_PACKETS\n", port_num) );\r
+ info = MINIPORT_MAX_SEND_PACKETS;\r
+ break;\r
+ \r
+ /* Required General Statistics */\r
+ case OID_GEN_STATISTICS:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_GEN_STATISTICS\n", port_num) );\r
+ src_buf = NULL; \r
+ buf_len = sizeof(NDIS_STATISTICS_INFO);\r
+ if (info_buf_len < buf_len)\r
+ {\r
+ break;\r
+ } \r
+ status = ipoib_get_gen_stat(p_adapter, &oid_info );\r
+ break;\r
+ \r
+ case OID_GEN_XMIT_OK:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_GEN_XMIT_OK\n", port_num) );\r
+ src_buf = NULL;\r
+ status = ipoib_get_send_stat( p_adapter, IP_STAT_SUCCESS, &oid_info );\r
+ break;\r
+ \r
+ case OID_GEN_RCV_OK:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_GEN_RCV_OK\n", port_num) );\r
+ src_buf = NULL;\r
+ status = ipoib_get_recv_stat( p_adapter, IP_STAT_SUCCESS, &oid_info );\r
+ break;\r
+ \r
+ case OID_GEN_XMIT_ERROR:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_GEN_XMIT_ERROR\n", port_num) );\r
+ src_buf = NULL;\r
+ status = ipoib_get_send_stat( p_adapter, IP_STAT_ERROR, &oid_info );\r
+ break;\r
+ \r
+ case OID_GEN_RCV_ERROR:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_GEN_RCV_ERROR\n", port_num) );\r
+ src_buf = NULL;\r
+ status = ipoib_get_recv_stat( p_adapter, IP_STAT_ERROR, &oid_info );\r
+ break;\r
+ \r
+ case OID_GEN_RCV_NO_BUFFER:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_GEN_RCV_NO_BUFFER\n", port_num) );\r
+ src_buf = NULL;\r
+ status = ipoib_get_recv_stat( p_adapter, IP_STAT_DROPPED, &oid_info );\r
+ break;\r
+ \r
+ case OID_GEN_DIRECTED_BYTES_XMIT:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_GEN_DIRECTED_BYTES_XMIT\n", port_num) );\r
+ src_buf = NULL;\r
+ status = ipoib_get_send_stat( p_adapter, IP_STAT_UCAST_BYTES, &oid_info );\r
+ break;\r
+ \r
+ case OID_GEN_DIRECTED_FRAMES_XMIT:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_GEN_DIRECTED_FRAMES_XMIT\n", port_num) );\r
+ src_buf = NULL;\r
+ status = ipoib_get_send_stat( p_adapter, IP_STAT_UCAST_FRAMES, &oid_info );\r
+ break;\r
+ \r
+ case OID_GEN_MULTICAST_BYTES_XMIT:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_GEN_MULTICAST_BYTES_XMIT\n", port_num) );\r
+ src_buf = NULL;\r
+ status = ipoib_get_send_stat( p_adapter, IP_STAT_MCAST_BYTES, &oid_info );\r
+ break;\r
+ \r
+ case OID_GEN_MULTICAST_FRAMES_XMIT:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_GEN_MULTICAST_FRAMES_XMIT\n", port_num) );\r
+ src_buf = NULL;\r
+ status = ipoib_get_send_stat( p_adapter, IP_STAT_MCAST_FRAMES, &oid_info );\r
+ break;\r
+ \r
+ case OID_GEN_BROADCAST_BYTES_XMIT:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_GEN_BROADCAST_BYTES_XMIT\n", port_num) );\r
+ src_buf = NULL;\r
+ status = ipoib_get_send_stat( p_adapter, IP_STAT_BCAST_BYTES, &oid_info );\r
+ break;\r
+ \r
+ case OID_GEN_BROADCAST_FRAMES_XMIT:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_GEN_BROADCAST_FRAMES_XMIT\n", port_num) );\r
+ src_buf = NULL;\r
+ status = ipoib_get_send_stat( p_adapter, IP_STAT_BCAST_FRAMES, &oid_info );\r
+ break;\r
+ \r
+ case OID_GEN_DIRECTED_BYTES_RCV:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_GEN_DIRECTED_BYTES_RCV\n", port_num) );\r
+ src_buf = NULL;\r
+ status = ipoib_get_recv_stat( p_adapter, IP_STAT_UCAST_BYTES, &oid_info );\r
+ break;\r
+ \r
+ case OID_GEN_DIRECTED_FRAMES_RCV:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_GEN_DIRECTED_FRAMES_RCV\n", port_num) );\r
+ src_buf = NULL;\r
+ status = ipoib_get_recv_stat( p_adapter, IP_STAT_UCAST_FRAMES, &oid_info );\r
+ break;\r
+ \r
+ case OID_GEN_MULTICAST_BYTES_RCV:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_GEN_MULTICAST_BYTES_RCV\n", port_num) );\r
+ src_buf = NULL;\r
+ status = ipoib_get_recv_stat( p_adapter, IP_STAT_MCAST_BYTES, &oid_info );\r
+ break;\r
+ \r
+ case OID_GEN_MULTICAST_FRAMES_RCV:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_GEN_MULTICAST_FRAMES_RCV\n", port_num) );\r
+ src_buf = NULL;\r
+ status = ipoib_get_recv_stat( p_adapter, IP_STAT_MCAST_FRAMES, &oid_info );\r
+ break;\r
+ \r
+ case OID_GEN_BROADCAST_BYTES_RCV:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_GEN_BROADCAST_BYTES_RCV\n", port_num) );\r
+ src_buf = NULL;\r
+ status = ipoib_get_recv_stat( p_adapter, IP_STAT_BCAST_BYTES, &oid_info );\r
+ break;\r
+ \r
+ case OID_GEN_BROADCAST_FRAMES_RCV:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_GEN_BROADCAST_FRAMES_RCV\n", port_num) );\r
+ src_buf = NULL;\r
+ status = ipoib_get_recv_stat( p_adapter, IP_STAT_BCAST_FRAMES, &oid_info );\r
+ break;\r
+ \r
+ /* Required Ethernet operational characteristics */\r
+ case OID_802_3_PERMANENT_ADDRESS:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_802_3_PERMANENT_ADDRESS\n", port_num) );\r
+ src_buf = &p_adapter->mac;\r
+ buf_len = sizeof(p_adapter->mac);\r
+ break;\r
+ \r
+ case OID_802_3_CURRENT_ADDRESS:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_802_3_CURRENT_ADDRESS\n", port_num) );\r
+ src_buf = &p_adapter->params.conf_mac;\r
+ buf_len = sizeof(p_adapter->params.conf_mac);\r
+ break;\r
+ \r
+ case OID_802_3_MULTICAST_LIST:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_802_3_MULTICAST_LIST\n", port_num) );\r
+ src_buf = p_adapter->mcast_array;\r
+ buf_len = p_adapter->mcast_array_size * sizeof(mac_addr_t);\r
+ break;\r
+ \r
+ case OID_802_3_MAXIMUM_LIST_SIZE:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_802_3_MAXIMUM_LIST_SIZE\n", port_num) );\r
+ info = MAX_MCAST;\r
+ break;\r
+ \r
+ case OID_802_3_MAC_OPTIONS:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_802_3_MAC_OPTIONS\n", port_num) );\r
+ info = 0;\r
+ break;\r
+ \r
+ /* Required Ethernet stats */\r
+ case OID_802_3_RCV_ERROR_ALIGNMENT:\r
+ case OID_802_3_XMIT_ONE_COLLISION:\r
+ case OID_802_3_XMIT_MORE_COLLISIONS:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_802_3_RCV_ERROR_ALIGNMENT or "\r
+ "OID_802_3_XMIT_ONE_COLLISION or "\r
+ "OID_802_3_XMIT_MORE_COLLISIONS\n", port_num) );\r
+ info = 0;\r
+ break;\r
+ \r
+ case OID_TCP_TASK_OFFLOAD:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_TCP_TASK_OFFLOAD\n", port_num) );\r
+ src_buf = NULL;\r
+ status = __ipoib_get_tcp_task_offload( p_adapter, &oid_info );\r
+ break;\r
+ \r
+ /* Optional General */\r
+ case OID_GEN_SUPPORTED_GUIDS:\r
+#ifdef NDIS51_MINIPORT\r
+ case OID_GEN_VLAN_ID:\r
+#endif\r
+ \r
+ /* Optional General Stats */\r
+ case OID_GEN_RCV_CRC_ERROR:\r
+ case OID_GEN_TRANSMIT_QUEUE_LENGTH:\r
+ \r
+ /* Optional Ethernet Stats */\r
+ case OID_802_3_XMIT_DEFERRED:\r
+ case OID_802_3_XMIT_MAX_COLLISIONS:\r
+ case OID_802_3_RCV_OVERRUN:\r
+ case OID_802_3_XMIT_UNDERRUN:\r
+ case OID_802_3_XMIT_HEARTBEAT_FAILURE:\r
+ case OID_802_3_XMIT_TIMES_CRS_LOST:\r
+ case OID_802_3_XMIT_LATE_COLLISIONS:\r
+ case OID_PNP_CAPABILITIES:\r
+ status = NDIS_STATUS_NOT_SUPPORTED;\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received an unsupported oid of 0x%.8X!\n", port_num, oid) );\r
+ break;\r
+ \r
+ case OID_GEN_PROTOCOL_OPTIONS:\r
+ case OID_GEN_NETWORK_LAYER_ADDRESSES:\r
+ case OID_GEN_TRANSPORT_HEADER_OFFSET:\r
+ case OID_PNP_ENABLE_WAKE_UP:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("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) );\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Number of OID: 0x%.8X!\n", oid) );\r
+ status = NDIS_STATUS_SUCCESS; \r
+ break;\r
+ \r
+ case OID_PNP_QUERY_POWER:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_TCP_TASK_OFFLOAD\n", port_num) );\r
+ // Status is pre-set in this routine to Success\r
+ status = NDIS_STATUS_SUCCESS; \r
+ break;\r
+ \r
+ case OID_TCP_OFFLOAD_CURRENT_CONFIG:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_PNP_QUERY_POWER\n", port_num) );\r
+ //ulBytesAvailable = ulInfoLen = sizeof(NDIS_OFFLOAD);\r
+ if (info_buf_len < sizeof(NDIS_OFFLOAD))\r
+ {\r
+ status = NDIS_STATUS_BUFFER_TOO_SHORT;\r
+ *p_bytes_needed = sizeof(NDIS_OFFLOAD) ;\r
+ break;\r
+ }\r
+ \r
+ //ipoib_offload_config(pPort, &offload);\r
+ //pInfo = &offload;\r
+ break;\r
+ \r
+ default:\r
+ status = NDIS_STATUS_INVALID_OID;\r
+ // IPOIB_PRINT( TRACE_LEVEL_ERROR,IPOIB_DBG_OID,\r
+ // ("Port %d received an invalid oid of 0x%.8X!\n", port_num, oid) );\r
+ break;\r
+ }\r
+ \r
+ /*\r
+ * Complete the request as if it was handled asynchronously to maximize\r
+ * code reuse for when we really handle the requests asynchronously.\r
+ * Note that this requires the QueryInformation entry point to always\r
+ * return NDIS_STATUS_PENDING\r
+ */\r
+ if( status != NDIS_STATUS_PENDING )\r
+ {\r
+ ipoib_complete_query(\r
+ p_adapter, &oid_info, status, src_buf, buf_len );\r
+ return status;\r
+ }\r
+ \r
+ IPOIB_EXIT( IPOIB_DBG_OID );\r
+ return NDIS_STATUS_PENDING;\r
+ }\r
+ \r
+\r
+static void\r
+ipoib_complete_query(\r
+ IN ipoib_adapter_t* const p_adapter,\r
+ IN pending_oid_t* const p_oid_info,\r
+ IN const NDIS_STATUS status,\r
+ IN const void* const p_buf,\r
+ IN const ULONG buf_len )\r
+{\r
+ NDIS_STATUS oid_status = status;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_OID );\r
+\r
+ CL_ASSERT( status != NDIS_STATUS_PENDING );\r
+\r
+ if( status == NDIS_STATUS_SUCCESS )\r
+ {\r
+ if( p_oid_info->buf_len < buf_len )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Insufficient buffer space. "\r
+ "Returning NDIS_STATUS_INVALID_LENGTH.\n") );\r
+ oid_status = NDIS_STATUS_INVALID_LENGTH;\r
+ *p_oid_info->p_bytes_needed = buf_len;\r
+ *p_oid_info->p_bytes_used = 0;\r
+ }\r
+ else if( p_oid_info->p_buf )\r
+ {\r
+ /* Only copy if we have a distinct source buffer. */\r
+ if( p_buf )\r
+ {\r
+ NdisMoveMemory( p_oid_info->p_buf, p_buf, buf_len );\r
+ *p_oid_info->p_bytes_used = buf_len;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Returning NDIS_NOT_ACCEPTED") );\r
+ oid_status = NDIS_STATUS_NOT_ACCEPTED;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ *p_oid_info->p_bytes_used = 0;\r
+ }\r
+\r
+ if (p_adapter->query_oid.p_pending_oid)\r
+ {\r
+ NdisMOidRequestComplete(p_adapter->h_adapter,p_adapter->query_oid.p_pending_oid,oid_status); \r
+ p_adapter->query_oid.p_pending_oid = NULL;\r
+ }\r
+ p_adapter->pending_query = FALSE;\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_OID );\r
+}\r
+\r
+\r
+static NDIS_STATUS\r
+__ipoib_get_tcp_task_offload(\r
+ IN ipoib_adapter_t* p_adapter,\r
+ OUT pending_oid_t *pNdisRequest )\r
+{\r
+#ifndef NDIS60_MINIPORT\r
+ NDIS_TASK_OFFLOAD_HEADER *p_offload_hdr;\r
+ NDIS_TASK_OFFLOAD *p_offload_task;\r
+ NDIS_TASK_TCP_IP_CHECKSUM *p_offload_chksum;\r
+\r
+ NDIS_TASK_TCP_LARGE_SEND *p_offload_lso;\r
+ ULONG buf_len;\r
+\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received query for OID_TCP_TASK_OFFLOAD\n",\r
+ p_adapter->guids.port_num) );\r
+\r
+ buf_len = sizeof(NDIS_TASK_OFFLOAD_HEADER) +\r
+ offsetof( NDIS_TASK_OFFLOAD, TaskBuffer ) +\r
+ sizeof(NDIS_TASK_TCP_IP_CHECKSUM) +\r
+ (p_adapter->params.lso ? \r
+ sizeof(NDIS_TASK_OFFLOAD) + sizeof(NDIS_TASK_TCP_LARGE_SEND)\r
+ : 0);\r
+\r
+ pNdisRequest->DATA.QUERY_INFORMATION.BytesNeeded = buf_len;\r
+\r
+ if( pNdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength < buf_len )\r
+ return NDIS_STATUS_INVALID_LENGTH;\r
+\r
+ p_offload_hdr = (NDIS_TASK_OFFLOAD_HEADER*)pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;\r
+ if( p_offload_hdr->Version != NDIS_TASK_OFFLOAD_VERSION )\r
+ return NDIS_STATUS_INVALID_DATA;\r
+\r
+ if( p_offload_hdr->EncapsulationFormat.Encapsulation !=\r
+ IEEE_802_3_Encapsulation )\r
+ {\r
+ return NDIS_STATUS_INVALID_DATA;\r
+ }\r
+\r
+ p_offload_hdr->OffsetFirstTask = sizeof(NDIS_TASK_OFFLOAD_HEADER);\r
+ p_offload_task = (NDIS_TASK_OFFLOAD*)(p_offload_hdr + 1);\r
+ p_offload_task->Version = NDIS_TASK_OFFLOAD_VERSION;\r
+ p_offload_task->Size = sizeof(NDIS_TASK_OFFLOAD);\r
+ p_offload_task->Task = TcpIpChecksumNdisTask;\r
+ p_offload_task->OffsetNextTask = 0;\r
+ p_offload_task->TaskBufferLength = sizeof(NDIS_TASK_TCP_IP_CHECKSUM);\r
+ p_offload_chksum =\r
+ (NDIS_TASK_TCP_IP_CHECKSUM*)p_offload_task->TaskBuffer;\r
+ \r
+ p_offload_chksum->V4Transmit.IpOptionsSupported =\r
+ p_offload_chksum->V4Transmit.TcpOptionsSupported =\r
+ p_offload_chksum->V4Transmit.TcpChecksum =\r
+ p_offload_chksum->V4Transmit.UdpChecksum =\r
+ p_offload_chksum->V4Transmit.IpChecksum =\r
+ !!(p_adapter->params.send_chksum_offload);\r
+\r
+ p_offload_chksum->V4Receive.IpOptionsSupported =\r
+ p_offload_chksum->V4Receive.TcpOptionsSupported =\r
+ p_offload_chksum->V4Receive.TcpChecksum =\r
+ p_offload_chksum->V4Receive.UdpChecksum =\r
+ p_offload_chksum->V4Receive.IpChecksum =\r
+ !!(p_adapter->params.recv_chksum_offload);\r
+\r
+ p_offload_chksum->V6Transmit.IpOptionsSupported = FALSE;\r
+ p_offload_chksum->V6Transmit.TcpOptionsSupported = FALSE;\r
+ p_offload_chksum->V6Transmit.TcpChecksum = FALSE;\r
+ p_offload_chksum->V6Transmit.UdpChecksum = FALSE;\r
+\r
+ p_offload_chksum->V6Receive.IpOptionsSupported = FALSE;\r
+ p_offload_chksum->V6Receive.TcpOptionsSupported = FALSE;\r
+ p_offload_chksum->V6Receive.TcpChecksum = FALSE;\r
+ p_offload_chksum->V6Receive.UdpChecksum = FALSE;\r
+\r
+\r
+ if (p_adapter->params.lso) {\r
+ // set the previous pointer to the correct place\r
+ p_offload_task->OffsetNextTask = FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer) +\r
+ p_offload_task->TaskBufferLength;\r
+ // set the LSO packet\r
+ p_offload_task = (PNDIS_TASK_OFFLOAD)\r
+ ((PUCHAR)p_offload_task + p_offload_task->OffsetNextTask);\r
+\r
+ p_offload_task->Version = NDIS_TASK_OFFLOAD_VERSION;\r
+ p_offload_task->Size = sizeof(NDIS_TASK_OFFLOAD);\r
+ p_offload_task->Task = TcpLargeSendNdisTask;\r
+ p_offload_task->OffsetNextTask = 0;\r
+ p_offload_task->TaskBufferLength = sizeof(NDIS_TASK_TCP_LARGE_SEND);\r
+\r
+ p_offload_lso = (PNDIS_TASK_TCP_LARGE_SEND) p_offload_task->TaskBuffer;\r
+\r
+ p_offload_lso->Version = 0;\r
+ //TODO optimal size: 60000, 64000 or 65536\r
+ //TODO LSO_MIN_SEG_COUNT to be 1\r
+ p_offload_lso->MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE; \r
+#define LSO_MIN_SEG_COUNT 2\r
+ p_offload_lso->MinSegmentCount = LSO_MIN_SEG_COUNT;\r
+ p_offload_lso->TcpOptions = TRUE;\r
+ p_offload_lso->IpOptions = TRUE;\r
+ }\r
+\r
+ pNdisRequest->DATA.QUERY_INFORMATION.BytesWritten = buf_len\r
+\r
+ return NDIS_STATUS_SUCCESS;\r
+#endif\r
+ UNUSED_PARAM(p_adapter);\r
+ UNUSED_PARAM(pNdisRequest);\r
+ return NDIS_STATUS_NOT_SUPPORTED;\r
+\r
+}\r
+\r
+\r
+static NDIS_STATUS\r
+__ipoib_set_tcp_task_offload(\r
+ IN ipoib_adapter_t* p_adapter,\r
+ IN void* const p_info_buf,\r
+ IN ULONG* const p_info_len )\r
+{\r
+#ifndef NDIS60_MINIPORT\r
+ NDIS_TASK_OFFLOAD_HEADER *p_offload_hdr;\r
+ NDIS_TASK_OFFLOAD *p_offload_task;\r
+ NDIS_TASK_TCP_IP_CHECKSUM *p_offload_chksum;\r
+\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received set for OID_TCP_TASK_OFFLOAD\n",\r
+ p_adapter->guids.port_num) );\r
+\r
+ p_offload_hdr = (NDIS_TASK_OFFLOAD_HEADER*)p_info_buf;\r
+\r
+ if( *p_info_len < sizeof(NDIS_TASK_OFFLOAD_HEADER) )\r
+ return NDIS_STATUS_INVALID_LENGTH;\r
+\r
+ if( p_offload_hdr->Version != NDIS_TASK_OFFLOAD_VERSION )\r
+ return NDIS_STATUS_INVALID_DATA;\r
+\r
+ if( p_offload_hdr->Size != sizeof(NDIS_TASK_OFFLOAD_HEADER) )\r
+ return NDIS_STATUS_INVALID_LENGTH;\r
+\r
+ if( !p_offload_hdr->OffsetFirstTask )\r
+ return NDIS_STATUS_SUCCESS;\r
+\r
+ if( p_offload_hdr->EncapsulationFormat.Encapsulation !=\r
+ IEEE_802_3_Encapsulation )\r
+ {\r
+ return NDIS_STATUS_INVALID_DATA;\r
+ }\r
+\r
+ p_offload_task = (NDIS_TASK_OFFLOAD*)\r
+ (((UCHAR*)p_offload_hdr) + p_offload_hdr->OffsetFirstTask);\r
+\r
+ if( *p_info_len < sizeof(NDIS_TASK_OFFLOAD_HEADER) +\r
+ offsetof( NDIS_TASK_OFFLOAD, TaskBuffer ) +\r
+ sizeof(NDIS_TASK_TCP_IP_CHECKSUM) )\r
+ {\r
+ return NDIS_STATUS_INVALID_LENGTH;\r
+ }\r
+\r
+ if( p_offload_task->Version != NDIS_TASK_OFFLOAD_VERSION )\r
+ return NDIS_STATUS_INVALID_DATA;\r
+ p_offload_chksum =\r
+ (NDIS_TASK_TCP_IP_CHECKSUM*)p_offload_task->TaskBuffer;\r
+\r
+ if( !p_adapter->params.send_chksum_offload &&\r
+ (p_offload_chksum->V4Transmit.IpOptionsSupported ||\r
+ p_offload_chksum->V4Transmit.TcpOptionsSupported ||\r
+ p_offload_chksum->V4Transmit.TcpChecksum ||\r
+ p_offload_chksum->V4Transmit.UdpChecksum ||\r
+ p_offload_chksum->V4Transmit.IpChecksum) )\r
+ {\r
+ return NDIS_STATUS_NOT_SUPPORTED;\r
+ }\r
+\r
+ if( !p_adapter->params.recv_chksum_offload &&\r
+ (p_offload_chksum->V4Receive.IpOptionsSupported ||\r
+ p_offload_chksum->V4Receive.TcpOptionsSupported ||\r
+ p_offload_chksum->V4Receive.TcpChecksum ||\r
+ p_offload_chksum->V4Receive.UdpChecksum ||\r
+ p_offload_chksum->V4Receive.IpChecksum) )\r
+ {\r
+ return NDIS_STATUS_NOT_SUPPORTED;\r
+ }\r
+\r
+ return NDIS_STATUS_SUCCESS;\r
+#endif \r
+ UNUSED_PARAM(p_adapter);\r
+ UNUSED_PARAM(p_info_buf);\r
+ UNUSED_PARAM(p_info_len);\r
+ return NDIS_STATUS_NOT_SUPPORTED;\r
+}\r
+\r
+\r
+//! Issues a hardware reset to the NIC and/or resets the driver's software state.\r
+/* Tear down the connection and start over again. This is only called when there is a problem.\r
+For example, if a send, query info, or set info had a time out. MiniportCheckForHang will\r
+be called first.\r
+IRQL = DISPATCH_LEVEL\r
+\r
+@param p_addr_resetPointer to BOOLLEAN that is set to TRUE if the NDIS\r
+library should call MiniportSetInformation to restore addressing information to the current values.\r
+@param adapter_context The adapter context allocated at start\r
+@return NDIS_STATUS_SUCCESS, NDIS_STATUS_PENDING, NDIS_STATUS_NOT_RESETTABLE,\r
+NDIS_STATUS_RESET_IN_PROGRESS, NDIS_STATUS_SOFT_ERRORS, NDIS_STATUS_HARD_ERRORS\r
+*/\r
+NDIS_STATUS\r
+ipoib_reset(\r
+ IN NDIS_HANDLE adapter_context,\r
+ OUT PBOOLEAN p_addr_reset)\r
+{\r
+ ipoib_adapter_t* p_adapter;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+//return NDIS_STATUS_SUCCESS;\r
+ CL_ASSERT( p_addr_reset );\r
+ CL_ASSERT( adapter_context );\r
+ p_adapter = (ipoib_adapter_t*)adapter_context;\r
+\r
+ switch( ipoib_reset_adapter( p_adapter ) )\r
+ {\r
+ case IB_NOT_DONE:\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+ return NDIS_STATUS_PENDING;\r
+\r
+ case IB_SUCCESS:\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+ *p_addr_reset = TRUE;\r
+ return NDIS_STATUS_SUCCESS;\r
+\r
+ case IB_INVALID_STATE:\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+ return NDIS_STATUS_RESET_IN_PROGRESS;\r
+\r
+ default:\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+ return NDIS_STATUS_HARD_ERRORS;\r
+ }\r
+}\r
+\r
+\r
+//! Request changes in the state information that the miniport driver maintains\r
+/* For example, this is used to set multicast addresses and the packet filter.\r
+IRQL = DISPATCH_LEVEL\r
+\r
+@param adapter_context The adapter context allocated at start\r
+@param oid Object ID representing the set operation to be carried out\r
+@param info_buf Buffer containing input for this set and location for any output\r
+@param info_buf_len Number of bytes available in info_buf\r
+@param p_bytes_read Pointer to number of bytes read from info_buf\r
+@param p_bytes_needed Pointer to number of bytes needed to satisfy this oid\r
+@return NDIS_STATUS_SUCCESS, NDIS_STATUS_PENDING, NDIS_STATUS_INVALID_OID,\r
+NDIS_STATUS_INVALID_LENGTH, NDIS_STATUS_INVALID_DATA, NDIS_STATUS_NOT_ACCEPTED,\r
+NDIS_STATUS_NOT_SUPPORTED, NDIS_STATUS_RESOURCES\r
+*/\r
+NDIS_STATUS\r
+ipoib_set_info(\r
+ IN NDIS_HANDLE adapter_context,\r
+ IN NDIS_OID oid,\r
+ IN PVOID info_buf,\r
+ IN ULONG info_buf_len,\r
+ OUT PULONG p_bytes_read,\r
+ OUT PULONG p_bytes_needed )\r
+{\r
+ ipoib_adapter_t* p_adapter;\r
+ NDIS_STATUS status;\r
+\r
+ ULONG buf_len;\r
+ uint8_t port_num;\r
+\r
+ KLOCK_QUEUE_HANDLE hdl;\r
+ \r
+ IPOIB_ENTER( IPOIB_DBG_OID );\r
+\r
+ CL_ASSERT( adapter_context );\r
+ p_adapter = (ipoib_adapter_t*)adapter_context;\r
+\r
+ CL_ASSERT( p_bytes_read );\r
+ CL_ASSERT( p_bytes_needed );\r
+ CL_ASSERT( !p_adapter->pending_set );\r
+\r
+ status = NDIS_STATUS_SUCCESS;\r
+ *p_bytes_needed = 0;\r
+ buf_len = sizeof(ULONG);\r
+\r
+ port_num = p_adapter->guids.port_num;\r
+ \r
+ cl_obj_lock( &p_adapter->obj );\r
+\r
+ if( p_adapter->state == IB_PNP_PORT_REMOVE )\r
+ {\r
+ *p_bytes_read = 0;\r
+ cl_obj_unlock( &p_adapter->obj );\r
+ return NDIS_STATUS_NOT_ACCEPTED;\r
+ }\r
+\r
+ cl_obj_unlock( &p_adapter->obj );\r
+\r
+ switch( oid )\r
+ {\r
+ /* Required General */\r
+ case OID_GEN_CURRENT_PACKET_FILTER:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received set for OID_GEN_CURRENT_PACKET_FILTER\n", port_num));\r
+ if( info_buf_len < sizeof(p_adapter->packet_filter) )\r
+ {\r
+ status = NDIS_STATUS_INVALID_LENGTH;\r
+ }\r
+ else if( !info_buf )\r
+ {\r
+ status = NDIS_STATUS_INVALID_DATA;\r
+ }\r
+ else\r
+ {\r
+ KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
+ cl_obj_lock( &p_adapter->obj );\r
+ switch( p_adapter->state )\r
+ {\r
+ case IB_PNP_PORT_ADD:\r
+ p_adapter->set_oid.oid = oid;\r
+ p_adapter->set_oid.p_buf = info_buf;\r
+ p_adapter->set_oid.buf_len = info_buf_len;\r
+ p_adapter->set_oid.p_bytes_used = p_bytes_read;\r
+ p_adapter->set_oid.p_bytes_needed = p_bytes_needed;\r
+ p_adapter->pending_set = TRUE;\r
+ status = NDIS_STATUS_PENDING;\r
+ break;\r
+\r
+ case IB_PNP_PORT_REMOVE:\r
+ status = NDIS_STATUS_NOT_ACCEPTED;\r
+ break;\r
+\r
+ default:\r
+ if( !p_adapter->packet_filter && (*(uint32_t*)info_buf) )\r
+ {\r
+ cl_qlist_insert_tail(\r
+ &g_ipoib.adapter_list, &p_adapter->entry );\r
+\r
+ /*\r
+ * Filter was zero, now non-zero. Register IP addresses\r
+ * with SA.\r
+ */\r
+ ipoib_reg_addrs( p_adapter );\r
+ }\r
+ else if( p_adapter->packet_filter && !(*(uint32_t*)info_buf) )\r
+ {\r
+ /*\r
+ * Filter was non-zero, now zero. Deregister IP addresses.\r
+ */\r
+ ipoib_dereg_addrs( p_adapter );\r
+\r
+ ASSERT( cl_qlist_count( &g_ipoib.adapter_list ) );\r
+ cl_qlist_remove_item(\r
+ &g_ipoib.adapter_list, &p_adapter->entry );\r
+ }\r
+\r
+ p_adapter->packet_filter = *(uint32_t*)info_buf;\r
+ }\r
+ cl_obj_unlock( &p_adapter->obj );\r
+ KeReleaseInStackQueuedSpinLock( &hdl );\r
+ }\r
+ break;\r
+\r
+ case OID_GEN_CURRENT_LOOKAHEAD:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received set for OID_GEN_CURRENT_LOOKAHEAD\n", port_num));\r
+ if( info_buf_len < buf_len )\r
+ status = NDIS_STATUS_INVALID_LENGTH;\r
+ break;\r
+\r
+ case OID_GEN_PROTOCOL_OPTIONS:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received set for OID_GEN_PROTOCOL_OPTIONS\n", port_num));\r
+ if( info_buf_len < buf_len )\r
+ status = NDIS_STATUS_INVALID_LENGTH;\r
+ break;\r
+\r
+ case OID_GEN_NETWORK_LAYER_ADDRESSES:\r
+ status = __ipoib_set_net_addr( p_adapter, info_buf, info_buf_len, p_bytes_read, p_bytes_needed);\r
+ break;\r
+\r
+#ifdef NDIS51_MINIPORT\r
+ case OID_GEN_MACHINE_NAME:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,\r
+ ("Port %d received set for OID_GEN_MACHINE_NAME\n", port_num) );\r
+ break;\r
+#endif\r
+\r
+ /* Required Ethernet operational characteristics */\r
+ case OID_802_3_MULTICAST_LIST:\r
+ IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,\r
+ ("Port %d received set for OID_802_3_MULTICAST_LIST\n", port_num) );\r
+ if( info_buf_len > MAX_MCAST * sizeof(mac_addr_t) )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d OID_802_3_MULTICAST_LIST - Multicast list full.\n", port_num) );\r
+ status = NDIS_STATUS_MULTICAST_FULL;\r
+ *p_bytes_needed = MAX_MCAST * sizeof(mac_addr_t);\r
+ }\r
+ else if( info_buf_len % sizeof(mac_addr_t) )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d OID_802_3_MULTICAST_LIST - Invalid input buffer.\n", port_num) );\r
+ status = NDIS_STATUS_INVALID_DATA;\r
+ }\r
+ else if( !info_buf && info_buf_len )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d OID_802_3_MULTICAST_LIST - Invalid input buffer.\n", port_num) );\r
+ status = NDIS_STATUS_INVALID_DATA;\r
+ }\r
+ else\r
+ {\r
+ ipoib_refresh_mcast( p_adapter, (mac_addr_t*)info_buf,\r
+ (uint8_t)(info_buf_len / sizeof(mac_addr_t)) );\r
+\r
+ buf_len = info_buf_len;\r
+ /*\r
+ * Note that we don't return pending. It will likely take longer\r
+ * for our SA transactions to complete than NDIS will give us\r
+ * before reseting the adapter. If an SA failure is encountered,\r
+ * the adapter will be marked as hung and we will get reset.\r
+ */\r
+ status = NDIS_STATUS_SUCCESS;\r
+ }\r
+ break;\r
+\r
+ case OID_TCP_TASK_OFFLOAD:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received set for OID_TCP_TASK_OFFLOAD\n", port_num) );\r
+\r
+ buf_len = info_buf_len;\r
+ status =\r
+ __ipoib_set_tcp_task_offload( p_adapter, info_buf, &buf_len );\r
+ break;\r
+\r
+ /* Optional General */\r
+ case OID_GEN_TRANSPORT_HEADER_OFFSET:\r
+#ifdef NDIS51_MINIPORT\r
+ case OID_GEN_RNDIS_CONFIG_PARAMETER:\r
+ case OID_GEN_VLAN_ID:\r
+#endif\r
+ status = NDIS_STATUS_NOT_SUPPORTED;\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received an unsupported oid of 0x%.8X!\n", port_num, oid));\r
+ break;\r
+\r
+ case OID_GEN_SUPPORTED_LIST:\r
+ case OID_GEN_HARDWARE_STATUS:\r
+ case OID_GEN_MEDIA_SUPPORTED:\r
+ case OID_GEN_MEDIA_IN_USE:\r
+ case OID_GEN_MAXIMUM_FRAME_SIZE:\r
+ case OID_GEN_LINK_SPEED:\r
+ case OID_GEN_TRANSMIT_BUFFER_SPACE:\r
+ case OID_GEN_RECEIVE_BUFFER_SPACE:\r
+ case OID_GEN_MAXIMUM_LOOKAHEAD:\r
+ case OID_GEN_TRANSMIT_BLOCK_SIZE:\r
+ case OID_GEN_RECEIVE_BLOCK_SIZE:\r
+ case OID_GEN_MAXIMUM_TOTAL_SIZE:\r
+ case OID_GEN_VENDOR_ID:\r
+ case OID_GEN_VENDOR_DESCRIPTION:\r
+ case OID_GEN_VENDOR_DRIVER_VERSION:\r
+ case OID_GEN_DRIVER_VERSION:\r
+ case OID_GEN_MAC_OPTIONS:\r
+ case OID_GEN_MEDIA_CONNECT_STATUS:\r
+ case OID_GEN_MAXIMUM_SEND_PACKETS:\r
+ case OID_GEN_SUPPORTED_GUIDS:\r
+ case OID_GEN_PHYSICAL_MEDIUM:\r
+ default:\r
+ status = NDIS_STATUS_INVALID_OID;\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received an invalid oid of 0x%.8X!\n", port_num, oid));\r
+ break;\r
+ }\r
+\r
+ if( status == NDIS_STATUS_SUCCESS )\r
+ {\r
+ *p_bytes_read = buf_len;\r
+ }\r
+ else\r
+ {\r
+ if( status == NDIS_STATUS_INVALID_LENGTH )\r
+ {\r
+ if ( !*p_bytes_needed )\r
+ {\r
+ *p_bytes_needed = buf_len;\r
+ }\r
+ }\r
+\r
+ *p_bytes_read = 0;\r
+ }\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_OID );\r
+ return status;\r
+}\r
+\r
+#ifdef NNN\r
+NDIS_STATUS\r
+ipoib_set_info(\r
+ ipoib_adapter_t* p_adapter,\r
+ IN PNDIS_OID_REQUEST pNdisRequest)\r
+{\r
+ NDIS_STATUS status;\r
+ NDIS_OID oid;\r
+ UINT info_buf_len;\r
+ UINT buf_len;\r
+ uint8_t port_num;\r
+ PVOID info_buf;\r
+ UINT *p_bytes_needed;\r
+ KLOCK_QUEUE_HANDLE hdl;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_OID );\r
+\r
+ oid = pNdisRequest->DATA.SET_INFORMATION.Oid;\r
+ info_buf = pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;\r
+ info_buf_len = pNdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength;\r
+ p_bytes_needed = &pNdisRequest->DATA.QUERY_INFORMATION.BytesNeeded;\r
+ status = NDIS_STATUS_SUCCESS;\r
+\r
+ buf_len = sizeof(UINT);\r
+ port_num = p_adapter->guids.port_num;\r
+\r
+ switch( oid )\r
+ {\r
+ /* Required General */\r
+ case OID_GEN_CURRENT_PACKET_FILTER:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received set for OID_GEN_CURRENT_PACKET_FILTER\n", port_num));\r
+ if( info_buf_len < sizeof(p_adapter->packet_filter) )\r
+ {\r
+ status = NDIS_STATUS_INVALID_LENGTH;\r
+ }\r
+ else if( !info_buf )\r
+ {\r
+ status = NDIS_STATUS_INVALID_DATA;\r
+ }\r
+ else\r
+ {\r
+ KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
+ cl_obj_lock( &p_adapter->obj );\r
+ switch( p_adapter->state )\r
+ {\r
+ case IB_PNP_PORT_ADD:\r
+ p_adapter->p_oid_request = pNdisRequest;\r
+ status = NDIS_STATUS_PENDING;\r
+ break;\r
+\r
+ case IB_PNP_PORT_REMOVE:\r
+ status = NDIS_STATUS_NOT_ACCEPTED;\r
+ break;\r
+\r
+ default:\r
+ if( !p_adapter->packet_filter && (*(uint32_t*)info_buf) )\r
+ {\r
+ cl_qlist_insert_tail(\r
+ &g_ipoib.adapter_list, &p_adapter->entry );\r
+\r
+ /*\r
+ * Filter was zero, now non-zero. Register IP addresses\r
+ * with SA.\r
+ */\r
+ ipoib_reg_addrs( p_adapter );\r
+ }\r
+ else if( p_adapter->packet_filter && !(*(uint32_t*)info_buf) )\r
+ {\r
+ /*\r
+ * Filter was non-zero, now zero. Deregister IP addresses.\r
+ */\r
+ ipoib_dereg_addrs( p_adapter );\r
+\r
+ ASSERT( cl_qlist_count( &g_ipoib.adapter_list ) );\r
+ cl_qlist_remove_item(\r
+ &g_ipoib.adapter_list, &p_adapter->entry );\r
+ }\r
+\r
+ p_adapter->packet_filter = *(uint32_t*)info_buf;\r
+ }\r
+ cl_obj_unlock( &p_adapter->obj );\r
+ KeReleaseInStackQueuedSpinLock( &hdl );\r
+ }\r
+ break;\r
+\r
+ case OID_GEN_CURRENT_LOOKAHEAD:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received set for OID_GEN_CURRENT_LOOKAHEAD\n", port_num));\r
+ if( info_buf_len < buf_len )\r
+ status = NDIS_STATUS_INVALID_LENGTH;\r
+ break;\r
+\r
+ case OID_GEN_PROTOCOL_OPTIONS:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received set for OID_GEN_PROTOCOL_OPTIONS\n", port_num));\r
+ if( info_buf_len < buf_len )\r
+ status = NDIS_STATUS_INVALID_LENGTH;\r
+ break;\r
+\r
+ case OID_GEN_NETWORK_LAYER_ADDRESSES:\r
+ status = __ipoib_set_net_addr( p_adapter, pNdisRequest);\r
+ break;\r
+\r
+ case OID_GEN_MACHINE_NAME:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,\r
+ ("Port %d received set for OID_GEN_MACHINE_NAME\n", port_num) );\r
+ break;\r
+\r
+\r
+ /* Required Ethernet operational characteristics */\r
+ case OID_802_3_MULTICAST_LIST:\r
+ IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,\r
+ ("Port %d received set for OID_802_3_MULTICAST_LIST\n", port_num) );\r
+ if( info_buf_len > MAX_MCAST * sizeof(mac_addr_t) )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d OID_802_3_MULTICAST_LIST - Multicast list full.\n", port_num) );\r
+ status = NDIS_STATUS_MULTICAST_FULL;\r
+ *p_bytes_needed = MAX_MCAST * sizeof(mac_addr_t);\r
+ }\r
+ else if( info_buf_len % sizeof(mac_addr_t) )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d OID_802_3_MULTICAST_LIST - Invalid input buffer.\n", port_num) );\r
+ status = NDIS_STATUS_INVALID_DATA;\r
+ }\r
+ else if( !info_buf && info_buf_len )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d OID_802_3_MULTICAST_LIST - Invalid input buffer.\n", port_num) );\r
+ status = NDIS_STATUS_INVALID_DATA;\r
+ }\r
+ else\r
+ {\r
+ ipoib_refresh_mcast( p_adapter, (mac_addr_t*)info_buf,\r
+ (uint8_t)(info_buf_len / sizeof(mac_addr_t)) );\r
+\r
+ buf_len = info_buf_len;\r
+ /*\r
+ * Note that we don't return pending. It will likely take longer\r
+ * for our SA transactions to complete than NDIS will give us\r
+ * before reseting the adapter. If an SA failure is encountered,\r
+ * the adapter will be marked as hung and we will get reset.\r
+ */\r
+ status = NDIS_STATUS_SUCCESS;\r
+ }\r
+ break;\r
+\r
+ case OID_TCP_TASK_OFFLOAD:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received set for OID_TCP_TASK_OFFLOAD\n", port_num) );\r
+\r
+ buf_len = info_buf_len;\r
+ status =\r
+ __ipoib_set_tcp_task_offload( p_adapter, pNdisRequest );\r
+ break;\r
+\r
+ /* Optional General */\r
+ case OID_GEN_TRANSPORT_HEADER_OFFSET:\r
+#ifdef NDIS51_MINIPORT\r
+ case OID_GEN_RNDIS_CONFIG_PARAMETER:\r
+ case OID_GEN_VLAN_ID:\r
+#endif\r
+ status = NDIS_STATUS_NOT_SUPPORTED;\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received an unsupported oid of 0x%.8X!\n", port_num, oid));\r
+ break;\r
+\r
+ case OID_GEN_SUPPORTED_LIST:\r
+ case OID_GEN_HARDWARE_STATUS:\r
+ case OID_GEN_MEDIA_SUPPORTED:\r
+ case OID_GEN_MEDIA_IN_USE:\r
+ case OID_GEN_MAXIMUM_FRAME_SIZE:\r
+ case OID_GEN_LINK_SPEED:\r
+ case OID_GEN_TRANSMIT_BUFFER_SPACE:\r
+ case OID_GEN_RECEIVE_BUFFER_SPACE:\r
+ case OID_GEN_MAXIMUM_LOOKAHEAD:\r
+ case OID_GEN_TRANSMIT_BLOCK_SIZE:\r
+ case OID_GEN_RECEIVE_BLOCK_SIZE:\r
+ case OID_GEN_MAXIMUM_TOTAL_SIZE:\r
+ case OID_GEN_VENDOR_ID:\r
+ case OID_GEN_VENDOR_DESCRIPTION:\r
+ case OID_GEN_VENDOR_DRIVER_VERSION:\r
+ case OID_GEN_DRIVER_VERSION:\r
+ case OID_GEN_MAC_OPTIONS:\r
+ case OID_GEN_MEDIA_CONNECT_STATUS:\r
+ case OID_GEN_MAXIMUM_SEND_PACKETS:\r
+ case OID_GEN_SUPPORTED_GUIDS:\r
+ case OID_GEN_PHYSICAL_MEDIUM:\r
+ default:\r
+ status = NDIS_STATUS_INVALID_OID;\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received an invalid oid of 0x%.8X!\n", port_num, oid));\r
+ break;\r
+ }\r
+\r
+ if( status == NDIS_STATUS_SUCCESS )\r
+ {\r
+ pNdisRequest->DATA.SET_INFORMATION.BytesRead = buf_len;\r
+ }\r
+ else\r
+ {\r
+ if( status == NDIS_STATUS_INVALID_LENGTH )\r
+ {\r
+ if ( !*p_bytes_needed )\r
+ {\r
+ *p_bytes_needed = buf_len;\r
+ }\r
+ }\r
+\r
+ pNdisRequest->DATA.SET_INFORMATION.BytesRead = 0;\r
+ }\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_OID );\r
+ return status;\r
+}\r
+#endif\r
+static NDIS_STATUS\r
+ipoib_oid_handler(\r
+ IN NDIS_HANDLE adapter_context,\r
+ IN PNDIS_OID_REQUEST pNdisRequest)\r
+{\r
+ NDIS_REQUEST_TYPE RequestType;\r
+ NDIS_STATUS status = NDIS_STATUS_SUCCESS;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_OID );\r
+\r
+ RequestType = pNdisRequest->RequestType;\r
+\r
+ switch(RequestType)\r
+ {\r
+ case NdisRequestSetInformation: \r
+ status = ipoib_set_info(adapter_context,\r
+ pNdisRequest->DATA.SET_INFORMATION.Oid,\r
+ pNdisRequest->DATA.SET_INFORMATION.InformationBuffer,\r
+ pNdisRequest->DATA.SET_INFORMATION.InformationBufferLength,\r
+ (PULONG)&pNdisRequest->DATA.SET_INFORMATION.BytesRead,\r
+ (PULONG)&pNdisRequest->DATA.SET_INFORMATION.BytesNeeded);\r
+ break;\r
+ \r
+ case NdisRequestQueryInformation:\r
+ case NdisRequestQueryStatistics:\r
+ status = ipoib_query_info(adapter_context,\r
+ pNdisRequest->DATA.QUERY_INFORMATION.Oid,\r
+ pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer,\r
+ pNdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength,\r
+ (PULONG)&pNdisRequest->DATA.QUERY_INFORMATION.BytesWritten,\r
+ (PULONG)&pNdisRequest->DATA.QUERY_INFORMATION.BytesNeeded);\r
+ \r
+ break;\r
+\r
+ default:\r
+ status = NDIS_STATUS_NOT_SUPPORTED;\r
+ break;\r
+ }\r
+ IPOIB_EXIT( IPOIB_DBG_OID );\r
+ return status;\r
+}\r
+\r
+//! Transfers some number of packets, specified as an array of packet pointers, over the network. \r
+/* For a deserialized driver, these packets are completed asynchronously\r
+using NdisMSendComplete.\r
+IRQL <= DISPATCH_LEVEL\r
+\r
+@param adapter_context Pointer to ipoib_adapter_t structure with per NIC state\r
+@param packet_array Array of packets to send\r
+@param numPackets Number of packets in the array\r
+*/\r
+void\r
+ipoib_send_net_buffer_list(\r
+ IN NDIS_HANDLE adapter_context,\r
+ IN PNET_BUFFER_LIST net_buffer_list,\r
+ IN NDIS_PORT_NUMBER port_num,\r
+ IN ULONG send_flags\r
+ )\r
+{\r
+ ipoib_adapter_t *p_adapter;\r
+ ipoib_port_t *p_port;\r
+ ULONG send_complete_flags;\r
+ PNET_BUFFER_LIST curr_net_buffer_list;\r
+ PNET_BUFFER_LIST next_net_buffer_list;\r
+ NDIS_STATUS status = NDIS_STATUS_SUCCESS;\r
+ \r
+ UNREFERENCED_PARAMETER(port_num);\r
+ PERF_DECLARE( SendPackets );\r
+ PERF_DECLARE( PortSend );\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_SEND );\r
+ cl_perf_start( SendPackets );\r
+\r
+ CL_ASSERT( adapter_context );\r
+ p_adapter = (ipoib_adapter_t*)adapter_context;\r
+ p_port = p_adapter->p_port;\r
+\r
+ cl_obj_lock( &p_adapter->obj );\r
+ if( p_adapter->ipoib_state == IPOIB_PAUSING ||\r
+ p_adapter->ipoib_state == IPOIB_PAUSED)\r
+ {\r
+ status = NDIS_STATUS_PAUSED; \r
+ cl_obj_unlock( &p_adapter->obj );\r
+ goto compl_status;\r
+ }\r
+\r
+ if( p_adapter->state != IB_PNP_PORT_ACTIVE || !p_adapter->p_port )\r
+ {\r
+ cl_obj_unlock( &p_adapter->obj );\r
+ status = NDIS_STATUS_FAILURE; \r
+ goto compl_status;\r
+ }\r
+\r
+ p_port = p_adapter->p_port;\r
+ ipoib_port_ref( p_port, ref_send_packets );\r
+ cl_obj_unlock( &p_adapter->obj );\r
+ //IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ // ("Starting NET BUFFER LIST \n") );\r
+ for (curr_net_buffer_list = net_buffer_list;\r
+ curr_net_buffer_list != NULL;\r
+ curr_net_buffer_list = next_net_buffer_list)\r
+ {\r
+ next_net_buffer_list = NET_BUFFER_LIST_NEXT_NBL(curr_net_buffer_list);\r
+ cl_perf_start( PortSend );\r
+ \r
+ ipoib_port_send( p_port, curr_net_buffer_list, send_flags);\r
+ cl_perf_stop( &adapter->perf, PortSend );\r
+ }\r
+ ipoib_port_deref( p_port, ref_send_packets );\r
+\r
+ cl_perf_stop( &p_adapter->perf, SendPackets );\r
+\r
+ cl_perf_log( &p_adapter->perf, SendBundle, num_packets );\r
+\r
+compl_status:\r
+ if (status != NDIS_STATUS_SUCCESS)\r
+ {\r
+ //ASSERT(FALSE); //????\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Got bad status \n") );\r
+ send_complete_flags = 0;\r
+ \r
+ for (curr_net_buffer_list = net_buffer_list;\r
+ curr_net_buffer_list != NULL;\r
+ curr_net_buffer_list = next_net_buffer_list)\r
+ {\r
+ next_net_buffer_list = NET_BUFFER_LIST_NEXT_NBL(curr_net_buffer_list);\r
+ NET_BUFFER_LIST_STATUS(curr_net_buffer_list) = status;\r
+ ipoib_inc_send_stat( p_adapter, IP_STAT_DROPPED, 0 );\r
+ }\r
+\r
+\r
+ if (NDIS_TEST_SEND_AT_DISPATCH_LEVEL(send_flags))\r
+ {\r
+ NDIS_SET_SEND_COMPLETE_FLAG(send_complete_flags, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL);\r
+ }\r
+ \r
+ NdisMSendNetBufferListsComplete(\r
+ p_adapter->h_adapter,\r
+ net_buffer_list,\r
+ send_complete_flags); \r
+ }\r
+ IPOIB_EXIT( IPOIB_DBG_SEND );\r
+}\r
+\r
+void\r
+ipoib_pnp_notify(\r
+ IN NDIS_HANDLE adapter_context,\r
+ IN PNET_DEVICE_PNP_EVENT pnp_event)\r
+{\r
+ ipoib_adapter_t *p_adapter;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_PNP );\r
+\r
+ p_adapter = (ipoib_adapter_t*)adapter_context;\r
+\r
+ IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_PNP, ("Event %d\n", pnp_event->DevicePnPEvent) );\r
+ if( pnp_event->DevicePnPEvent != NdisDevicePnPEventPowerProfileChanged )\r
+ {\r
+ cl_obj_lock( &p_adapter->obj );\r
+ p_adapter->state = IB_PNP_PORT_REMOVE;\r
+ cl_obj_unlock( &p_adapter->obj );\r
+\r
+ ipoib_resume_oids( p_adapter );\r
+ }\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_PNP );\r
+}\r
+\r
+\r
+VOID\r
+ipoib_shutdown_ex(\r
+ IN NDIS_HANDLE adapter_context,\r
+ IN NDIS_SHUTDOWN_ACTION shutdown_action)\r
+{\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+ UNUSED_PARAM( adapter_context );\r
+ UNUSED_PARAM( shutdown_action );\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+void\r
+ipoib_resume_oids(\r
+ IN ipoib_adapter_t* const p_adapter )\r
+{\r
+ ULONG info;\r
+ NDIS_STATUS status;\r
+ boolean_t pending_query, pending_set;\r
+ pending_oid_t query_oid = {0};\r
+ pending_oid_t set_oid = {0};\r
+ KLOCK_QUEUE_HANDLE hdl;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+ cl_obj_lock( &p_adapter->obj );\r
+ /*\r
+ * Set the status depending on our state. Fail OID requests that\r
+ * are pending while we reset the adapter.\r
+ */\r
+ switch( p_adapter->state )\r
+ {\r
+ case IB_PNP_PORT_ADD:\r
+ status = NDIS_STATUS_FAILURE;\r
+ break;\r
+\r
+ case IB_PNP_PORT_REMOVE:\r
+ status = NDIS_STATUS_NOT_ACCEPTED;\r
+ break;\r
+ \r
+ default:\r
+ status = NDIS_STATUS_SUCCESS;\r
+ }\r
+\r
+ pending_query = p_adapter->pending_query;\r
+ if( pending_query )\r
+ {\r
+ query_oid = p_adapter->query_oid;\r
+ p_adapter->pending_query = FALSE;\r
+ }\r
+ pending_set = p_adapter->pending_set;\r
+ if( pending_set )\r
+ {\r
+ set_oid = p_adapter->set_oid;\r
+ p_adapter->pending_set = FALSE;\r
+ }\r
+ cl_obj_unlock( &p_adapter->obj );\r
+\r
+ /*\r
+ * If we had a pending OID request for OID_GEN_LINK_SPEED,\r
+ * complete it now. Note that we hold the object lock since\r
+ * NdisMQueryInformationComplete is called at DISPATCH_LEVEL.\r
+ */\r
+ if( pending_query )\r
+ {\r
+ switch( query_oid.oid )\r
+ {\r
+ case OID_GEN_LINK_SPEED:\r
+ ipoib_complete_query( p_adapter, &query_oid,\r
+ status, &p_adapter->port_rate, sizeof(p_adapter->port_rate) );\r
+ break;\r
+\r
+ case OID_GEN_MEDIA_CONNECT_STATUS:\r
+ info = NdisMediaStateConnected;\r
+ ipoib_complete_query( p_adapter, &query_oid,\r
+ status, &info, sizeof(info) );\r
+ break;\r
+\r
+ default:\r
+ CL_ASSERT( query_oid.oid == OID_GEN_LINK_SPEED ||\r
+ query_oid.oid == OID_GEN_MEDIA_CONNECT_STATUS );\r
+ break;\r
+ }\r
+ }\r
+\r
+ if( pending_set )\r
+ {\r
+ switch( set_oid.oid )\r
+ {\r
+ case OID_GEN_CURRENT_PACKET_FILTER:\r
+ /* Validation already performed in the SetInformation path. */\r
+\r
+ KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
+ cl_obj_lock( &p_adapter->obj );\r
+ if( !p_adapter->packet_filter && (*(PULONG)set_oid.p_buf) )\r
+ {\r
+ cl_qlist_insert_tail(\r
+ &g_ipoib.adapter_list, &p_adapter->entry );\r
+ /*\r
+ * Filter was zero, now non-zero. Register IP addresses\r
+ * with SA.\r
+ */\r
+ ipoib_reg_addrs( p_adapter );\r
+ }\r
+ else if( p_adapter->packet_filter && !(*(PULONG)set_oid.p_buf) )\r
+ {\r
+ /* Filter was non-zero, now zero. Deregister IP addresses. */\r
+ ipoib_dereg_addrs( p_adapter );\r
+\r
+ ASSERT( cl_qlist_count( &g_ipoib.adapter_list ) );\r
+ cl_qlist_remove_item(\r
+ &g_ipoib.adapter_list, &p_adapter->entry );\r
+ }\r
+ p_adapter->packet_filter = *(PULONG)set_oid.p_buf;\r
+\r
+ cl_obj_unlock( &p_adapter->obj );\r
+ KeReleaseInStackQueuedSpinLock( &hdl );\r
+ p_adapter->set_oid.p_pending_oid = NULL;\r
+ NdisMOidRequestComplete( p_adapter->h_adapter, set_oid.p_pending_oid, status );\r
+ break;\r
+\r
+ case OID_GEN_NETWORK_LAYER_ADDRESSES:\r
+ status = __ipoib_set_net_addr( p_adapter,\r
+ p_adapter->set_oid.p_buf,\r
+ p_adapter->set_oid.buf_len,\r
+ p_adapter->set_oid.p_bytes_used,\r
+ p_adapter->set_oid.p_bytes_needed );\r
+\r
+ if( status != NDIS_STATUS_PENDING )\r
+ {\r
+ p_adapter->set_oid.p_pending_oid = NULL;\r
+ NdisMOidRequestComplete( p_adapter->h_adapter, set_oid.p_pending_oid, status );\r
+ }\r
+ break;\r
+\r
+ default:\r
+ CL_ASSERT( set_oid.oid && 0 );\r
+ break;\r
+ }\r
+ }\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static NDIS_STATUS\r
+__ipoib_set_net_addr(\r
+ IN ipoib_adapter_t * p_adapter,\r
+ IN PVOID info_buf,\r
+ IN ULONG info_buf_len,\r
+ OUT PULONG p_bytes_read,\r
+ OUT PULONG p_bytes_needed )\r
+{\r
+ NDIS_STATUS status;\r
+ PNETWORK_ADDRESS_LIST p_net_addrs;\r
+ PNETWORK_ADDRESS p_net_addr_oid;\r
+ PNETWORK_ADDRESS_IP p_ip_addr;\r
+\r
+ net_address_item_t *p_addr_item;\r
+\r
+ cl_status_t cl_status;\r
+\r
+ size_t idx;\r
+ LONG i;\r
+ ULONG addr_size;\r
+ ULONG total_size;\r
+\r
+ uint8_t port_num;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_OID );\r
+\r
+ status = NDIS_STATUS_SUCCESS;\r
+ port_num = p_adapter->guids.port_num;\r
+\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d received set for OID_GEN_NETWORK_LAYER_ADDRESSES\n",\r
+ port_num) );\r
+\r
+ if( !info_buf )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Port %d - OID_GEN_NETWORK_LAYER_ADDRESSES - "\r
+ "NULL buffer\n", port_num) );\r
+ IPOIB_EXIT( IPOIB_DBG_OID );\r
+ return NDIS_STATUS_INVALID_DATA;\r
+ }\r
+\r
+ /*\r
+ * Must use field offset because the structures define array's of size one\r
+ * of a the incorrect type for what is really stored.\r
+ */\r
+ if( info_buf_len < FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address) )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, \r
+ ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - "\r
+ "bad length of %d, not enough "\r
+ "for NETWORK_ADDRESS_LIST (%d)\n", port_num, info_buf_len,\r
+ FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address)) );\r
+ *p_bytes_needed = FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address);\r
+ IPOIB_EXIT( IPOIB_DBG_OID );\r
+ return NDIS_STATUS_INVALID_LENGTH;\r
+ }\r
+\r
+ p_net_addrs = (PNETWORK_ADDRESS_LIST)info_buf;\r
+ if( p_net_addrs->AddressCount == 0)\r
+ {\r
+ if( p_net_addrs->AddressType == NDIS_PROTOCOL_ID_TCP_IP )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,\r
+ ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - "\r
+ "clear TCP/IP addresses\n", port_num) );\r
+ }\r
+ else\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,\r
+ ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - "\r
+ "Non TCP/IP address type of 0x%.4X on clear\n",\r
+ port_num, p_net_addrs->AddressType) );\r
+ IPOIB_EXIT( IPOIB_DBG_OID );\r
+ return NDIS_STATUS_SUCCESS;\r
+ }\r
+ }\r
+\r
+ addr_size = FIELD_OFFSET(NETWORK_ADDRESS, Address) +\r
+ NETWORK_ADDRESS_LENGTH_IP;\r
+ total_size = FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address) +\r
+ addr_size * p_net_addrs->AddressCount;\r
+\r
+ if( info_buf_len < total_size )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - "\r
+ "bad length of %d, %d required for %d addresses\n",\r
+ port_num, info_buf_len, total_size, p_net_addrs->AddressCount) );\r
+ *p_bytes_needed = total_size;\r
+ IPOIB_EXIT( IPOIB_DBG_OID );\r
+ return NDIS_STATUS_INVALID_LENGTH;\r
+ }\r
+\r
+ /* Lock lists for duration since SA callbacks can occur on other CPUs */\r
+ cl_obj_lock( &p_adapter->obj );\r
+\r
+ /* Set the capacity of the vector to accomodate all assinged addresses. */\r
+ cl_status = cl_vector_set_capacity(\r
+ &p_adapter->ip_vector, p_net_addrs->AddressCount );\r
+ if( cl_status != CL_SUCCESS )\r
+ {\r
+ cl_obj_unlock( &p_adapter->obj );\r
+ IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Port %d - OID_GEN_NETWORK_LAYER_ADDRESSES - "\r
+ "Failed to set IP vector capacity: %#x\n", port_num,\r
+ cl_status) );\r
+ IPOIB_EXIT( IPOIB_DBG_OID );\r
+ return NDIS_STATUS_RESOURCES;\r
+ }\r
+\r
+ *p_bytes_read = total_size;\r
+\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - List contains %d addresses\n",\r
+ port_num, p_net_addrs->AddressCount));\r
+\r
+ /* First look for addresses we had that should be removed */\r
+ for( idx = 0; idx != cl_vector_get_size( &p_adapter->ip_vector ); idx++ )\r
+ {\r
+ p_addr_item = (net_address_item_t*)\r
+ cl_vector_get_ptr( &p_adapter->ip_vector, idx );\r
+ p_net_addr_oid = (PNETWORK_ADDRESS)p_net_addrs->Address;\r
+\r
+ for( i = 0; i < p_net_addrs->AddressCount; ++i, p_net_addr_oid =\r
+ (PNETWORK_ADDRESS)((uint8_t *)p_net_addr_oid +\r
+ FIELD_OFFSET(NETWORK_ADDRESS, Address) +\r
+ p_net_addr_oid->AddressLength) )\r
+ {\r
+\r
+ if( p_net_addr_oid->AddressType != NDIS_PROTOCOL_ID_TCP_IP )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_OID,\r
+ ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Address %d is wrong type of 0x%.4X, "\r
+ "should be 0x%.4X\n", port_num, i, p_net_addr_oid->AddressType,\r
+ NDIS_PROTOCOL_ID_TCP_IP));\r
+ continue;\r
+ }\r
+\r
+ if( p_net_addr_oid->AddressLength != NETWORK_ADDRESS_LENGTH_IP)\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_OID,\r
+ ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Address %d is wrong size of %d, "\r
+ "should be %d\n", port_num, i, p_net_addr_oid->AddressLength,\r
+ NETWORK_ADDRESS_LENGTH_IP));\r
+ continue;\r
+ }\r
+\r
+ p_ip_addr = (PNETWORK_ADDRESS_IP)p_net_addr_oid->Address;\r
+ if( !cl_memcmp( &p_ip_addr->in_addr,\r
+ &p_addr_item->address.as_ulong, sizeof(ULONG) ) )\r
+ {\r
+ break;\r
+ }\r
+ }\r
+\r
+ if( i == p_net_addrs->AddressCount )\r
+ {\r
+ /* Didn't find a match, delete from SA */\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Deleting Address %d.%d.%d.%d\n",\r
+ port_num,\r
+ p_addr_item->address.as_bytes[0],\r
+ p_addr_item->address.as_bytes[1],\r
+ p_addr_item->address.as_bytes[2],\r
+ p_addr_item->address.as_bytes[3]));\r
+\r
+ if( p_addr_item->p_reg )\r
+ {\r
+ if( p_addr_item->p_reg->h_reg_svc )\r
+ {\r
+ p_adapter->p_ifc->dereg_svc(\r
+ p_addr_item->p_reg->h_reg_svc, __ipoib_ats_dereg_cb );\r
+ }\r
+ else\r
+ {\r
+ cl_free( p_addr_item->p_reg );\r
+ }\r
+ p_addr_item->p_reg = NULL;\r
+ }\r
+ p_addr_item->address.as_ulong = 0;\r
+ }\r
+ }\r
+\r
+ /* Now look for new addresses */\r
+ p_net_addr_oid = (NETWORK_ADDRESS *)p_net_addrs->Address;\r
+ idx = 0;\r
+ for( i = 0; i < p_net_addrs->AddressCount; i++, p_net_addr_oid =\r
+ (PNETWORK_ADDRESS)((uint8_t *)p_net_addr_oid +\r
+ FIELD_OFFSET(NETWORK_ADDRESS, Address) + p_net_addr_oid->AddressLength) )\r
+ {\r
+\r
+ if( p_net_addr_oid->AddressType != NDIS_PROTOCOL_ID_TCP_IP )\r
+ {\r
+ IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,\r
+ ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Address %d is wrong type of 0x%.4X, "\r
+ "should be 0x%.4X\n", port_num, i, p_net_addr_oid->AddressType,\r
+ NDIS_PROTOCOL_ID_TCP_IP));\r
+ continue;\r
+ }\r
+\r
+ if( p_net_addr_oid->AddressLength != NETWORK_ADDRESS_LENGTH_IP)\r
+ {\r
+ IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,\r
+ ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Address %d is wrong size of %d, "\r
+ "should be %d\n", port_num, i, p_net_addr_oid->AddressLength,\r
+ NETWORK_ADDRESS_LENGTH_IP));\r
+ continue;\r
+ }\r
+\r
+ p_ip_addr = (PNETWORK_ADDRESS_IP)p_net_addr_oid->Address;\r
+\r
+ /* Size the vector as needed. */\r
+ if( cl_vector_get_size( &p_adapter->ip_vector ) <= idx )\r
+ cl_vector_set_size( &p_adapter->ip_vector, idx + 1 );\r
+\r
+ p_addr_item = (net_address_item_t *) cl_vector_get_ptr( &p_adapter->ip_vector, idx );\r
+ if( !cl_memcmp( &p_ip_addr->in_addr, &p_addr_item->address.as_ulong,\r
+ sizeof(ULONG) ) )\r
+ {\r
+ idx++;\r
+ /* Already have this address - no change needed */\r
+ continue;\r
+ }\r
+\r
+ /*\r
+ * Copy the address information, but don't register yet - the port\r
+ * could be down.\r
+ */\r
+ if( p_addr_item->p_reg )\r
+ {\r
+ /* If in use by some other address, deregister. */\r
+ if( p_addr_item->p_reg->h_reg_svc )\r
+ {\r
+ p_adapter->p_ifc->dereg_svc(\r
+ p_addr_item->p_reg->h_reg_svc, __ipoib_ats_dereg_cb );\r
+ }\r
+ else\r
+ {\r
+ cl_free( p_addr_item->p_reg );\r
+ }\r
+ p_addr_item->p_reg = NULL;\r
+ }\r
+ memcpy ((void *)&p_addr_item->address.as_ulong, (const void *)&p_ip_addr->in_addr, sizeof(ULONG) );\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Adding Address %d.%d.%d.%d\n",\r
+ port_num,\r
+ p_addr_item->address.as_bytes[0],\r
+ p_addr_item->address.as_bytes[1],\r
+ p_addr_item->address.as_bytes[2],\r
+ p_addr_item->address.as_bytes[3]) );\r
+ idx++;\r
+ }\r
+\r
+ /* Now clear any extra entries that shouldn't be there. */\r
+ while( idx < cl_vector_get_size( &p_adapter->ip_vector ) )\r
+ {\r
+ p_addr_item = (net_address_item_t*)\r
+ cl_vector_get_ptr( &p_adapter->ip_vector,\r
+ cl_vector_get_size( &p_adapter->ip_vector ) - 1 );\r
+\r
+ if( p_addr_item->p_reg )\r
+ {\r
+ if( p_addr_item->p_reg->h_reg_svc )\r
+ {\r
+ p_adapter->p_ifc->dereg_svc(\r
+ p_addr_item->p_reg->h_reg_svc, __ipoib_ats_dereg_cb );\r
+ }\r
+ else\r
+ {\r
+ cl_free( p_addr_item->p_reg );\r
+ }\r
+ p_addr_item->p_reg = NULL;\r
+ p_addr_item->address.as_ulong = 0;\r
+ }\r
+\r
+ /* No need to check return value - shrinking always succeeds. */\r
+ cl_vector_set_size( &p_adapter->ip_vector,\r
+ cl_vector_get_size( &p_adapter->ip_vector ) - 1 );\r
+ }\r
+\r
+ if( p_adapter->state == IB_PNP_PORT_ACTIVE && p_adapter->packet_filter )\r
+ ipoib_reg_addrs( p_adapter );\r
+\r
+ cl_obj_unlock( &p_adapter->obj );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_OID );\r
+ return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+\r
+/* Object lock is held when this function is called. */\r
+void\r
+ipoib_reg_addrs(\r
+ IN ipoib_adapter_t* const p_adapter )\r
+{\r
+ net_address_item_t *p_addr_item;\r
+\r
+ size_t idx;\r
+\r
+ uint8_t port_num;\r
+\r
+ ib_api_status_t ib_status;\r
+ ib_reg_svc_req_t ib_service;\r
+ ib_gid_t port_gid;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_OID );\r
+\r
+ if(p_adapter->guids.port_guid.pkey != IB_DEFAULT_PKEY)\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR,IPOIB_DBG_ERROR,\r
+ ("ATS Service available for default pkey only\n")); \r
+ return;\r
+ }\r
+ port_num = p_adapter->guids.port_num;\r
+\r
+ /* Setup our service call with things common to all calls */\r
+ cl_memset( &ib_service, 0, sizeof(ib_service) );\r
+\r
+ /* BUGBUG Only register local subnet GID prefix for now */\r
+ ib_gid_set_default( &port_gid, p_adapter->guids.port_guid.guid );\r
+ ib_service.svc_rec.service_gid = port_gid;\r
+\r
+ ib_service.svc_rec.service_pkey = IB_DEFAULT_PKEY;\r
+ ib_service.svc_rec.service_lease = IB_INFINITE_SERVICE_LEASE;\r
+\r
+ /* Must cast here because the service name is an array of unsigned chars but\r
+ * strcpy want a pointer to a signed char */\r
+ if ( StringCchCopy( (char *)ib_service.svc_rec.service_name, \r
+ sizeof(ib_service.svc_rec.service_name) / sizeof(char), ATS_NAME ) != S_OK) {\r
+ ASSERT(FALSE);\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR,IPOIB_DBG_ERROR,\r
+ ("Problem copying ATS name: exiting\n"));\r
+ return;\r
+ }\r
+ \r
+ /* IP Address in question will be put in below */\r
+ ib_service.port_guid = p_adapter->guids.port_guid.guid;\r
+ ib_service.timeout_ms = p_adapter->params.sa_timeout;\r
+ ib_service.retry_cnt = p_adapter->params.sa_retry_cnt;\r
+\r
+ /* Can't set IB_FLAGS_SYNC here because I can't wait at dispatch */\r
+ ib_service.flags = 0;\r
+\r
+ /* Service context will be put in below */\r
+\r
+ ib_service.svc_data_mask = IB_SR_COMPMASK_SID |\r
+ IB_SR_COMPMASK_SGID |\r
+ IB_SR_COMPMASK_SPKEY |\r
+ IB_SR_COMPMASK_SLEASE |\r
+ IB_SR_COMPMASK_SNAME |\r
+ IB_SR_COMPMASK_SDATA8_12 |\r
+ IB_SR_COMPMASK_SDATA8_13 |\r
+ IB_SR_COMPMASK_SDATA8_14 |\r
+ IB_SR_COMPMASK_SDATA8_15;\r
+ ib_service.pfn_reg_svc_cb = __ipoib_ats_reg_cb;\r
+\r
+ for( idx = 0; idx < cl_vector_get_size( &p_adapter->ip_vector); idx++ )\r
+ {\r
+ p_addr_item = (net_address_item_t*)\r
+ cl_vector_get_ptr( &p_adapter->ip_vector, idx );\r
+\r
+ if( p_addr_item->p_reg )\r
+ continue;\r
+\r
+ p_addr_item->p_reg = (ats_reg_t *) cl_zalloc( sizeof(ats_reg_t) );\r
+ if( !p_addr_item->p_reg )\r
+ break;\r
+\r
+ p_addr_item->p_reg->p_adapter = p_adapter;\r
+\r
+ ib_service.svc_context = p_addr_item->p_reg;\r
+\r
+ ib_service.svc_rec.service_id =\r
+ ATS_SERVICE_ID & CL_HTON64(0xFFFFFFFFFFFFFF00);\r
+ /* ATS service IDs start at 0x10000CE100415453 */\r
+ ib_service.svc_rec.service_id |= ((uint64_t)(idx + 0x53)) << 56;\r
+\r
+ cl_memcpy( &ib_service.svc_rec.service_data8[ATS_IPV4_OFFSET],\r
+ p_addr_item->address.as_bytes, IPV4_ADDR_SIZE );\r
+\r
+ /* Take a reference for each service request. */\r
+ cl_obj_ref(&p_adapter->obj);\r
+ ib_status = p_adapter->p_ifc->reg_svc(\r
+ p_adapter->h_al, &ib_service, &p_addr_item->p_reg->h_reg_svc );\r
+ if( ib_status != IB_SUCCESS )\r
+ {\r
+ if( ib_status == IB_INVALID_GUID )\r
+ {\r
+ /* If this occurs, we log the error but do not fail the OID yet */\r
+ IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_OID,\r
+ ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - "\r
+ "Failed to register IP Address "\r
+ "of %d.%d.%d.%d with error IB_INVALID_GUID\n",\r
+ port_num,\r
+ p_addr_item->address.as_bytes[0],\r
+ p_addr_item->address.as_bytes[1],\r
+ p_addr_item->address.as_bytes[2],\r
+ p_addr_item->address.as_bytes[3]) );\r
+ }\r
+ else\r
+ {\r
+ /* Fatal error. */\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Failed to register IP Address "\r
+ "of %d.%d.%d.%d with error %s\n",\r
+ port_num,\r
+ p_addr_item->address.as_bytes[0],\r
+ p_addr_item->address.as_bytes[1],\r
+ p_addr_item->address.as_bytes[2],\r
+ p_addr_item->address.as_bytes[3],\r
+ p_adapter->p_ifc->get_err_str( ib_status )) );\r
+ p_adapter->hung = TRUE;\r
+ }\r
+ cl_obj_deref(&p_adapter->obj);\r
+ cl_free( p_addr_item->p_reg );\r
+ p_addr_item->p_reg = NULL;\r
+ }\r
+ }\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_OID );\r
+}\r
+\r
+\r
+/* Object lock is held when this function is called. */\r
+void\r
+ipoib_dereg_addrs(\r
+ IN ipoib_adapter_t* const p_adapter )\r
+{\r
+ net_address_item_t *p_addr_item;\r
+\r
+ size_t idx;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_OID );\r
+\r
+ for( idx = 0; idx < cl_vector_get_size( &p_adapter->ip_vector); idx++ )\r
+ {\r
+ p_addr_item = (net_address_item_t*)\r
+ cl_vector_get_ptr( &p_adapter->ip_vector, idx );\r
+\r
+ if( !p_addr_item->p_reg )\r
+ continue;\r
+\r
+ if( p_addr_item->p_reg->h_reg_svc )\r
+ {\r
+ p_adapter->p_ifc->dereg_svc(\r
+ p_addr_item->p_reg->h_reg_svc, __ipoib_ats_dereg_cb );\r
+ }\r
+ else\r
+ {\r
+ cl_free( p_addr_item->p_reg );\r
+ }\r
+ p_addr_item->p_reg = NULL;\r
+ }\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_OID );\r
+}\r
+\r
+\r
+void\r
+ipoib_cancel_xmit(\r
+ IN NDIS_HANDLE adapter_context,\r
+ IN PVOID cancel_id )\r
+{\r
+/* ipoib_adapter_t* const p_adapter =\r
+ (ipoib_adapter_t* const )adapter_context;\r
+ \r
+\r
+if 0\r
+ if( p_adapter && p_adapter->p_port )\r
+ {\r
+ ipoib_port_cancel_xmit( p_adapter->p_port, cancel_id );\r
+ }\r
+endif\r
+*/\r
+\r
+ UNUSED_PARAM(adapter_context);\r
+ UNUSED_PARAM(cancel_id);\r
+\r
+ return; //TODO return this functionality\r
+\r
+}\r
+\r
+\r
+static void\r
+__ipoib_ats_reg_cb(\r
+ IN ib_reg_svc_rec_t *p_reg_svc_rec )\r
+{\r
+ ats_reg_t *p_reg;\r
+ uint8_t port_num;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_OID );\r
+\r
+ CL_ASSERT( p_reg_svc_rec );\r
+ CL_ASSERT( p_reg_svc_rec->svc_context );\r
+\r
+ p_reg = (ats_reg_t*)p_reg_svc_rec->svc_context;\r
+ port_num = p_reg->p_adapter->guids.port_num;\r
+\r
+ cl_obj_lock( &p_reg->p_adapter->obj );\r
+\r
+ if( p_reg_svc_rec->req_status == IB_SUCCESS &&\r
+ !p_reg_svc_rec->resp_status )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+ ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Registered IP Address "\r
+ "of %d.%d.%d.%d\n",\r
+ port_num,\r
+ p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET],\r
+ p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+1],\r
+ p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+2],\r
+ p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+3]) );\r
+ }\r
+ else if( p_reg_svc_rec->req_status != IB_CANCELED )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_OID,\r
+ ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Failed to register IP Address "\r
+ "of %d.%d.%d.%d with error %s\n",\r
+ port_num,\r
+ p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET],\r
+ p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+1],\r
+ p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+2],\r
+ p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+3],\r
+ p_reg->p_adapter->p_ifc->get_err_str((ib_api_status_t) p_reg_svc_rec->resp_status )) );\r
+ p_reg->p_adapter->hung = TRUE;\r
+ p_reg->h_reg_svc = NULL;\r
+ }\r
+\r
+ cl_obj_unlock( &p_reg->p_adapter->obj );\r
+ cl_obj_deref(&p_reg->p_adapter->obj);\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_OID );\r
+}\r
+\r
+\r
+static void\r
+__ipoib_ats_dereg_cb(\r
+ IN void *context )\r
+{\r
+ cl_free( context );\r
+}\r
+\r
+static NDIS_STATUS \r
+ipoib_pause(\r
+ IN NDIS_HANDLE adapter_context, \r
+ IN PNDIS_MINIPORT_PAUSE_PARAMETERS pause_parameters)\r
+{\r
+ ipoib_adapter_t *p_adapter;\r
+ KLOCK_QUEUE_HANDLE hdl;\r
+\r
+ UNREFERENCED_PARAMETER(pause_parameters);\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+//return NDIS_STATUS_SUCCESS;\r
+ CL_ASSERT(adapter_context);\r
+ p_adapter = (ipoib_adapter_t*)adapter_context;\r
+ CL_ASSERT(p_adapter->ipoib_state == IPOIB_RUNNING);\r
+\r
+ KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
+ p_adapter->ipoib_state = IPOIB_PAUSING;\r
+ KeReleaseInStackQueuedSpinLock( &hdl );\r
+\r
+ //TODO: \r
+ ipoib_port_resume(p_adapter->p_port,FALSE);\r
+// ASSERT(FALSE);\r
+\r
+ KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
+ p_adapter->ipoib_state = IPOIB_PAUSED;\r
+ KeReleaseInStackQueuedSpinLock( &hdl );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+ return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+static NDIS_STATUS \r
+ipoib_restart(\r
+ IN NDIS_HANDLE adapter_context, \r
+ IN PNDIS_MINIPORT_RESTART_PARAMETERS restart_parameters)\r
+{\r
+ ipoib_adapter_t *p_adapter;\r
+ KLOCK_QUEUE_HANDLE hdl;\r
+ PNDIS_RESTART_ATTRIBUTES NdisRestartAttributes;\r
+ PNDIS_RESTART_GENERAL_ATTRIBUTES NdisGeneralAttributes;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+ p_adapter = (ipoib_adapter_t*)adapter_context;\r
+\r
+ NdisRestartAttributes = restart_parameters->RestartAttributes;\r
+\r
+ if (NdisRestartAttributes != NULL)\r
+ {\r
+ CL_ASSERT(NdisRestartAttributes->Oid == OID_GEN_MINIPORT_RESTART_ATTRIBUTES);\r
+ NdisGeneralAttributes = (PNDIS_RESTART_GENERAL_ATTRIBUTES)NdisRestartAttributes->Data; \r
+ //\r
+ // Check to see if we need to change any attributes\r
+ }\r
+\r
+ KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
+ p_adapter->ipoib_state = IPOIB_RUNNING;\r
+ KeReleaseInStackQueuedSpinLock( &hdl );\r
+\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+ return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+/*++\r
+Routine Description:\r
+\r
+ This function aborts the request pending in the miniport.\r
+\r
+Arguments:\r
+\r
+ MiniportAdapterContext Pointer to the adapter structure\r
+ RequestId Specify the request to be cancelled.\r
+ \r
+Return Value:\r
+ \r
+--*/\r
+static void\r
+ipoib_cancel_oid_request(\r
+ IN NDIS_HANDLE adapter_context,\r
+ IN PVOID requestId\r
+ )\r
+{\r
+ PNDIS_OID_REQUEST pending_request;\r
+ ipoib_adapter_t *p_adapter;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_OID );\r
+ p_adapter = (ipoib_adapter_t*)adapter_context;\r
+\r
+ cl_obj_lock( &p_adapter->obj );\r
+ \r
+ if ( p_adapter->query_oid.p_pending_oid &&\r
+ p_adapter->query_oid.p_pending_oid->RequestId == requestId)\r
+ {\r
+ pending_request = p_adapter->query_oid.p_pending_oid;\r
+ p_adapter->query_oid.p_pending_oid = NULL;\r
+ p_adapter->pending_query = FALSE;\r
+ }\r
+ else if(p_adapter->set_oid.p_pending_oid && \r
+ p_adapter->set_oid.p_pending_oid->RequestId == requestId)\r
+ {\r
+ pending_request = p_adapter->set_oid.p_pending_oid;\r
+ p_adapter->set_oid.p_pending_oid = NULL;\r
+ p_adapter->pending_set = FALSE;\r
+ }\r
+ else\r
+ {\r
+ cl_obj_unlock( &p_adapter->obj );\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("No Pending OID found\n") );\r
+ return;\r
+ }\r
+ cl_obj_unlock( &p_adapter->obj );\r
+\r
+ NdisMOidRequestComplete(p_adapter->h_adapter, \r
+ pending_request, \r
+ NDIS_STATUS_REQUEST_ABORTED);\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_OID );\r
+}\r
+++ /dev/null
-/*\r
- * Copyright (c) 2005 SilverStorm Technologies. All rights reserved.\r
- * Copyright (c) 2006 Mellanox Technologies. All rights reserved.\r
- * Portions Copyright (c) 2008 Microsoft Corporation. All rights reserved.\r
- *\r
- * This software is available to you under the OpenIB.org BSD license\r
- * below:\r
- *\r
- * Redistribution and use in source and binary forms, with or\r
- * without modification, are permitted provided that the following\r
- * conditions are met:\r
- *\r
- * - Redistributions of source code must retain the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer.\r
- *\r
- * - Redistributions in binary form must reproduce the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer in the documentation and/or other materials\r
- * provided with the distribution.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- * SOFTWARE.\r
- *\r
- * $Id: ipoib_endpoint.c 4226 2009-04-06 06:01:03Z xalex $\r
- */\r
-\r
-\r
-\r
-#include "ipoib_endpoint.h"\r
-#include "ipoib_port.h"\r
-#include "ipoib_debug.h"\r
-#if defined(EVENT_TRACING)\r
-#ifdef offsetof\r
-#undef offsetof\r
-#endif\r
-#include "ipoib_endpoint.tmh"\r
-#endif\r
-#include <complib/cl_atomic.h>\r
-#include <complib/cl_math.h>\r
-\r
-\r
-static void\r
-__endpt_destroying(\r
- IN cl_obj_t* p_obj );\r
-\r
-static void\r
-__endpt_cleanup(\r
- IN cl_obj_t* p_obj );\r
-\r
-static void\r
-__endpt_free(\r
- IN cl_obj_t* p_obj );\r
-\r
-static ib_api_status_t\r
-__create_mcast_av(\r
- IN ib_pd_handle_t h_pd,\r
- IN uint8_t port_num,\r
- IN ib_member_rec_t* const p_member_rec,\r
- OUT ib_av_handle_t* const ph_av );\r
-\r
-static inline ipoib_port_t*\r
-__endpt_parent(\r
- IN ipoib_endpt_t* const p_endpt );\r
-\r
-static void\r
-__path_query_cb(\r
- IN ib_query_rec_t *p_query_rec );\r
-\r
-static void\r
-__endpt_resolve(\r
- IN ipoib_endpt_t* const p_endpt );\r
-\r
-static void\r
-__endpt_cm_send_cb(\r
- IN const ib_cq_handle_t h_cq,\r
- IN void *cq_context );\r
-static void\r
-__endpt_cm_recv_cb(\r
- IN const ib_cq_handle_t h_cq,\r
- IN void *cq_context );\r
-\r
-static void\r
-__endpt_cm_buf_mgr_construct(\r
- IN endpt_buf_mgr_t * const p_buf_mgr );\r
-static void\r
-__conn_reply_cb(\r
- IN ib_cm_rep_rec_t *p_cm_rep );\r
-\r
-static void\r
-__conn_mra_cb(\r
- IN ib_cm_mra_rec_t *p_mra_rec );\r
-\r
-static void\r
-__conn_rej_cb(\r
- IN ib_cm_rej_rec_t *p_rej_rec );\r
-\r
-static void\r
-__conn_dreq_cb(\r
- IN ib_cm_dreq_rec_t *p_dreq_rec );\r
-\r
-#if 0 //CM\r
-static cl_status_t\r
-__cm_recv_desc_ctor(\r
- IN void* const p_object,\r
- IN void* context,\r
- OUT cl_pool_item_t** const pp_pool_item );\r
-\r
-static void\r
-__cm_recv_desc_dtor(\r
- IN const cl_pool_item_t* const p_pool_item,\r
- IN void *context );\r
-\r
-static NDIS_PACKET*\r
-__endpt_cm_get_ndis_pkt(\r
- IN ipoib_port_t* const p_port,\r
- IN ipoib_cm_desc_t* const p_desc );\r
-\r
-static inline ipoib_cm_desc_t*\r
-__endpt_cm_buf_mgr_get_recv(\r
- IN endpt_buf_mgr_t * const p_buf_mgr );\r
-\r
-static boolean_t\r
-__cm_recv_is_dhcp(\r
- IN const ipoib_pkt_t* const p_ipoib );\r
-\r
-static ib_api_status_t\r
-__endpt_cm_recv_arp(\r
- IN ipoib_port_t* const p_port,\r
- IN const ipoib_pkt_t* const p_ipoib,\r
- OUT eth_pkt_t* const p_eth,\r
- IN ipoib_endpt_t* const p_src_endpt );\r
-\r
-static ib_api_status_t\r
-__endpt_cm_recv_udp(\r
- IN ipoib_port_t* const p_port,\r
- IN ib_wc_t* const p_wc,\r
- IN const ipoib_pkt_t* const p_ipoib,\r
- OUT eth_pkt_t* const p_eth,\r
- IN ipoib_endpt_t* const p_src_endpt );\r
-#endif\r
-\r
-ipoib_endpt_t*\r
-ipoib_endpt_create(\r
- IN const ib_gid_t* const p_dgid,\r
- IN const net16_t dlid,\r
- IN const net32_t qpn )\r
-{\r
- ipoib_endpt_t *p_endpt;\r
- cl_status_t status;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
-\r
- p_endpt = cl_zalloc( sizeof(ipoib_endpt_t) );\r
- if( !p_endpt )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Failed to allocate endpoint (%d bytes)\n",\r
- sizeof(ipoib_endpt_t)) );\r
- return NULL;\r
- }\r
-\r
- cl_obj_construct( &p_endpt->obj, IPOIB_OBJ_ENDPOINT );\r
-\r
- status = cl_obj_init( &p_endpt->obj, CL_DESTROY_ASYNC,\r
- __endpt_destroying, __endpt_cleanup, __endpt_free );\r
-\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
- ("Created endpoint: [ %p ] DLID: %#x QPN: %#x \n", \r
- p_endpt, cl_ntoh16(dlid), cl_ntoh32(qpn) ) );\r
-\r
- p_endpt->dgid = *p_dgid;\r
- p_endpt->dlid = dlid;\r
- p_endpt->qpn = qpn;\r
-\r
- IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
- return p_endpt;\r
-}\r
-\r
-\r
-static ib_api_status_t\r
-__create_mcast_av(\r
- IN ib_pd_handle_t h_pd,\r
- IN uint8_t port_num,\r
- IN ib_member_rec_t* const p_member_rec,\r
- OUT ib_av_handle_t* const ph_av )\r
-{\r
- ib_av_attr_t av_attr;\r
- uint32_t flow_lbl;\r
- uint8_t hop_lmt;\r
- ib_api_status_t status;\r
- ipoib_endpt_t *p_endpt;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_MCAST );\r
-\r
- p_endpt = PARENT_STRUCT(ph_av, ipoib_endpt_t, h_av );\r
-\r
- cl_memclr( &av_attr, sizeof(ib_av_attr_t) );\r
- av_attr.port_num = port_num;\r
- ib_member_get_sl_flow_hop( p_member_rec->sl_flow_hop,\r
- &av_attr.sl, &flow_lbl, &hop_lmt );\r
- av_attr.dlid = p_member_rec->mlid;\r
- av_attr.grh_valid = TRUE;\r
- av_attr.grh.hop_limit = hop_lmt;\r
- av_attr.grh.dest_gid = p_member_rec->mgid;\r
- av_attr.grh.src_gid = p_member_rec->port_gid;\r
- av_attr.grh.ver_class_flow =\r
- ib_grh_set_ver_class_flow( 6, p_member_rec->tclass, flow_lbl );\r
- av_attr.static_rate = p_member_rec->rate & IB_PATH_REC_BASE_MASK;\r
- av_attr.path_bits = 0;\r
- /* port is not attached to endpoint at this point, so use endpt ifc reference */\r
- status = p_endpt->p_ifc->create_av( h_pd, &av_attr, ph_av );\r
-\r
- if( status != IB_SUCCESS )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ib_create_av returned %s\n",\r
- p_endpt->p_ifc->get_err_str( status )) );\r
- }\r
-\r
- IPOIB_EXIT( IPOIB_DBG_MCAST );\r
- return status;\r
-}\r
-\r
-\r
-ib_api_status_t\r
-ipoib_endpt_set_mcast(\r
- IN ipoib_endpt_t* const p_endpt,\r
- IN ib_pd_handle_t h_pd,\r
- IN uint8_t port_num,\r
- IN ib_mcast_rec_t* const p_mcast_rec )\r
-{\r
- ib_api_status_t status;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
-\r
- IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
- ("Create av for MAC: %02X-%02X-%02X-%02X-%02X-%02X\n",\r
- p_endpt->mac.addr[0], p_endpt->mac.addr[1],\r
- p_endpt->mac.addr[2], p_endpt->mac.addr[3],\r
- p_endpt->mac.addr[4], p_endpt->mac.addr[5]) );\r
- \r
- status = __create_mcast_av( h_pd, port_num, p_mcast_rec->p_member_rec,\r
- &p_endpt->h_av );\r
- if( status != IB_SUCCESS )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("__create_mcast_av returned %s\n", \r
- p_endpt->p_ifc->get_err_str( status )) );\r
- return status;\r
- }\r
- p_endpt->h_mcast = p_mcast_rec->h_mcast;\r
- CL_ASSERT(p_endpt->dlid == 0);\r
-\r
- IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
- return IB_SUCCESS;\r
-}\r
-\r
-\r
-static void\r
-__endpt_destroying(\r
- IN cl_obj_t* p_obj )\r
-{\r
- ipoib_endpt_t *p_endpt;\r
- ipoib_port_t *p_port;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
-\r
- p_endpt = PARENT_STRUCT( p_obj, ipoib_endpt_t, obj );\r
- p_port = __endpt_parent( p_endpt );\r
-\r
- cl_obj_lock( p_obj );\r
- if( p_endpt->h_query )\r
- {\r
- p_port->p_adapter->p_ifc->cancel_query(\r
- p_port->p_adapter->h_al, p_endpt->h_query );\r
- p_endpt->h_query = NULL;\r
- }\r
-\r
- /* Leave the multicast group if it exists. */\r
- if( p_endpt->h_mcast )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
- ("Leaving MCast group\n") );\r
- ipoib_port_ref(p_port, ref_leave_mcast);\r
- p_port->p_adapter->p_ifc->leave_mcast( p_endpt->h_mcast, ipoib_leave_mcast_cb );\r
- }\r
-#if 0\r
- else if( p_port->p_adapter->params.cm_enabled )\r
- {\r
- p_endpt->cm_flag = 0;\r
- CL_ASSERT( endpt_cm_get_state( p_endpt ) == IPOIB_CM_DISCONNECTED );\r
- }\r
-#endif\r
-\r
- cl_obj_unlock( p_obj );\r
- \r
- IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
-}\r
-\r
-\r
-static void\r
-__endpt_cleanup(\r
- IN cl_obj_t* p_obj )\r
-{\r
- ipoib_endpt_t *p_endpt;\r
- ipoib_port_t *p_port;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
-\r
- p_endpt = PARENT_STRUCT( p_obj, ipoib_endpt_t, obj );\r
- p_port = __endpt_parent( p_endpt );\r
-\r
- /* Destroy the AV if it exists. */\r
- if( p_endpt->h_av )\r
- p_port->p_adapter->p_ifc->destroy_av( p_endpt->h_av );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
-}\r
-\r
-\r
-static void\r
-__endpt_free(\r
- IN cl_obj_t* p_obj )\r
-{\r
- ipoib_endpt_t *p_endpt;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
-\r
- p_endpt = PARENT_STRUCT( p_obj, ipoib_endpt_t, obj );\r
-\r
- cl_obj_deinit( p_obj );\r
- cl_free( p_endpt );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
-}\r
-\r
-\r
-static inline ipoib_port_t*\r
-__endpt_parent(\r
- IN ipoib_endpt_t* const p_endpt )\r
-{\r
- return PARENT_STRUCT( p_endpt->rel.p_parent_obj, ipoib_port_t, obj );\r
-}\r
-\r
-ipoib_port_t*\r
-ipoib_endpt_parent(\r
- IN ipoib_endpt_t* const p_endpt )\r
-{\r
- return __endpt_parent( p_endpt );\r
-}\r
-\r
-/*\r
- * This function is called with the port object's send lock held and\r
- * a reference held on the endpoint. If we fail, we release the reference.\r
- */\r
-NDIS_STATUS\r
-ipoib_endpt_queue(\r
- IN ipoib_endpt_t* const p_endpt )\r
-{\r
- ib_api_status_t status;\r
- ipoib_port_t *p_port;\r
- ib_av_attr_t av_attr;\r
- net32_t flow_lbl;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
-\r
- if( p_endpt->h_av )\r
- {\r
- IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
- return NDIS_STATUS_SUCCESS;\r
- }\r
-\r
- if( p_endpt->qpn == CL_HTON32(0x00FFFFFF) )\r
- {\r
- /*\r
- * Handle a race between the mcast callback and a receive/send. The QP\r
- * is joined to the MC group before the MC callback is received, so it\r
- * can receive packets, and NDIS can try to respond. We need to delay\r
- * a response until the MC callback runs and sets the AV.\r
- */\r
- ipoib_endpt_deref( p_endpt );\r
- IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
- return NDIS_STATUS_PENDING;\r
- }\r
-\r
- /* This is the first packet for this endpoint. Create the AV. */\r
- p_port = __endpt_parent( p_endpt );\r
-\r
- cl_memclr( &av_attr, sizeof(ib_av_attr_t) );\r
-\r
- av_attr.port_num = p_port->port_num;\r
-\r
- ib_member_get_sl_flow_hop(\r
- p_port->ib_mgr.bcast_rec.sl_flow_hop,\r
- &av_attr.sl,\r
- &flow_lbl,\r
- &av_attr.grh.hop_limit\r
- );\r
-\r
- av_attr.dlid = p_endpt->dlid;\r
-\r
- /*\r
- * We always send the GRH so that we preferably lookup endpoints\r
- * by GID rather than by LID. This allows certain WHQL tests\r
- * such as the 2c_MediaCheck test to succeed since they don't use\r
- * IP. This allows endpoints to be created on the fly for requests\r
- * for which there is no match, something that doesn't work when\r
- * using LIDs only.\r
- */\r
- av_attr.grh_valid = TRUE;\r
- av_attr.grh.ver_class_flow = ib_grh_set_ver_class_flow(\r
- 6, p_port->ib_mgr.bcast_rec.tclass, flow_lbl );\r
- av_attr.grh.resv1 = 0;\r
- av_attr.grh.resv2 = 0;\r
- ib_gid_set_default( &av_attr.grh.src_gid, p_port->p_adapter->guids.port_guid.guid );\r
- av_attr.grh.dest_gid = p_endpt->dgid;\r
-\r
- av_attr.static_rate = p_port->ib_mgr.bcast_rec.rate;\r
- av_attr.path_bits = 0;\r
-\r
- /* Create the AV. */\r
- status = p_port->p_adapter->p_ifc->create_av(\r
- p_port->ib_mgr.h_pd, &av_attr, &p_endpt->h_av );\r
- if( status != IB_SUCCESS )\r
- {\r
- p_port->p_adapter->hung = TRUE;\r
- ipoib_endpt_deref( p_endpt );\r
- cl_obj_unlock( &p_endpt->obj );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ib_create_av failed with %s\n", \r
- p_port->p_adapter->p_ifc->get_err_str( status )) );\r
- return NDIS_STATUS_FAILURE;\r
- }\r
-\r
- IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
- return NDIS_STATUS_SUCCESS;\r
-}\r
-\r
-#if 0\r
-\r
-static void\r
-__endpt_cm_buf_mgr_construct(\r
- IN endpt_buf_mgr_t * const p_buf_mgr )\r
-{\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-\r
- cl_qpool_construct( &p_buf_mgr->recv_pool );\r
-\r
- p_buf_mgr->h_packet_pool = NULL;\r
- p_buf_mgr->h_buffer_pool = NULL;\r
-\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
-}\r
-\r
-ib_api_status_t\r
-endpt_cm_buf_mgr_init(\r
- IN ipoib_port_t* const p_port )\r
-{\r
- cl_status_t cl_status;\r
- NDIS_STATUS ndis_status;\r
- ib_api_status_t ib_status = IB_SUCCESS;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-\r
- if( p_port->cm_buf_mgr.pool_init )\r
- return ib_status;\r
-\r
- cl_qlist_init( &p_port->cm_buf_mgr.posted_list );\r
-\r
- __endpt_cm_buf_mgr_construct( &p_port->cm_buf_mgr );\r
- p_port->cm_recv_mgr.rq_depth = \r
- min( (uint32_t)p_port->p_adapter->params.rq_depth * 8,\r
- p_port->p_ca_attrs->max_srq_wrs/2 );\r
- p_port->cm_recv_mgr.depth = 0;\r
- /* Allocate the receive descriptors pool */\r
- cl_status = cl_qpool_init( &p_port->cm_buf_mgr.recv_pool,\r
- p_port->cm_recv_mgr.rq_depth ,\r
- 0,\r
- 0,\r
- sizeof( ipoib_cm_desc_t ),\r
- __cm_recv_desc_ctor,\r
- __cm_recv_desc_dtor,\r
- p_port );\r
-\r
- if( cl_status != CL_SUCCESS )\r
- {\r
- NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
- EVENT_IPOIB_RECV_POOL, 1, cl_status );\r
- \r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("cl_qpool_init for cm recvs returned %#x\n", cl_status) );\r
- \r
- return IB_INSUFFICIENT_MEMORY;\r
- }\r
-\r
- /* Allocate the NDIS buffer and packet pools for receive indication. */\r
- NdisAllocatePacketPool( &ndis_status, \r
- &p_port->cm_buf_mgr.h_packet_pool,\r
- p_port->cm_recv_mgr.rq_depth, \r
- PROTOCOL_RESERVED_SIZE_IN_PACKET );\r
- if( ndis_status != NDIS_STATUS_SUCCESS )\r
- {\r
- NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
- EVENT_IPOIB_RECV_PKT_POOL, 1, ndis_status );\r
-\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("NdisAllocatePacketPool returned %08X\n", ndis_status) );\r
- \r
- ib_status = IB_INSUFFICIENT_RESOURCES;\r
- goto pkt_pool_failed;\r
- }\r
-\r
- NdisAllocateBufferPool( &ndis_status, \r
- &p_port->cm_buf_mgr.h_buffer_pool,\r
- p_port->cm_recv_mgr.rq_depth );\r
- if( ndis_status != NDIS_STATUS_SUCCESS )\r
- {\r
- NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
- EVENT_IPOIB_RECV_BUF_POOL, 1, ndis_status );\r
- \r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("NdisAllocateBufferPool returned %08X\n", ndis_status) );\r
- \r
- ib_status = IB_INSUFFICIENT_RESOURCES;\r
- goto buf_pool_failed;\r
- }\r
- //NDIS60\r
- //p_port->cm_recv_mgr.recv_pkt_array = \r
- //cl_zalloc( sizeof(NDIS_PACKET*) * p_port->cm_recv_mgr.rq_depth );\r
- p_port->cm_recv_mgr.recv_lst_array = \r
- cl_zalloc( sizeof(NET_BUFFER_LIST*) * p_port->cm_recv_mgr.rq_depth );\r
- \r
- \r
-\r
- if( !p_port->cm_recv_mgr.recv_pkt_array )\r
- {\r
- //NDIS60\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("cl_zalloc for NET_BUFFER_LIST array failed.\n") );\r
- \r
- ib_status = IB_INSUFFICIENT_MEMORY;\r
- goto pkt_array_failed;\r
- }\r
-\r
- p_port->cm_buf_mgr.pool_init = TRUE;\r
- return IB_SUCCESS;\r
-\r
-pkt_array_failed:\r
- if( p_port->cm_buf_mgr.h_buffer_pool )\r
- NdisFreeBufferPool( p_port->cm_buf_mgr.h_buffer_pool );\r
-buf_pool_failed:\r
- if( p_port->cm_buf_mgr.h_packet_pool )\r
- NdisFreePacketPool( p_port->cm_buf_mgr.h_packet_pool );\r
-pkt_pool_failed:\r
- cl_qpool_destroy( &p_port->cm_buf_mgr.recv_pool );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
- return ib_status;\r
-}\r
-\r
-void\r
-endpt_cm_buf_mgr_reset(\r
- IN ipoib_port_t* const p_port )\r
-{\r
- cl_list_item_t *p_item;\r
-\r
- if( !p_port->cm_buf_mgr.pool_init )\r
- return;\r
-\r
- if( cl_qlist_count( &p_port->cm_buf_mgr.posted_list ) )\r
- {\r
- for( p_item = cl_qlist_remove_head( &p_port->cm_buf_mgr.posted_list );\r
- p_item != cl_qlist_end( &p_port->cm_buf_mgr.posted_list );\r
- p_item = cl_qlist_remove_head( &p_port->cm_buf_mgr.posted_list ) )\r
- {\r
- cl_qpool_put( &p_port->cm_buf_mgr.recv_pool, \r
- &( PARENT_STRUCT( p_item, ipoib_cm_desc_t, list_item ))->item );\r
- }\r
- }\r
-}\r
-\r
-void\r
-endpt_cm_buf_mgr_destroy(\r
- IN ipoib_port_t* const p_port )\r
-{\r
-\r
- IPOIB_ENTER(IPOIB_DBG_INIT );\r
-\r
- CL_ASSERT( p_port );\r
- \r
- /* Free the receive descriptors. */\r
- if( !p_port->cm_buf_mgr.pool_init )\r
- return;\r
-\r
- endpt_cm_buf_mgr_reset( p_port );\r
-\r
- p_port->cm_buf_mgr.pool_init = FALSE;\r
- \r
- if( p_port->cm_recv_mgr.recv_pkt_array )\r
- {\r
- cl_free( p_port->cm_recv_mgr.recv_pkt_array );\r
- }\r
-\r
- /* Destroy the receive packet and buffer pools. */\r
- if( p_port->cm_buf_mgr.h_buffer_pool )\r
- NdisFreeBufferPool( p_port->cm_buf_mgr.h_buffer_pool );\r
- if( p_port->cm_buf_mgr.h_packet_pool )\r
- NdisFreePacketPool( p_port->cm_buf_mgr.h_packet_pool );\r
-\r
- cl_qpool_destroy( &p_port->cm_buf_mgr.recv_pool );\r
- \r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
-}\r
-\r
-static cl_status_t\r
-__cm_recv_desc_ctor(\r
- IN void* const p_object,\r
- IN void* context,\r
- OUT cl_pool_item_t** const pp_pool_item )\r
-{\r
- ipoib_cm_desc_t* p_desc;\r
- ipoib_port_t* p_port;\r
- ib_mr_create_t create_mr;\r
- net32_t rkey;\r
-\r
- CL_ASSERT( p_object );\r
- CL_ASSERT( context );\r
-\r
- p_desc = (ipoib_cm_desc_t*)p_object;\r
- p_port = (ipoib_port_t*)context;\r
-\r
-#define BUF_ALIGN (16)\r
-\r
- p_desc->alloc_buf_size = \r
- ROUNDUP( p_port->p_adapter->params.cm_xfer_block_size, BUF_ALIGN );\r
- \r
- p_desc->p_alloc_buf = (uint8_t *)ExAllocatePoolWithTag( \r
- NonPagedPool, p_desc->alloc_buf_size, 'DOMC' );\r
-\r
- if( p_desc->p_alloc_buf == NULL )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Failed to allocate receive buffer size %d bytes.\n", p_desc->alloc_buf_size ) );\r
- return CL_INSUFFICIENT_MEMORY;\r
- }\r
-\r
- create_mr.vaddr = p_desc->p_alloc_buf;\r
- create_mr.length = p_desc->alloc_buf_size;\r
- create_mr.access_ctrl = IB_AC_LOCAL_WRITE;\r
-\r
- \r
- if( p_port->p_adapter->p_ifc->reg_mem( \r
- p_port->ib_mgr.h_pd,\r
- &create_mr,\r
- &p_desc->lkey,\r
- &rkey,\r
- &p_desc->h_mr ) != IB_SUCCESS )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Failed to create Memory Region size %d bytes.\n", p_desc->alloc_buf_size ) );\r
- goto ctor_failed;\r
- }\r
- p_desc->p_buf = p_desc->p_alloc_buf + (BUF_ALIGN - sizeof( ipoib_hdr_t));\r
- p_desc->buf_size = p_desc->alloc_buf_size - (BUF_ALIGN - sizeof( ipoib_hdr_t));\r
-\r
- /* Setup the local data segment. */\r
- p_desc->local_ds[0].vaddr = (uint64_t)(uintn_t)p_desc->p_buf;\r
- p_desc->local_ds[0].length = p_desc->buf_size;\r
- p_desc->local_ds[0].lkey = p_desc->lkey;\r
-\r
- /* Setup the work request. */\r
- p_desc->wr.wr_id = (uintn_t)p_desc;\r
- p_desc->wr.ds_array = p_desc->local_ds;\r
- p_desc->wr.num_ds = 1;\r
- p_desc->type = PKT_TYPE_CM_UCAST;\r
- \r
- *pp_pool_item = &p_desc->item;\r
- return CL_SUCCESS;\r
-\r
-ctor_failed:\r
- ExFreePoolWithTag( p_desc->p_alloc_buf, 'DOMC' );\r
- return CL_INSUFFICIENT_MEMORY;\r
-}\r
-\r
-static void\r
-__cm_recv_desc_dtor(\r
- IN const cl_pool_item_t* const p_pool_item,\r
- IN void *context )\r
-{\r
- ipoib_cm_desc_t *p_desc;\r
- ipoib_port_t* p_port;\r
-\r
- if( p_pool_item == NULL || context == NULL )\r
- return;\r
-\r
- p_port = (ipoib_port_t*)context;\r
- p_desc = PARENT_STRUCT( p_pool_item, ipoib_cm_desc_t, item );\r
-\r
- if( p_desc->h_mr )\r
- p_port->p_adapter->p_ifc->dereg_mr( p_desc->h_mr );\r
-\r
- if( p_desc->p_alloc_buf )\r
- ExFreePoolWithTag( p_desc->p_alloc_buf, 'DOMC' );\r
-}\r
-\r
-\r
-static NDIS_PACKET*\r
-__endpt_cm_get_ndis_pkt(\r
- IN ipoib_port_t* const p_port,\r
- IN ipoib_cm_desc_t* const p_desc )\r
-{\r
- NDIS_STATUS status;\r
- NDIS_PACKET *p_packet;\r
- NDIS_BUFFER *p_buffer;\r
- \r
- IPOIB_ENTER( IPOIB_DBG_RECV );\r
-\r
- NdisDprAllocatePacketNonInterlocked( &status, &p_packet,\r
- p_port->cm_buf_mgr.h_packet_pool );\r
- if( status != NDIS_STATUS_SUCCESS )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Failed to allocate NDIS_PACKET: %08x\n", status) );\r
- return NULL;\r
- }\r
-\r
- IPOIB_PORT_FROM_PACKET( p_packet ) = p_port;\r
- IPOIB_RECV_FROM_PACKET( p_packet ) = p_desc;\r
-\r
- NdisAllocateBuffer( \r
- &status, \r
- &p_buffer,\r
- p_port->cm_buf_mgr.h_buffer_pool, \r
- (void *)(p_desc->p_buf - DATA_OFFSET),\r
- p_desc->len + DATA_OFFSET );\r
-\r
- if( status != NDIS_STATUS_SUCCESS )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Failed to allocate NDIS_BUFFER: %08x\n", status) );\r
- NdisDprFreePacketNonInterlocked( p_packet );\r
- return NULL;\r
- }\r
-\r
- NdisChainBufferAtFront( p_packet, p_buffer );\r
- NDIS_SET_PACKET_HEADER_SIZE( p_packet, sizeof(eth_hdr_t) );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_RECV );\r
- return p_packet;\r
-}\r
-\r
-static inline ipoib_cm_desc_t*\r
-__endpt_cm_buf_mgr_get_recv(\r
- IN endpt_buf_mgr_t * const p_buf_mgr )\r
-{\r
- ipoib_cm_desc_t *p_desc;\r
-\r
- p_desc = (ipoib_cm_desc_t*)cl_qpool_get( &p_buf_mgr->recv_pool );\r
- if( p_desc )\r
- cl_qlist_insert_tail( &p_buf_mgr->posted_list, &p_desc->list_item );\r
-\r
- return p_desc;\r
-}\r
-\r
-void\r
-endpt_cm_buf_mgr_put_recv(\r
- IN endpt_buf_mgr_t * const p_buf_mgr,\r
- IN ipoib_cm_desc_t* const p_desc )\r
-{\r
-\r
- IPOIB_ENTER(IPOIB_DBG_RECV );\r
-\r
- /* Return the descriptor to it's pool. */\r
- cl_qlist_remove_item( &p_buf_mgr->posted_list, &p_desc->list_item );\r
- cl_qpool_put( &p_buf_mgr->recv_pool, &p_desc->item );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_RECV );\r
-}\r
-\r
-void\r
-endpt_cm_buf_mgr_put_recv_list(\r
- IN endpt_buf_mgr_t * const p_buf_mgr,\r
- IN cl_qlist_t* const p_list )\r
-{\r
- cl_qpool_put_list( &p_buf_mgr->recv_pool, p_list );\r
-}\r
-\r
-uint32_t\r
-endpt_cm_recv_mgr_build_pkt_array(\r
- IN ipoib_port_t* const p_port,\r
- IN ipoib_endpt_t* const p_endpt,\r
- IN cl_qlist_t* const p_done_list,\r
- IN OUT uint32_t* p_bytes_recv )\r
-{\r
- cl_list_item_t *p_item;\r
- ipoib_cm_desc_t *p_desc;\r
- uint32_t i = 0;\r
- NDIS_PACKET *p_packet;\r
- NDIS_TCP_IP_CHECKSUM_PACKET_INFO chksum;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_RECV );\r
- UNUSED_PARAM( p_endpt );\r
-\r
- p_item = cl_qlist_remove_head( p_done_list );\r
- \r
- *p_bytes_recv = 0;\r
-\r
- for( p_item; p_item != cl_qlist_end( p_done_list );\r
- p_item = cl_qlist_remove_head( p_done_list ) )\r
- {\r
- p_desc = (ipoib_cm_desc_t*)p_item;\r
-\r
- p_packet = __endpt_cm_get_ndis_pkt( p_port, p_desc );\r
- if( !p_packet )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Failed to get Packet from descriptor\n" ) );\r
- endpt_cm_buf_mgr_put_recv( &p_port->cm_buf_mgr, p_desc );\r
- p_port->cm_recv_mgr.depth--;\r
- continue;\r
- }\r
- chksum.Value = 0;\r
- switch( p_port->p_adapter->params.recv_chksum_offload )\r
- {\r
- default:\r
- CL_ASSERT( FALSE );\r
- case CSUM_DISABLED:\r
- case CSUM_ENABLED:\r
- NDIS_PER_PACKET_INFO_FROM_PACKET( p_packet, TcpIpChecksumPacketInfo ) =\r
- (void*)(uintn_t)chksum.Value;\r
- break;\r
- case CSUM_BYPASS:\r
- /* Flag the checksums as having been calculated. */\r
- chksum.Receive.NdisPacketTcpChecksumSucceeded = TRUE;\r
- chksum.Receive.NdisPacketUdpChecksumSucceeded = TRUE;\r
- chksum.Receive.NdisPacketIpChecksumSucceeded = TRUE;\r
- NDIS_PER_PACKET_INFO_FROM_PACKET( p_packet, TcpIpChecksumPacketInfo ) =\r
- (void*)(uintn_t)chksum.Value;\r
- break;\r
- }\r
-\r
- NDIS_SET_PACKET_STATUS( p_packet, NDIS_STATUS_SUCCESS );\r
- p_port->cm_recv_mgr.recv_pkt_array[i] = p_packet;\r
- i++; \r
- *p_bytes_recv += p_desc->len;\r
- }\r
-\r
- IPOIB_EXIT( IPOIB_DBG_RECV );\r
- return i;\r
-}\r
-void\r
-endpt_cm_flush_recv(\r
- IN ipoib_port_t* const p_port,\r
- IN ipoib_endpt_t* const p_endpt )\r
-{\r
- ib_api_status_t ib_status = IB_SUCCESS;\r
- ib_qp_mod_t mod_attr;\r
- ib_wc_t wc[MAX_RECV_WC];\r
- ib_wc_t *p_free_wc;\r
- ib_wc_t *p_done_wc;\r
- ib_wc_t *p_wc;\r
- ipoib_cm_desc_t *p_desc;\r
- size_t i;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_RECV );\r
-\r
- CL_ASSERT( p_endpt );\r
-\r
- if( p_endpt->conn.h_recv_qp )\r
- {\r
- cl_memclr( &mod_attr, sizeof( mod_attr ) );\r
- mod_attr.req_state = IB_QPS_ERROR;\r
- p_port->p_adapter->p_ifc->modify_qp( p_endpt->conn.h_send_qp, &mod_attr );\r
- p_port->p_adapter->p_ifc->modify_qp( p_endpt->conn.h_recv_qp, &mod_attr );\r
-\r
- for( i = 0; i < MAX_RECV_WC; i++ )\r
- wc[i].p_next = &wc[i + 1];\r
- wc[MAX_RECV_WC - 1].p_next = NULL;\r
-\r
- do\r
- {\r
- p_free_wc = wc;\r
- ib_status = \r
- p_port->p_adapter->p_ifc->poll_cq( p_endpt->conn.h_recv_cq, \r
- &p_free_wc, &p_done_wc );\r
- if( ib_status != IB_SUCCESS && \r
- ib_status != IB_NOT_FOUND )\r
- {\r
- /* connection CQ failed */\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Poll Recv CQ failed status %#x\n", ib_status ) );\r
- break;\r
- }\r
- cl_spinlock_acquire( &p_port->recv_lock );\r
- for( p_wc = p_done_wc; p_wc; p_wc = p_wc->p_next )\r
- {\r
- p_desc = (ipoib_cm_desc_t *)(uintn_t)p_wc->wr_id;\r
- endpt_cm_buf_mgr_put_recv( &p_port->cm_buf_mgr, p_desc );\r
- p_port->cm_recv_mgr.depth--;\r
- }\r
- cl_spinlock_release( &p_port->recv_lock );\r
- } while( !p_free_wc );\r
-\r
- ib_status = p_port->p_adapter->p_ifc->destroy_qp( p_endpt->conn.h_recv_qp, NULL );\r
- if( ib_status != IB_SUCCESS )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Destroy Recv QP failed status %#x\n", ib_status ) );\r
- }\r
- p_endpt->conn.h_recv_qp = NULL;\r
- }\r
-\r
- if( p_endpt->conn.h_send_qp )\r
- {\r
- ib_status = p_port->p_adapter->p_ifc->destroy_qp( p_endpt->conn.h_send_qp, NULL );\r
- if( ib_status != IB_SUCCESS )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Destroy Send QP failed status %#x\n", ib_status ) );\r
- }\r
- p_endpt->conn.h_send_qp = NULL;\r
- }\r
-\r
- IPOIB_EXIT( IPOIB_DBG_RECV );\r
-}\r
-\r
-int32_t\r
-endpt_cm_recv_mgr_filter(\r
- IN ipoib_endpt_t* const p_endpt,\r
- IN ib_wc_t* const p_done_wc_list,\r
- OUT cl_qlist_t* const p_done_list,\r
- OUT cl_qlist_t* const p_bad_list )\r
-{\r
- ib_api_status_t ib_status;\r
- ipoib_cm_desc_t *p_desc;\r
- ib_wc_t *p_wc;\r
- ipoib_pkt_t *p_ipoib;\r
- eth_pkt_t *p_eth;\r
- ipoib_port_t* p_port;\r
- int32_t recv_cnt;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_RECV );\r
-\r
- p_port = ipoib_endpt_parent( p_endpt );\r
-\r
- for( p_wc = p_done_wc_list, recv_cnt = 0; p_wc; p_wc = p_wc->p_next )\r
- {\r
- p_desc = (ipoib_cm_desc_t *)(uintn_t)p_wc->wr_id;\r
- recv_cnt++;\r
- if( p_wc->status != IB_WCS_SUCCESS )\r
- {\r
- if( p_wc->status != IB_WCS_WR_FLUSHED_ERR )\r
- {\r
- \r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Failed completion %s (vendor specific %#x)\n",\r
- p_port->p_adapter->p_ifc->get_wc_status_str( p_wc->status ),\r
- (int)p_wc->vendor_specific) );\r
- }\r
- else\r
- {\r
- IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_RECV,\r
- ("Flushed completion %s\n",\r
- p_port->p_adapter->p_ifc->get_wc_status_str( p_wc->status )) );\r
- }\r
- \r
- ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_ERROR, 0, 0 );\r
-\r
- cl_qlist_remove_item( &p_port->cm_buf_mgr.posted_list,&p_desc->list_item );\r
- cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item );\r
- continue;\r
- }\r
-\r
- /* Successful completion \r
- Setup the ethernet/ip/arp header and queue descriptor for report. */\r
- ib_status = IB_SUCCESS;\r
- p_ipoib = (ipoib_pkt_t *)((uint8_t*)p_desc->p_buf );\r
- p_eth = (eth_pkt_t *)((uint8_t*)p_desc->p_buf - DATA_OFFSET );\r
- \r
- switch( p_ipoib->hdr.type )\r
- {\r
- case ETH_PROT_TYPE_ARP:\r
- if( p_wc->length < (sizeof(ipoib_hdr_t) + sizeof(ipoib_arp_pkt_t)) )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Received ARP packet too short\n") );\r
- ib_status = IB_ERROR;\r
- break;\r
- }\r
- ib_status = \r
- __endpt_cm_recv_arp( p_port, p_ipoib, p_eth, p_endpt );\r
- break;\r
- case ETH_PROT_TYPE_IP:\r
- if( p_wc->length < (sizeof(ipoib_hdr_t) + sizeof(ip_hdr_t)) )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Received IP packet too short\n") );\r
- ib_status = IB_ERROR;\r
- break;\r
- }\r
- if( p_ipoib->type.ip.hdr.prot == IP_PROT_UDP )\r
- {\r
- ib_status = \r
- __endpt_cm_recv_udp( p_port, p_wc, p_ipoib, p_eth, p_endpt );\r
- }\r
- \r
- break;\r
- }\r
-\r
- if( ib_status != IB_SUCCESS )\r
- {\r
- ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_ERROR, 0, 0 );\r
- cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item );\r
- continue;\r
- }\r
-\r
- p_eth->hdr.type = p_ipoib->hdr.type;\r
- p_eth->hdr.src = p_endpt->mac;\r
- p_eth->hdr.dst = p_port->p_adapter->mac;\r
-\r
- /* save payload length */\r
- p_desc->len = p_wc->length;\r
- \r
- cl_qlist_insert_tail( p_done_list, &p_desc->item.list_item );\r
- }\r
-\r
- IPOIB_EXIT( IPOIB_DBG_RECV );\r
- return recv_cnt;\r
-}\r
-\r
-ib_api_status_t\r
-endpt_cm_post_recv(\r
- IN ipoib_port_t* const p_port )\r
-{\r
- ib_api_status_t ib_status = IB_SUCCESS;\r
- ipoib_cm_desc_t *p_head_desc = NULL;\r
- ipoib_cm_desc_t *p_tail_desc = NULL;\r
- ipoib_cm_desc_t *p_next_desc;\r
- ib_recv_wr_t *p_failed_wc = NULL;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_RECV );\r
-\r
- while( cl_qpool_count( &p_port->cm_buf_mgr.recv_pool ) > 1 )\r
- {\r
- /* Pull receives out of the pool and chain them up. */\r
- p_next_desc = __endpt_cm_buf_mgr_get_recv( \r
- &p_port->cm_buf_mgr );\r
- if( !p_next_desc )\r
- {\r
- IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_RECV,\r
- ("Out of receive descriptors! Endpt recv queue depth 0x%x\n",\r
- p_port->cm_recv_mgr.depth ) );\r
- break;\r
- }\r
-\r
- if( !p_tail_desc )\r
- {\r
- p_tail_desc = p_next_desc;\r
- p_next_desc->wr.p_next = NULL;\r
- }\r
- else\r
- {\r
- p_next_desc->wr.p_next = &p_head_desc->wr;\r
- }\r
-\r
- p_head_desc = p_next_desc;\r
-\r
- p_port->cm_recv_mgr.depth++;\r
- }\r
-\r
- if( p_head_desc )\r
- {\r
- ib_status = p_port->p_adapter->p_ifc->post_srq_recv(\r
- p_port->ib_mgr.h_srq, &p_head_desc->wr, &p_failed_wc );\r
-\r
- if( ib_status != IB_SUCCESS )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ip_post_recv returned %s\n", \r
- p_port->p_adapter->p_ifc->get_err_str( ib_status )) );\r
- \r
- /* put descriptors back to the pool */\r
- while( p_failed_wc )\r
- {\r
- p_head_desc = PARENT_STRUCT( p_failed_wc, ipoib_cm_desc_t, wr );\r
- p_failed_wc = p_failed_wc->p_next;\r
- endpt_cm_buf_mgr_put_recv( &p_port->cm_buf_mgr, p_head_desc );\r
- p_port->cm_recv_mgr.depth--;\r
- }\r
- }\r
- }\r
-\r
-\r
- IPOIB_EXIT( IPOIB_DBG_RECV );\r
- return( ib_status );\r
-}\r
-\r
-static ib_api_status_t\r
-__endpt_cm_recv_arp(\r
- IN ipoib_port_t* const p_port,\r
- IN const ipoib_pkt_t* const p_ipoib,\r
- OUT eth_pkt_t* const p_eth,\r
- IN ipoib_endpt_t* const p_src_endpt )\r
-{\r
- const ipoib_arp_pkt_t *p_ib_arp;\r
- arp_pkt_t *p_arp;\r
- \r
- p_ib_arp = &p_ipoib->type.arp;\r
- p_arp = &p_eth->type.arp;\r
- \r
- if( p_ib_arp->hw_type != ARP_HW_TYPE_IB ||\r
- p_ib_arp->hw_size != sizeof(ipoib_hw_addr_t) ||\r
- p_ib_arp->prot_type != ETH_PROT_TYPE_IP )\r
- {\r
- return IB_ERROR;\r
- }\r
- \r
- p_arp->hw_type = ARP_HW_TYPE_ETH;\r
- p_arp->hw_size = sizeof(mac_addr_t);\r
- p_arp->src_hw = p_src_endpt->mac;\r
- p_arp->src_ip = p_ib_arp->src_ip;\r
- p_arp->dst_hw = p_port->p_local_endpt->mac;\r
- p_arp->dst_ip = p_ib_arp->dst_ip;\r
-\r
- return IB_SUCCESS; \r
-}\r
-\r
-static ib_api_status_t\r
-__endpt_cm_recv_udp(\r
- IN ipoib_port_t* const p_port,\r
- IN ib_wc_t* const p_wc,\r
- IN const ipoib_pkt_t* const p_ipoib,\r
- OUT eth_pkt_t* const p_eth,\r
- IN ipoib_endpt_t* const p_src_endpt )\r
-{\r
- ib_api_status_t ib_status = IB_SUCCESS;\r
-\r
- if( p_wc->length <\r
- (sizeof(ipoib_hdr_t) + sizeof(ip_hdr_t) + sizeof(udp_hdr_t)) )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Received UDP packet too short\n") );\r
- return IB_ERROR;\r
- }\r
- if( __cm_recv_is_dhcp( p_ipoib ) )\r
- {\r
- ib_status = ipoib_recv_dhcp(\r
- p_port, p_ipoib, p_eth, p_src_endpt, p_port->p_local_endpt );\r
- }\r
-\r
- return ib_status;\r
-}\r
-\r
-static boolean_t\r
-__cm_recv_is_dhcp(\r
- IN const ipoib_pkt_t* const p_ipoib )\r
-{\r
- return( (p_ipoib->type.ip.prot.udp.hdr.dst_port == DHCP_PORT_SERVER &&\r
- p_ipoib->type.ip.prot.udp.hdr.src_port == DHCP_PORT_CLIENT) ||\r
- (p_ipoib->type.ip.prot.udp.hdr.dst_port == DHCP_PORT_CLIENT &&\r
- p_ipoib->type.ip.prot.udp.hdr.src_port == DHCP_PORT_SERVER) );\r
-}\r
-#endif\r
--- /dev/null
+/*\r
+ * Copyright (c) 2005 SilverStorm Technologies. All rights reserved.\r
+ * Copyright (c) 2006 Mellanox Technologies. All rights reserved.\r
+ * Portions Copyright (c) 2008 Microsoft Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ * - Redistributions of source code must retain the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer.\r
+ *\r
+ * - Redistributions in binary form must reproduce the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer in the documentation and/or other materials\r
+ * provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id: ipoib_endpoint.c 4226 2009-04-06 06:01:03Z xalex $\r
+ */\r
+\r
+\r
+\r
+#include "ipoib_endpoint.h"\r
+#include "ipoib_port.h"\r
+#include "ipoib_debug.h"\r
+#if defined(EVENT_TRACING)\r
+#ifdef offsetof\r
+#undef offsetof\r
+#endif\r
+#include "ipoib_endpoint.tmh"\r
+#endif\r
+#include <complib/cl_atomic.h>\r
+#include <complib/cl_math.h>\r
+\r
+\r
+static void\r
+__endpt_destroying(\r
+ IN cl_obj_t* p_obj );\r
+\r
+static void\r
+__endpt_cleanup(\r
+ IN cl_obj_t* p_obj );\r
+\r
+static void\r
+__endpt_free(\r
+ IN cl_obj_t* p_obj );\r
+\r
+static ib_api_status_t\r
+__create_mcast_av(\r
+ IN ib_pd_handle_t h_pd,\r
+ IN uint8_t port_num,\r
+ IN ib_member_rec_t* const p_member_rec,\r
+ OUT ib_av_handle_t* const ph_av );\r
+\r
+static inline ipoib_port_t*\r
+__endpt_parent(\r
+ IN ipoib_endpt_t* const p_endpt );\r
+\r
+static void\r
+__path_query_cb(\r
+ IN ib_query_rec_t *p_query_rec );\r
+\r
+static void\r
+__endpt_resolve(\r
+ IN ipoib_endpt_t* const p_endpt );\r
+\r
+static void\r
+__endpt_cm_send_cb(\r
+ IN const ib_cq_handle_t h_cq,\r
+ IN void *cq_context );\r
+static void\r
+__endpt_cm_recv_cb(\r
+ IN const ib_cq_handle_t h_cq,\r
+ IN void *cq_context );\r
+\r
+static void\r
+__endpt_cm_buf_mgr_construct(\r
+ IN endpt_buf_mgr_t * const p_buf_mgr );\r
+static void\r
+__conn_reply_cb(\r
+ IN ib_cm_rep_rec_t *p_cm_rep );\r
+\r
+static void\r
+__conn_mra_cb(\r
+ IN ib_cm_mra_rec_t *p_mra_rec );\r
+\r
+static void\r
+__conn_rej_cb(\r
+ IN ib_cm_rej_rec_t *p_rej_rec );\r
+\r
+static void\r
+__conn_dreq_cb(\r
+ IN ib_cm_dreq_rec_t *p_dreq_rec );\r
+\r
+#if 0 //CM\r
+static cl_status_t\r
+__cm_recv_desc_ctor(\r
+ IN void* const p_object,\r
+ IN void* context,\r
+ OUT cl_pool_item_t** const pp_pool_item );\r
+\r
+static void\r
+__cm_recv_desc_dtor(\r
+ IN const cl_pool_item_t* const p_pool_item,\r
+ IN void *context );\r
+\r
+static NDIS_PACKET*\r
+__endpt_cm_get_ndis_pkt(\r
+ IN ipoib_port_t* const p_port,\r
+ IN ipoib_cm_desc_t* const p_desc );\r
+\r
+static inline ipoib_cm_desc_t*\r
+__endpt_cm_buf_mgr_get_recv(\r
+ IN endpt_buf_mgr_t * const p_buf_mgr );\r
+\r
+static boolean_t\r
+__cm_recv_is_dhcp(\r
+ IN const ipoib_pkt_t* const p_ipoib );\r
+\r
+static ib_api_status_t\r
+__endpt_cm_recv_arp(\r
+ IN ipoib_port_t* const p_port,\r
+ IN const ipoib_pkt_t* const p_ipoib,\r
+ OUT eth_pkt_t* const p_eth,\r
+ IN ipoib_endpt_t* const p_src_endpt );\r
+\r
+static ib_api_status_t\r
+__endpt_cm_recv_udp(\r
+ IN ipoib_port_t* const p_port,\r
+ IN ib_wc_t* const p_wc,\r
+ IN const ipoib_pkt_t* const p_ipoib,\r
+ OUT eth_pkt_t* const p_eth,\r
+ IN ipoib_endpt_t* const p_src_endpt );\r
+#endif\r
+\r
+ipoib_endpt_t*\r
+ipoib_endpt_create(\r
+ IN const ib_gid_t* const p_dgid,\r
+ IN const net16_t dlid,\r
+ IN const net32_t qpn )\r
+{\r
+ ipoib_endpt_t *p_endpt;\r
+ cl_status_t status;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+ p_endpt = (ipoib_endpt_t *) cl_zalloc( sizeof(ipoib_endpt_t) );\r
+ if( !p_endpt )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed to allocate endpoint (%d bytes)\n",\r
+ sizeof(ipoib_endpt_t)) );\r
+ return NULL;\r
+ }\r
+\r
+ cl_obj_construct( &p_endpt->obj, IPOIB_OBJ_ENDPOINT );\r
+\r
+ status = cl_obj_init( &p_endpt->obj, CL_DESTROY_ASYNC,\r
+ __endpt_destroying, __endpt_cleanup, __endpt_free );\r
+\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
+ ("Created endpoint: [ %p ] DLID: %#x QPN: %#x \n", \r
+ p_endpt, cl_ntoh16(dlid), cl_ntoh32(qpn) ) );\r
+\r
+ p_endpt->dgid = *p_dgid;\r
+ p_endpt->dlid = dlid;\r
+ p_endpt->qpn = qpn;\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+ return p_endpt;\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__create_mcast_av(\r
+ IN ib_pd_handle_t h_pd,\r
+ IN uint8_t port_num,\r
+ IN ib_member_rec_t* const p_member_rec,\r
+ OUT ib_av_handle_t* const ph_av )\r
+{\r
+ ib_av_attr_t av_attr;\r
+ uint32_t flow_lbl;\r
+ uint8_t hop_lmt;\r
+ ib_api_status_t status;\r
+ ipoib_endpt_t *p_endpt;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_MCAST );\r
+\r
+ p_endpt = PARENT_STRUCT(ph_av, ipoib_endpt_t, h_av );\r
+\r
+ cl_memclr( &av_attr, sizeof(ib_av_attr_t) );\r
+ av_attr.port_num = port_num;\r
+ ib_member_get_sl_flow_hop( p_member_rec->sl_flow_hop,\r
+ &av_attr.sl, &flow_lbl, &hop_lmt );\r
+ av_attr.dlid = p_member_rec->mlid;\r
+ av_attr.grh_valid = TRUE;\r
+ av_attr.grh.hop_limit = hop_lmt;\r
+ av_attr.grh.dest_gid = p_member_rec->mgid;\r
+ av_attr.grh.src_gid = p_member_rec->port_gid;\r
+ av_attr.grh.ver_class_flow =\r
+ ib_grh_set_ver_class_flow( 6, p_member_rec->tclass, flow_lbl );\r
+ av_attr.static_rate = p_member_rec->rate & IB_PATH_REC_BASE_MASK;\r
+ av_attr.path_bits = 0;\r
+ /* port is not attached to endpoint at this point, so use endpt ifc reference */\r
+ status = p_endpt->p_ifc->create_av( h_pd, &av_attr, ph_av );\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ib_create_av returned %s\n",\r
+ p_endpt->p_ifc->get_err_str( status )) );\r
+ }\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_MCAST );\r
+ return status;\r
+}\r
+\r
+\r
+ib_api_status_t\r
+ipoib_endpt_set_mcast(\r
+ IN ipoib_endpt_t* const p_endpt,\r
+ IN ib_pd_handle_t h_pd,\r
+ IN uint8_t port_num,\r
+ IN ib_mcast_rec_t* const p_mcast_rec )\r
+{\r
+ ib_api_status_t status;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+ IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
+ ("Create av for MAC: %02X-%02X-%02X-%02X-%02X-%02X\n",\r
+ p_endpt->mac.addr[0], p_endpt->mac.addr[1],\r
+ p_endpt->mac.addr[2], p_endpt->mac.addr[3],\r
+ p_endpt->mac.addr[4], p_endpt->mac.addr[5]) );\r
+ \r
+ status = __create_mcast_av( h_pd, port_num, p_mcast_rec->p_member_rec,\r
+ &p_endpt->h_av );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("__create_mcast_av returned %s\n", \r
+ p_endpt->p_ifc->get_err_str( status )) );\r
+ return status;\r
+ }\r
+ p_endpt->h_mcast = p_mcast_rec->h_mcast;\r
+ CL_ASSERT(p_endpt->dlid == 0);\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+ return IB_SUCCESS;\r
+}\r
+\r
+\r
+static void\r
+__endpt_destroying(\r
+ IN cl_obj_t* p_obj )\r
+{\r
+ ipoib_endpt_t *p_endpt;\r
+ ipoib_port_t *p_port;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+ p_endpt = PARENT_STRUCT( p_obj, ipoib_endpt_t, obj );\r
+ p_port = __endpt_parent( p_endpt );\r
+\r
+ cl_obj_lock( p_obj );\r
+ if( p_endpt->h_query )\r
+ {\r
+ p_port->p_adapter->p_ifc->cancel_query(\r
+ p_port->p_adapter->h_al, p_endpt->h_query );\r
+ p_endpt->h_query = NULL;\r
+ }\r
+\r
+ /* Leave the multicast group if it exists. */\r
+ if( p_endpt->h_mcast )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
+ ("Leaving MCast group\n") );\r
+ ipoib_port_ref(p_port, ref_leave_mcast);\r
+ p_port->p_adapter->p_ifc->leave_mcast( p_endpt->h_mcast, ipoib_leave_mcast_cb );\r
+ }\r
+#if 0\r
+ else if( p_port->p_adapter->params.cm_enabled )\r
+ {\r
+ p_endpt->cm_flag = 0;\r
+ CL_ASSERT( endpt_cm_get_state( p_endpt ) == IPOIB_CM_DISCONNECTED );\r
+ }\r
+#endif\r
+\r
+ cl_obj_unlock( p_obj );\r
+ \r
+ IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+}\r
+\r
+\r
+static void\r
+__endpt_cleanup(\r
+ IN cl_obj_t* p_obj )\r
+{\r
+ ipoib_endpt_t *p_endpt;\r
+ ipoib_port_t *p_port;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+ p_endpt = PARENT_STRUCT( p_obj, ipoib_endpt_t, obj );\r
+ p_port = __endpt_parent( p_endpt );\r
+\r
+ /* Destroy the AV if it exists. */\r
+ if( p_endpt->h_av )\r
+ p_port->p_adapter->p_ifc->destroy_av( p_endpt->h_av );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+}\r
+\r
+\r
+static void\r
+__endpt_free(\r
+ IN cl_obj_t* p_obj )\r
+{\r
+ ipoib_endpt_t *p_endpt;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+ p_endpt = PARENT_STRUCT( p_obj, ipoib_endpt_t, obj );\r
+\r
+ cl_obj_deinit( p_obj );\r
+ cl_free( p_endpt );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+}\r
+\r
+\r
+static inline ipoib_port_t*\r
+__endpt_parent(\r
+ IN ipoib_endpt_t* const p_endpt )\r
+{\r
+ return PARENT_STRUCT( p_endpt->rel.p_parent_obj, ipoib_port_t, obj );\r
+}\r
+\r
+ipoib_port_t*\r
+ipoib_endpt_parent(\r
+ IN ipoib_endpt_t* const p_endpt )\r
+{\r
+ return __endpt_parent( p_endpt );\r
+}\r
+\r
+/*\r
+ * This function is called with the port object's send lock held and\r
+ * a reference held on the endpoint. If we fail, we release the reference.\r
+ */\r
+NDIS_STATUS\r
+ipoib_endpt_queue(\r
+ IN ipoib_endpt_t* const p_endpt )\r
+{\r
+ ib_api_status_t status;\r
+ ipoib_port_t *p_port;\r
+ ib_av_attr_t av_attr;\r
+ net32_t flow_lbl;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+ if( p_endpt->h_av )\r
+ {\r
+ IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+ return NDIS_STATUS_SUCCESS;\r
+ }\r
+\r
+ if( p_endpt->qpn == CL_HTON32(0x00FFFFFF) )\r
+ {\r
+ /*\r
+ * Handle a race between the mcast callback and a receive/send. The QP\r
+ * is joined to the MC group before the MC callback is received, so it\r
+ * can receive packets, and NDIS can try to respond. We need to delay\r
+ * a response until the MC callback runs and sets the AV.\r
+ */\r
+ ipoib_endpt_deref( p_endpt );\r
+ IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+ return NDIS_STATUS_PENDING;\r
+ }\r
+\r
+ /* This is the first packet for this endpoint. Create the AV. */\r
+ p_port = __endpt_parent( p_endpt );\r
+\r
+ cl_memclr( &av_attr, sizeof(ib_av_attr_t) );\r
+\r
+ av_attr.port_num = p_port->port_num;\r
+\r
+ ib_member_get_sl_flow_hop(\r
+ p_port->ib_mgr.bcast_rec.sl_flow_hop,\r
+ &av_attr.sl,\r
+ &flow_lbl,\r
+ &av_attr.grh.hop_limit\r
+ );\r
+\r
+ av_attr.dlid = p_endpt->dlid;\r
+\r
+ /*\r
+ * We always send the GRH so that we preferably lookup endpoints\r
+ * by GID rather than by LID. This allows certain WHQL tests\r
+ * such as the 2c_MediaCheck test to succeed since they don't use\r
+ * IP. This allows endpoints to be created on the fly for requests\r
+ * for which there is no match, something that doesn't work when\r
+ * using LIDs only.\r
+ */\r
+ av_attr.grh_valid = TRUE;\r
+ av_attr.grh.ver_class_flow = ib_grh_set_ver_class_flow(\r
+ 6, p_port->ib_mgr.bcast_rec.tclass, flow_lbl );\r
+ av_attr.grh.resv1 = 0;\r
+ av_attr.grh.resv2 = 0;\r
+ ib_gid_set_default( &av_attr.grh.src_gid, p_port->p_adapter->guids.port_guid.guid );\r
+ av_attr.grh.dest_gid = p_endpt->dgid;\r
+\r
+ av_attr.static_rate = p_port->ib_mgr.bcast_rec.rate;\r
+ av_attr.path_bits = 0;\r
+\r
+ /* Create the AV. */\r
+ status = p_port->p_adapter->p_ifc->create_av(\r
+ p_port->ib_mgr.h_pd, &av_attr, &p_endpt->h_av );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ p_port->p_adapter->hung = TRUE;\r
+ ipoib_endpt_deref( p_endpt );\r
+ cl_obj_unlock( &p_endpt->obj );\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ib_create_av failed with %s\n", \r
+ p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+ return NDIS_STATUS_FAILURE;\r
+ }\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+ return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+#if 0\r
+\r
+static void\r
+__endpt_cm_buf_mgr_construct(\r
+ IN endpt_buf_mgr_t * const p_buf_mgr )\r
+{\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+ cl_qpool_construct( &p_buf_mgr->recv_pool );\r
+\r
+ p_buf_mgr->h_packet_pool = NULL;\r
+ p_buf_mgr->h_buffer_pool = NULL;\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+ib_api_status_t\r
+endpt_cm_buf_mgr_init(\r
+ IN ipoib_port_t* const p_port )\r
+{\r
+ cl_status_t cl_status;\r
+ NDIS_STATUS ndis_status;\r
+ ib_api_status_t ib_status = IB_SUCCESS;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+ if( p_port->cm_buf_mgr.pool_init )\r
+ return ib_status;\r
+\r
+ cl_qlist_init( &p_port->cm_buf_mgr.posted_list );\r
+\r
+ __endpt_cm_buf_mgr_construct( &p_port->cm_buf_mgr );\r
+ p_port->cm_recv_mgr.rq_depth = \r
+ min( (uint32_t)p_port->p_adapter->params.rq_depth * 8,\r
+ p_port->p_ca_attrs->max_srq_wrs/2 );\r
+ p_port->cm_recv_mgr.depth = 0;\r
+ /* Allocate the receive descriptors pool */\r
+ cl_status = cl_qpool_init( &p_port->cm_buf_mgr.recv_pool,\r
+ p_port->cm_recv_mgr.rq_depth ,\r
+ 0,\r
+ 0,\r
+ sizeof( ipoib_cm_desc_t ),\r
+ __cm_recv_desc_ctor,\r
+ __cm_recv_desc_dtor,\r
+ p_port );\r
+\r
+ if( cl_status != CL_SUCCESS )\r
+ {\r
+ NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+ EVENT_IPOIB_RECV_POOL, 1, cl_status );\r
+ \r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("cl_qpool_init for cm recvs returned %#x\n", cl_status) );\r
+ \r
+ return IB_INSUFFICIENT_MEMORY;\r
+ }\r
+\r
+ /* Allocate the NDIS buffer and packet pools for receive indication. */\r
+ NdisAllocatePacketPool( &ndis_status, \r
+ &p_port->cm_buf_mgr.h_packet_pool,\r
+ p_port->cm_recv_mgr.rq_depth, \r
+ PROTOCOL_RESERVED_SIZE_IN_PACKET );\r
+ if( ndis_status != NDIS_STATUS_SUCCESS )\r
+ {\r
+ NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+ EVENT_IPOIB_RECV_PKT_POOL, 1, ndis_status );\r
+\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("NdisAllocatePacketPool returned %08X\n", ndis_status) );\r
+ \r
+ ib_status = IB_INSUFFICIENT_RESOURCES;\r
+ goto pkt_pool_failed;\r
+ }\r
+\r
+ NdisAllocateBufferPool( &ndis_status, \r
+ &p_port->cm_buf_mgr.h_buffer_pool,\r
+ p_port->cm_recv_mgr.rq_depth );\r
+ if( ndis_status != NDIS_STATUS_SUCCESS )\r
+ {\r
+ NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+ EVENT_IPOIB_RECV_BUF_POOL, 1, ndis_status );\r
+ \r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("NdisAllocateBufferPool returned %08X\n", ndis_status) );\r
+ \r
+ ib_status = IB_INSUFFICIENT_RESOURCES;\r
+ goto buf_pool_failed;\r
+ }\r
+ //NDIS60\r
+ //p_port->cm_recv_mgr.recv_pkt_array = \r
+ //cl_zalloc( sizeof(NDIS_PACKET*) * p_port->cm_recv_mgr.rq_depth );\r
+ p_port->cm_recv_mgr.recv_lst_array = \r
+ cl_zalloc( sizeof(NET_BUFFER_LIST*) * p_port->cm_recv_mgr.rq_depth );\r
+ \r
+ \r
+\r
+ if( !p_port->cm_recv_mgr.recv_pkt_array )\r
+ {\r
+ //NDIS60\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("cl_zalloc for NET_BUFFER_LIST array failed.\n") );\r
+ \r
+ ib_status = IB_INSUFFICIENT_MEMORY;\r
+ goto pkt_array_failed;\r
+ }\r
+\r
+ p_port->cm_buf_mgr.pool_init = TRUE;\r
+ return IB_SUCCESS;\r
+\r
+pkt_array_failed:\r
+ if( p_port->cm_buf_mgr.h_buffer_pool )\r
+ NdisFreeBufferPool( p_port->cm_buf_mgr.h_buffer_pool );\r
+buf_pool_failed:\r
+ if( p_port->cm_buf_mgr.h_packet_pool )\r
+ NdisFreePacketPool( p_port->cm_buf_mgr.h_packet_pool );\r
+pkt_pool_failed:\r
+ cl_qpool_destroy( &p_port->cm_buf_mgr.recv_pool );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+ return ib_status;\r
+}\r
+\r
+void\r
+endpt_cm_buf_mgr_reset(\r
+ IN ipoib_port_t* const p_port )\r
+{\r
+ cl_list_item_t *p_item;\r
+\r
+ if( !p_port->cm_buf_mgr.pool_init )\r
+ return;\r
+\r
+ if( cl_qlist_count( &p_port->cm_buf_mgr.posted_list ) )\r
+ {\r
+ for( p_item = cl_qlist_remove_head( &p_port->cm_buf_mgr.posted_list );\r
+ p_item != cl_qlist_end( &p_port->cm_buf_mgr.posted_list );\r
+ p_item = cl_qlist_remove_head( &p_port->cm_buf_mgr.posted_list ) )\r
+ {\r
+ cl_qpool_put( &p_port->cm_buf_mgr.recv_pool, \r
+ &( PARENT_STRUCT( p_item, ipoib_cm_desc_t, list_item ))->item );\r
+ }\r
+ }\r
+}\r
+\r
+void\r
+endpt_cm_buf_mgr_destroy(\r
+ IN ipoib_port_t* const p_port )\r
+{\r
+\r
+ IPOIB_ENTER(IPOIB_DBG_INIT );\r
+\r
+ CL_ASSERT( p_port );\r
+ \r
+ /* Free the receive descriptors. */\r
+ if( !p_port->cm_buf_mgr.pool_init )\r
+ return;\r
+\r
+ endpt_cm_buf_mgr_reset( p_port );\r
+\r
+ p_port->cm_buf_mgr.pool_init = FALSE;\r
+ \r
+ if( p_port->cm_recv_mgr.recv_pkt_array )\r
+ {\r
+ cl_free( p_port->cm_recv_mgr.recv_pkt_array );\r
+ }\r
+\r
+ /* Destroy the receive packet and buffer pools. */\r
+ if( p_port->cm_buf_mgr.h_buffer_pool )\r
+ NdisFreeBufferPool( p_port->cm_buf_mgr.h_buffer_pool );\r
+ if( p_port->cm_buf_mgr.h_packet_pool )\r
+ NdisFreePacketPool( p_port->cm_buf_mgr.h_packet_pool );\r
+\r
+ cl_qpool_destroy( &p_port->cm_buf_mgr.recv_pool );\r
+ \r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+static cl_status_t\r
+__cm_recv_desc_ctor(\r
+ IN void* const p_object,\r
+ IN void* context,\r
+ OUT cl_pool_item_t** const pp_pool_item )\r
+{\r
+ ipoib_cm_desc_t* p_desc;\r
+ ipoib_port_t* p_port;\r
+ ib_mr_create_t create_mr;\r
+ net32_t rkey;\r
+\r
+ CL_ASSERT( p_object );\r
+ CL_ASSERT( context );\r
+\r
+ p_desc = (ipoib_cm_desc_t*)p_object;\r
+ p_port = (ipoib_port_t*)context;\r
+\r
+#define BUF_ALIGN (16)\r
+\r
+ p_desc->alloc_buf_size = \r
+ ROUNDUP( p_port->p_adapter->params.cm_xfer_block_size, BUF_ALIGN );\r
+ \r
+ p_desc->p_alloc_buf = (uint8_t *)ExAllocatePoolWithTag( \r
+ NonPagedPool, p_desc->alloc_buf_size, 'DOMC' );\r
+\r
+ if( p_desc->p_alloc_buf == NULL )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed to allocate receive buffer size %d bytes.\n", p_desc->alloc_buf_size ) );\r
+ return CL_INSUFFICIENT_MEMORY;\r
+ }\r
+\r
+ create_mr.vaddr = p_desc->p_alloc_buf;\r
+ create_mr.length = p_desc->alloc_buf_size;\r
+ create_mr.access_ctrl = IB_AC_LOCAL_WRITE;\r
+\r
+ \r
+ if( p_port->p_adapter->p_ifc->reg_mem( \r
+ p_port->ib_mgr.h_pd,\r
+ &create_mr,\r
+ &p_desc->lkey,\r
+ &rkey,\r
+ &p_desc->h_mr ) != IB_SUCCESS )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed to create Memory Region size %d bytes.\n", p_desc->alloc_buf_size ) );\r
+ goto ctor_failed;\r
+ }\r
+ p_desc->p_buf = p_desc->p_alloc_buf + (BUF_ALIGN - sizeof( ipoib_hdr_t));\r
+ p_desc->buf_size = p_desc->alloc_buf_size - (BUF_ALIGN - sizeof( ipoib_hdr_t));\r
+\r
+ /* Setup the local data segment. */\r
+ p_desc->local_ds[0].vaddr = (uint64_t)(uintn_t)p_desc->p_buf;\r
+ p_desc->local_ds[0].length = p_desc->buf_size;\r
+ p_desc->local_ds[0].lkey = p_desc->lkey;\r
+\r
+ /* Setup the work request. */\r
+ p_desc->wr.wr_id = (uintn_t)p_desc;\r
+ p_desc->wr.ds_array = p_desc->local_ds;\r
+ p_desc->wr.num_ds = 1;\r
+ p_desc->type = PKT_TYPE_CM_UCAST;\r
+ \r
+ *pp_pool_item = &p_desc->item;\r
+ return CL_SUCCESS;\r
+\r
+ctor_failed:\r
+ ExFreePoolWithTag( p_desc->p_alloc_buf, 'DOMC' );\r
+ return CL_INSUFFICIENT_MEMORY;\r
+}\r
+\r
+static void\r
+__cm_recv_desc_dtor(\r
+ IN const cl_pool_item_t* const p_pool_item,\r
+ IN void *context )\r
+{\r
+ ipoib_cm_desc_t *p_desc;\r
+ ipoib_port_t* p_port;\r
+\r
+ if( p_pool_item == NULL || context == NULL )\r
+ return;\r
+\r
+ p_port = (ipoib_port_t*)context;\r
+ p_desc = PARENT_STRUCT( p_pool_item, ipoib_cm_desc_t, item );\r
+\r
+ if( p_desc->h_mr )\r
+ p_port->p_adapter->p_ifc->dereg_mr( p_desc->h_mr );\r
+\r
+ if( p_desc->p_alloc_buf )\r
+ ExFreePoolWithTag( p_desc->p_alloc_buf, 'DOMC' );\r
+}\r
+\r
+\r
+static NDIS_PACKET*\r
+__endpt_cm_get_ndis_pkt(\r
+ IN ipoib_port_t* const p_port,\r
+ IN ipoib_cm_desc_t* const p_desc )\r
+{\r
+ NDIS_STATUS status;\r
+ NDIS_PACKET *p_packet;\r
+ NDIS_BUFFER *p_buffer;\r
+ \r
+ IPOIB_ENTER( IPOIB_DBG_RECV );\r
+\r
+ NdisDprAllocatePacketNonInterlocked( &status, &p_packet,\r
+ p_port->cm_buf_mgr.h_packet_pool );\r
+ if( status != NDIS_STATUS_SUCCESS )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed to allocate NDIS_PACKET: %08x\n", status) );\r
+ return NULL;\r
+ }\r
+\r
+ IPOIB_PORT_FROM_PACKET( p_packet ) = p_port;\r
+ IPOIB_RECV_FROM_PACKET( p_packet ) = p_desc;\r
+\r
+ NdisAllocateBuffer( \r
+ &status, \r
+ &p_buffer,\r
+ p_port->cm_buf_mgr.h_buffer_pool, \r
+ (void *)(p_desc->p_buf - DATA_OFFSET),\r
+ p_desc->len + DATA_OFFSET );\r
+\r
+ if( status != NDIS_STATUS_SUCCESS )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed to allocate NDIS_BUFFER: %08x\n", status) );\r
+ NdisDprFreePacketNonInterlocked( p_packet );\r
+ return NULL;\r
+ }\r
+\r
+ NdisChainBufferAtFront( p_packet, p_buffer );\r
+ NDIS_SET_PACKET_HEADER_SIZE( p_packet, sizeof(eth_hdr_t) );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_RECV );\r
+ return p_packet;\r
+}\r
+\r
+static inline ipoib_cm_desc_t*\r
+__endpt_cm_buf_mgr_get_recv(\r
+ IN endpt_buf_mgr_t * const p_buf_mgr )\r
+{\r
+ ipoib_cm_desc_t *p_desc;\r
+\r
+ p_desc = (ipoib_cm_desc_t*)cl_qpool_get( &p_buf_mgr->recv_pool );\r
+ if( p_desc )\r
+ cl_qlist_insert_tail( &p_buf_mgr->posted_list, &p_desc->list_item );\r
+\r
+ return p_desc;\r
+}\r
+\r
+void\r
+endpt_cm_buf_mgr_put_recv(\r
+ IN endpt_buf_mgr_t * const p_buf_mgr,\r
+ IN ipoib_cm_desc_t* const p_desc )\r
+{\r
+\r
+ IPOIB_ENTER(IPOIB_DBG_RECV );\r
+\r
+ /* Return the descriptor to it's pool. */\r
+ cl_qlist_remove_item( &p_buf_mgr->posted_list, &p_desc->list_item );\r
+ cl_qpool_put( &p_buf_mgr->recv_pool, &p_desc->item );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_RECV );\r
+}\r
+\r
+void\r
+endpt_cm_buf_mgr_put_recv_list(\r
+ IN endpt_buf_mgr_t * const p_buf_mgr,\r
+ IN cl_qlist_t* const p_list )\r
+{\r
+ cl_qpool_put_list( &p_buf_mgr->recv_pool, p_list );\r
+}\r
+\r
+uint32_t\r
+endpt_cm_recv_mgr_build_pkt_array(\r
+ IN ipoib_port_t* const p_port,\r
+ IN ipoib_endpt_t* const p_endpt,\r
+ IN cl_qlist_t* const p_done_list,\r
+ IN OUT uint32_t* p_bytes_recv )\r
+{\r
+ cl_list_item_t *p_item;\r
+ ipoib_cm_desc_t *p_desc;\r
+ uint32_t i = 0;\r
+ NDIS_PACKET *p_packet;\r
+ NDIS_TCP_IP_CHECKSUM_PACKET_INFO chksum;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_RECV );\r
+ UNUSED_PARAM( p_endpt );\r
+\r
+ p_item = cl_qlist_remove_head( p_done_list );\r
+ \r
+ *p_bytes_recv = 0;\r
+\r
+ for( p_item; p_item != cl_qlist_end( p_done_list );\r
+ p_item = cl_qlist_remove_head( p_done_list ) )\r
+ {\r
+ p_desc = (ipoib_cm_desc_t*)p_item;\r
+\r
+ p_packet = __endpt_cm_get_ndis_pkt( p_port, p_desc );\r
+ if( !p_packet )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed to get Packet from descriptor\n" ) );\r
+ endpt_cm_buf_mgr_put_recv( &p_port->cm_buf_mgr, p_desc );\r
+ p_port->cm_recv_mgr.depth--;\r
+ continue;\r
+ }\r
+ chksum.Value = 0;\r
+ switch( p_port->p_adapter->params.recv_chksum_offload )\r
+ {\r
+ default:\r
+ CL_ASSERT( FALSE );\r
+ case CSUM_DISABLED:\r
+ case CSUM_ENABLED:\r
+ NDIS_PER_PACKET_INFO_FROM_PACKET( p_packet, TcpIpChecksumPacketInfo ) =\r
+ (void*)(uintn_t)chksum.Value;\r
+ break;\r
+ case CSUM_BYPASS:\r
+ /* Flag the checksums as having been calculated. */\r
+ chksum.Receive.NdisPacketTcpChecksumSucceeded = TRUE;\r
+ chksum.Receive.NdisPacketUdpChecksumSucceeded = TRUE;\r
+ chksum.Receive.NdisPacketIpChecksumSucceeded = TRUE;\r
+ NDIS_PER_PACKET_INFO_FROM_PACKET( p_packet, TcpIpChecksumPacketInfo ) =\r
+ (void*)(uintn_t)chksum.Value;\r
+ break;\r
+ }\r
+\r
+ NDIS_SET_PACKET_STATUS( p_packet, NDIS_STATUS_SUCCESS );\r
+ p_port->cm_recv_mgr.recv_pkt_array[i] = p_packet;\r
+ i++; \r
+ *p_bytes_recv += p_desc->len;\r
+ }\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_RECV );\r
+ return i;\r
+}\r
+void\r
+endpt_cm_flush_recv(\r
+ IN ipoib_port_t* const p_port,\r
+ IN ipoib_endpt_t* const p_endpt )\r
+{\r
+ ib_api_status_t ib_status = IB_SUCCESS;\r
+ ib_qp_mod_t mod_attr;\r
+ ib_wc_t wc[MAX_RECV_WC];\r
+ ib_wc_t *p_free_wc;\r
+ ib_wc_t *p_done_wc;\r
+ ib_wc_t *p_wc;\r
+ ipoib_cm_desc_t *p_desc;\r
+ size_t i;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_RECV );\r
+\r
+ CL_ASSERT( p_endpt );\r
+\r
+ if( p_endpt->conn.h_recv_qp )\r
+ {\r
+ cl_memclr( &mod_attr, sizeof( mod_attr ) );\r
+ mod_attr.req_state = IB_QPS_ERROR;\r
+ p_port->p_adapter->p_ifc->modify_qp( p_endpt->conn.h_send_qp, &mod_attr );\r
+ p_port->p_adapter->p_ifc->modify_qp( p_endpt->conn.h_recv_qp, &mod_attr );\r
+\r
+ for( i = 0; i < MAX_RECV_WC; i++ )\r
+ wc[i].p_next = &wc[i + 1];\r
+ wc[MAX_RECV_WC - 1].p_next = NULL;\r
+\r
+ do\r
+ {\r
+ p_free_wc = wc;\r
+ ib_status = \r
+ p_port->p_adapter->p_ifc->poll_cq( p_endpt->conn.h_recv_cq, \r
+ &p_free_wc, &p_done_wc );\r
+ if( ib_status != IB_SUCCESS && \r
+ ib_status != IB_NOT_FOUND )\r
+ {\r
+ /* connection CQ failed */\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Poll Recv CQ failed status %#x\n", ib_status ) );\r
+ break;\r
+ }\r
+ cl_spinlock_acquire( &p_port->recv_lock );\r
+ for( p_wc = p_done_wc; p_wc; p_wc = p_wc->p_next )\r
+ {\r
+ p_desc = (ipoib_cm_desc_t *)(uintn_t)p_wc->wr_id;\r
+ endpt_cm_buf_mgr_put_recv( &p_port->cm_buf_mgr, p_desc );\r
+ p_port->cm_recv_mgr.depth--;\r
+ }\r
+ cl_spinlock_release( &p_port->recv_lock );\r
+ } while( !p_free_wc );\r
+\r
+ ib_status = p_port->p_adapter->p_ifc->destroy_qp( p_endpt->conn.h_recv_qp, NULL );\r
+ if( ib_status != IB_SUCCESS )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Destroy Recv QP failed status %#x\n", ib_status ) );\r
+ }\r
+ p_endpt->conn.h_recv_qp = NULL;\r
+ }\r
+\r
+ if( p_endpt->conn.h_send_qp )\r
+ {\r
+ ib_status = p_port->p_adapter->p_ifc->destroy_qp( p_endpt->conn.h_send_qp, NULL );\r
+ if( ib_status != IB_SUCCESS )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Destroy Send QP failed status %#x\n", ib_status ) );\r
+ }\r
+ p_endpt->conn.h_send_qp = NULL;\r
+ }\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_RECV );\r
+}\r
+\r
+int32_t\r
+endpt_cm_recv_mgr_filter(\r
+ IN ipoib_endpt_t* const p_endpt,\r
+ IN ib_wc_t* const p_done_wc_list,\r
+ OUT cl_qlist_t* const p_done_list,\r
+ OUT cl_qlist_t* const p_bad_list )\r
+{\r
+ ib_api_status_t ib_status;\r
+ ipoib_cm_desc_t *p_desc;\r
+ ib_wc_t *p_wc;\r
+ ipoib_pkt_t *p_ipoib;\r
+ eth_pkt_t *p_eth;\r
+ ipoib_port_t* p_port;\r
+ int32_t recv_cnt;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_RECV );\r
+\r
+ p_port = ipoib_endpt_parent( p_endpt );\r
+\r
+ for( p_wc = p_done_wc_list, recv_cnt = 0; p_wc; p_wc = p_wc->p_next )\r
+ {\r
+ p_desc = (ipoib_cm_desc_t *)(uintn_t)p_wc->wr_id;\r
+ recv_cnt++;\r
+ if( p_wc->status != IB_WCS_SUCCESS )\r
+ {\r
+ if( p_wc->status != IB_WCS_WR_FLUSHED_ERR )\r
+ {\r
+ \r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed completion %s (vendor specific %#x)\n",\r
+ p_port->p_adapter->p_ifc->get_wc_status_str( p_wc->status ),\r
+ (int)p_wc->vendor_specific) );\r
+ }\r
+ else\r
+ {\r
+ IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_RECV,\r
+ ("Flushed completion %s\n",\r
+ p_port->p_adapter->p_ifc->get_wc_status_str( p_wc->status )) );\r
+ }\r
+ \r
+ ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_ERROR, 0, 0 );\r
+\r
+ cl_qlist_remove_item( &p_port->cm_buf_mgr.posted_list,&p_desc->list_item );\r
+ cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item );\r
+ continue;\r
+ }\r
+\r
+ /* Successful completion \r
+ Setup the ethernet/ip/arp header and queue descriptor for report. */\r
+ ib_status = IB_SUCCESS;\r
+ p_ipoib = (ipoib_pkt_t *)((uint8_t*)p_desc->p_buf );\r
+ p_eth = (eth_pkt_t *)((uint8_t*)p_desc->p_buf - DATA_OFFSET );\r
+ \r
+ switch( p_ipoib->hdr.type )\r
+ {\r
+ case ETH_PROT_TYPE_ARP:\r
+ if( p_wc->length < (sizeof(ipoib_hdr_t) + sizeof(ipoib_arp_pkt_t)) )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Received ARP packet too short\n") );\r
+ ib_status = IB_ERROR;\r
+ break;\r
+ }\r
+ ib_status = \r
+ __endpt_cm_recv_arp( p_port, p_ipoib, p_eth, p_endpt );\r
+ break;\r
+ case ETH_PROT_TYPE_IP:\r
+ if( p_wc->length < (sizeof(ipoib_hdr_t) + sizeof(ip_hdr_t)) )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Received IP packet too short\n") );\r
+ ib_status = IB_ERROR;\r
+ break;\r
+ }\r
+ if( p_ipoib->type.ip.hdr.prot == IP_PROT_UDP )\r
+ {\r
+ ib_status = \r
+ __endpt_cm_recv_udp( p_port, p_wc, p_ipoib, p_eth, p_endpt );\r
+ }\r
+ \r
+ break;\r
+ }\r
+\r
+ if( ib_status != IB_SUCCESS )\r
+ {\r
+ ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_ERROR, 0, 0 );\r
+ cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item );\r
+ continue;\r
+ }\r
+\r
+ p_eth->hdr.type = p_ipoib->hdr.type;\r
+ p_eth->hdr.src = p_endpt->mac;\r
+ p_eth->hdr.dst = p_port->p_adapter->mac;\r
+\r
+ /* save payload length */\r
+ p_desc->len = p_wc->length;\r
+ \r
+ cl_qlist_insert_tail( p_done_list, &p_desc->item.list_item );\r
+ }\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_RECV );\r
+ return recv_cnt;\r
+}\r
+\r
+ib_api_status_t\r
+endpt_cm_post_recv(\r
+ IN ipoib_port_t* const p_port )\r
+{\r
+ ib_api_status_t ib_status = IB_SUCCESS;\r
+ ipoib_cm_desc_t *p_head_desc = NULL;\r
+ ipoib_cm_desc_t *p_tail_desc = NULL;\r
+ ipoib_cm_desc_t *p_next_desc;\r
+ ib_recv_wr_t *p_failed_wc = NULL;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_RECV );\r
+\r
+ while( cl_qpool_count( &p_port->cm_buf_mgr.recv_pool ) > 1 )\r
+ {\r
+ /* Pull receives out of the pool and chain them up. */\r
+ p_next_desc = __endpt_cm_buf_mgr_get_recv( \r
+ &p_port->cm_buf_mgr );\r
+ if( !p_next_desc )\r
+ {\r
+ IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_RECV,\r
+ ("Out of receive descriptors! Endpt recv queue depth 0x%x\n",\r
+ p_port->cm_recv_mgr.depth ) );\r
+ break;\r
+ }\r
+\r
+ if( !p_tail_desc )\r
+ {\r
+ p_tail_desc = p_next_desc;\r
+ p_next_desc->wr.p_next = NULL;\r
+ }\r
+ else\r
+ {\r
+ p_next_desc->wr.p_next = &p_head_desc->wr;\r
+ }\r
+\r
+ p_head_desc = p_next_desc;\r
+\r
+ p_port->cm_recv_mgr.depth++;\r
+ }\r
+\r
+ if( p_head_desc )\r
+ {\r
+ ib_status = p_port->p_adapter->p_ifc->post_srq_recv(\r
+ p_port->ib_mgr.h_srq, &p_head_desc->wr, &p_failed_wc );\r
+\r
+ if( ib_status != IB_SUCCESS )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ip_post_recv returned %s\n", \r
+ p_port->p_adapter->p_ifc->get_err_str( ib_status )) );\r
+ \r
+ /* put descriptors back to the pool */\r
+ while( p_failed_wc )\r
+ {\r
+ p_head_desc = PARENT_STRUCT( p_failed_wc, ipoib_cm_desc_t, wr );\r
+ p_failed_wc = p_failed_wc->p_next;\r
+ endpt_cm_buf_mgr_put_recv( &p_port->cm_buf_mgr, p_head_desc );\r
+ p_port->cm_recv_mgr.depth--;\r
+ }\r
+ }\r
+ }\r
+\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_RECV );\r
+ return( ib_status );\r
+}\r
+\r
+static ib_api_status_t\r
+__endpt_cm_recv_arp(\r
+ IN ipoib_port_t* const p_port,\r
+ IN const ipoib_pkt_t* const p_ipoib,\r
+ OUT eth_pkt_t* const p_eth,\r
+ IN ipoib_endpt_t* const p_src_endpt )\r
+{\r
+ const ipoib_arp_pkt_t *p_ib_arp;\r
+ arp_pkt_t *p_arp;\r
+ \r
+ p_ib_arp = &p_ipoib->type.arp;\r
+ p_arp = &p_eth->type.arp;\r
+ \r
+ if( p_ib_arp->hw_type != ARP_HW_TYPE_IB ||\r
+ p_ib_arp->hw_size != sizeof(ipoib_hw_addr_t) ||\r
+ p_ib_arp->prot_type != ETH_PROT_TYPE_IP )\r
+ {\r
+ return IB_ERROR;\r
+ }\r
+ \r
+ p_arp->hw_type = ARP_HW_TYPE_ETH;\r
+ p_arp->hw_size = sizeof(mac_addr_t);\r
+ p_arp->src_hw = p_src_endpt->mac;\r
+ p_arp->src_ip = p_ib_arp->src_ip;\r
+ p_arp->dst_hw = p_port->p_local_endpt->mac;\r
+ p_arp->dst_ip = p_ib_arp->dst_ip;\r
+\r
+ return IB_SUCCESS; \r
+}\r
+\r
+static ib_api_status_t\r
+__endpt_cm_recv_udp(\r
+ IN ipoib_port_t* const p_port,\r
+ IN ib_wc_t* const p_wc,\r
+ IN const ipoib_pkt_t* const p_ipoib,\r
+ OUT eth_pkt_t* const p_eth,\r
+ IN ipoib_endpt_t* const p_src_endpt )\r
+{\r
+ ib_api_status_t ib_status = IB_SUCCESS;\r
+\r
+ if( p_wc->length <\r
+ (sizeof(ipoib_hdr_t) + sizeof(ip_hdr_t) + sizeof(udp_hdr_t)) )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Received UDP packet too short\n") );\r
+ return IB_ERROR;\r
+ }\r
+ if( __cm_recv_is_dhcp( p_ipoib ) )\r
+ {\r
+ ib_status = ipoib_recv_dhcp(\r
+ p_port, p_ipoib, p_eth, p_src_endpt, p_port->p_local_endpt );\r
+ }\r
+\r
+ return ib_status;\r
+}\r
+\r
+static boolean_t\r
+__cm_recv_is_dhcp(\r
+ IN const ipoib_pkt_t* const p_ipoib )\r
+{\r
+ return( (p_ipoib->type.ip.prot.udp.hdr.dst_port == DHCP_PORT_SERVER &&\r
+ p_ipoib->type.ip.prot.udp.hdr.src_port == DHCP_PORT_CLIENT) ||\r
+ (p_ipoib->type.ip.prot.udp.hdr.dst_port == DHCP_PORT_CLIENT &&\r
+ p_ipoib->type.ip.prot.udp.hdr.src_port == DHCP_PORT_SERVER) );\r
+}\r
+#endif\r
+++ /dev/null
-/*\r
- * Copyright (c) 2005 Mellanox Technologies. All rights reserved.\r
- * Copyright (c) 2005 SilverStorm Technologies. All rights reserved.\r
- * Portions Copyright (c) 2008 Microsoft Corporation. All rights reserved.\r
- *\r
- * This software is available to you under the OpenIB.org BSD license\r
- * below:\r
- *\r
- * Redistribution and use in source and binary forms, with or\r
- * without modification, are permitted provided that the following\r
- * conditions are met:\r
- *\r
- * - Redistributions of source code must retain the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer.\r
- *\r
- * - Redistributions in binary form must reproduce the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer in the documentation and/or other materials\r
- * provided with the distribution.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- * SOFTWARE.\r
- *\r
- * $Id: ipoib_ibat.c 4494 2009-06-22 14:31:08Z xalex $\r
- */\r
-\r
-\r
-#include "ipoib_driver.h"\r
-#include "ipoib_adapter.h"\r
-#include "ipoib_port.h"\r
-#include "ipoib_debug.h"\r
-#if defined(EVENT_TRACING)\r
-#ifdef offsetof\r
-#undef offsetof\r
-#endif\r
-#include "ipoib_ibat.tmh"\r
-#endif\r
-#include <iba/ib_at_ioctl.h>\r
-\r
-extern PDRIVER_OBJECT g_p_drv_obj;\r
-\r
-static NTSTATUS\r
-__ipoib_create(\r
- IN DEVICE_OBJECT* const pDevObj,\r
- IN IRP* const pIrp );\r
-\r
-static NTSTATUS\r
-__ipoib_cleanup(\r
- IN DEVICE_OBJECT* const pDevObj,\r
- IN IRP* const pIrp );\r
-\r
-static NTSTATUS\r
-__ipoib_close(\r
- IN DEVICE_OBJECT* const pDevObj,\r
- IN IRP* const pIrp );\r
-\r
-static NTSTATUS\r
-__ipoib_dispatch(\r
- IN DEVICE_OBJECT* const pDevObj,\r
- IN IRP* const pIrp );\r
-\r
-\r
-static NTSTATUS\r
-__ibat_get_ports(\r
- IN IRP *pIrp,\r
- IN IO_STACK_LOCATION *pIoStack )\r
-{\r
- IOCTL_IBAT_PORTS_IN *pIn;\r
- IOCTL_IBAT_PORTS_OUT *pOut;\r
- KLOCK_QUEUE_HANDLE hdl;\r
- cl_list_item_t *pItem;\r
- ipoib_adapter_t *pAdapter;\r
- LONG nPorts;\r
-\r
- IPOIB_ENTER(IPOIB_DBG_IOCTL);\r
-\r
- if( pIoStack->Parameters.DeviceIoControl.InputBufferLength !=\r
- sizeof(IOCTL_IBAT_PORTS_IN) )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Invalid input buffer size.\n") );\r
- return STATUS_INVALID_PARAMETER;\r
- }\r
- \r
- if( pIoStack->Parameters.DeviceIoControl.OutputBufferLength <\r
- sizeof(IOCTL_IBAT_PORTS_OUT) )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Invalid output buffer size.\n") );\r
- return STATUS_INVALID_PARAMETER;\r
- }\r
-\r
- pIn = pIrp->AssociatedIrp.SystemBuffer;\r
- pOut = pIrp->AssociatedIrp.SystemBuffer;\r
-\r
- if( pIn->Version != IBAT_IOCTL_VERSION )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Invalid version.\n") );\r
- return STATUS_INVALID_PARAMETER;\r
- }\r
-\r
- KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
- nPorts = (LONG)cl_qlist_count( &g_ipoib.adapter_list );\r
- switch( nPorts )\r
- {\r
- case 0:\r
- cl_memclr( pOut->Ports, sizeof(pOut->Ports) );\r
- /* Fall through */\r
- case 1:\r
- pOut->Size = sizeof(IOCTL_IBAT_PORTS_OUT);\r
- break;\r
-\r
- default:\r
- pOut->Size = sizeof(IOCTL_IBAT_PORTS_OUT) + \r
- (sizeof(IBAT_PORT_RECORD) * (nPorts - 1));\r
- break;\r
- }\r
-\r
- pIrp->IoStatus.Information = pOut->Size;\r
-\r
- if( pOut->Size > pIoStack->Parameters.DeviceIoControl.OutputBufferLength )\r
- {\r
- nPorts = 1 +\r
- (pIoStack->Parameters.DeviceIoControl.OutputBufferLength -\r
- sizeof(IOCTL_IBAT_PORTS_OUT)) / sizeof(IBAT_PORT_RECORD);\r
-\r
- pIrp->IoStatus.Information = sizeof(IOCTL_IBAT_PORTS_OUT) +\r
- ((nPorts - 1) * sizeof(IBAT_PORT_RECORD));\r
- }\r
-\r
- pOut->NumPorts = 0;\r
- pItem = cl_qlist_head( &g_ipoib.adapter_list );\r
- while( pOut->NumPorts != nPorts )\r
- {\r
- pAdapter = CONTAINING_RECORD( pItem, ipoib_adapter_t, entry );\r
- pOut->Ports[pOut->NumPorts].CaGuid = pAdapter->guids.ca_guid;\r
- pOut->Ports[pOut->NumPorts].PortGuid = pAdapter->guids.port_guid.guid;\r
- pOut->Ports[pOut->NumPorts].PKey = IB_DEFAULT_PKEY;\r
- pOut->Ports[pOut->NumPorts].PortNum = pAdapter->guids.port_num;\r
- pOut->NumPorts++;\r
-\r
- pItem = cl_qlist_next( pItem );\r
- }\r
-\r
- KeReleaseInStackQueuedSpinLock( &hdl );\r
- IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
- return STATUS_SUCCESS;\r
-}\r
-\r
-\r
-static NTSTATUS\r
-__ibat_get_ips(\r
- IN IRP *pIrp,\r
- IN IO_STACK_LOCATION *pIoStack )\r
-{\r
- IOCTL_IBAT_IP_ADDRESSES_IN *pIn;\r
- IOCTL_IBAT_IP_ADDRESSES_OUT *pOut;\r
- KLOCK_QUEUE_HANDLE hdl;\r
- cl_list_item_t *pItem;\r
- ipoib_adapter_t *pAdapter;\r
- LONG nIps, maxIps;\r
- size_t idx;\r
- net_address_item_t *pAddr;\r
- UINT64 PortGuid;\r
-\r
- IPOIB_ENTER(IPOIB_DBG_IOCTL);\r
-\r
- if( pIoStack->Parameters.DeviceIoControl.InputBufferLength !=\r
- sizeof(IOCTL_IBAT_IP_ADDRESSES_IN) )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Invalid input buffer size.\n") );\r
- return STATUS_INVALID_PARAMETER;\r
- }\r
- \r
- if( pIoStack->Parameters.DeviceIoControl.OutputBufferLength <\r
- sizeof(IOCTL_IBAT_IP_ADDRESSES_OUT) )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Invalid output buffer size.\n") );\r
- return STATUS_INVALID_PARAMETER;\r
- }\r
-\r
- pIn = pIrp->AssociatedIrp.SystemBuffer;\r
- pOut = pIrp->AssociatedIrp.SystemBuffer;\r
-\r
- if( pIn->Version != IBAT_IOCTL_VERSION )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Invalid version.\n") );\r
- return STATUS_INVALID_PARAMETER;\r
- }\r
-\r
- PortGuid = pIn->PortGuid;\r
-\r
- nIps = 0;\r
- pOut->AddressCount = 0;\r
- maxIps = 1 +\r
- ((pIoStack->Parameters.DeviceIoControl.OutputBufferLength -\r
- sizeof(IOCTL_IBAT_IP_ADDRESSES_OUT)) / sizeof(IP_ADDRESS));\r
-\r
- KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
- for( pItem = cl_qlist_head( &g_ipoib.adapter_list );\r
- pItem != cl_qlist_end( &g_ipoib.adapter_list );\r
- pItem = cl_qlist_next( pItem ) )\r
- {\r
- pAdapter = CONTAINING_RECORD( pItem, ipoib_adapter_t, entry );\r
- if( PortGuid && pAdapter->guids.port_guid.guid != PortGuid )\r
- continue;\r
-\r
- cl_obj_lock( &pAdapter->obj );\r
- nIps += (LONG)cl_vector_get_size( &pAdapter->ip_vector );\r
-\r
- for( idx = 0;\r
- idx < cl_vector_get_size( &pAdapter->ip_vector );\r
- idx++ )\r
- {\r
- if( pOut->AddressCount == maxIps )\r
- break;\r
-\r
- pAddr = (net_address_item_t*)\r
- cl_vector_get_ptr( &pAdapter->ip_vector, idx );\r
-\r
- pOut->Address[pOut->AddressCount].IpVersion = 4;\r
- cl_memclr( &pOut->Address[pOut->AddressCount].Address,\r
- sizeof(IP_ADDRESS) );\r
- cl_memcpy( &pOut->Address[pOut->AddressCount].Address[12],\r
- pAddr->address.as_bytes, IPV4_ADDR_SIZE );\r
-\r
- pOut->AddressCount++;\r
- }\r
- cl_obj_unlock( &pAdapter->obj );\r
- }\r
-\r
- pOut->Size = sizeof(IOCTL_IBAT_IP_ADDRESSES_OUT);\r
- if( --nIps )\r
- pOut->Size += sizeof(IP_ADDRESS) * nIps;\r
-\r
- pIrp->IoStatus.Information = sizeof(IOCTL_IBAT_IP_ADDRESSES_OUT);\r
- if( --maxIps < nIps )\r
- pIrp->IoStatus.Information += (sizeof(IP_ADDRESS) * maxIps);\r
- else\r
- pIrp->IoStatus.Information += (sizeof(IP_ADDRESS) * nIps);\r
-\r
- KeReleaseInStackQueuedSpinLock( &hdl );\r
- IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
- return STATUS_SUCCESS;\r
-}\r
-\r
-\r
-static NTSTATUS\r
-__ibat_mac_to_gid(\r
- IN IRP *pIrp,\r
- IN IO_STACK_LOCATION *pIoStack )\r
-{\r
- NTSTATUS status = STATUS_INVALID_PARAMETER;\r
- IOCTL_IBAT_MAC_TO_GID_IN *pIn;\r
- IOCTL_IBAT_MAC_TO_GID_OUT *pOut;\r
- KLOCK_QUEUE_HANDLE hdl;\r
- cl_list_item_t *pItem;\r
- ipoib_adapter_t *pAdapter;\r
-\r
- IPOIB_ENTER(IPOIB_DBG_IOCTL);\r
-\r
- if( pIoStack->Parameters.DeviceIoControl.InputBufferLength !=\r
- sizeof(IOCTL_IBAT_MAC_TO_GID_IN) )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Invalid input buffer size.\n") );\r
- return STATUS_INVALID_PARAMETER;\r
- }\r
- \r
- if( pIoStack->Parameters.DeviceIoControl.OutputBufferLength !=\r
- sizeof(IOCTL_IBAT_MAC_TO_GID_OUT) )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Invalid output buffer size.\n") );\r
- return STATUS_INVALID_PARAMETER;\r
- }\r
-\r
- pIn = pIrp->AssociatedIrp.SystemBuffer;\r
- pOut = pIrp->AssociatedIrp.SystemBuffer;\r
-\r
- if( pIn->Version != IBAT_IOCTL_VERSION )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Invalid version.\n") );\r
- return STATUS_INVALID_PARAMETER;\r
- }\r
-\r
- KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
-\r
- for( pItem = cl_qlist_head( &g_ipoib.adapter_list );\r
- pItem != cl_qlist_end( &g_ipoib.adapter_list );\r
- pItem = cl_qlist_next( pItem ) )\r
- {\r
- pAdapter = CONTAINING_RECORD( pItem, ipoib_adapter_t, entry );\r
- if( pIn->PortGuid != pAdapter->guids.port_guid.guid )\r
- continue;\r
-\r
- /* Found the port - lookup the MAC. */\r
- cl_obj_lock( &pAdapter->obj );\r
- if( pAdapter->p_port )\r
- {\r
- status = ipoib_mac_to_gid(\r
- pAdapter->p_port, *(mac_addr_t*)pIn->DestMac, &pOut->DestGid );\r
- if( NT_SUCCESS( status ) )\r
- {\r
- pIrp->IoStatus.Information =\r
- sizeof(IOCTL_IBAT_MAC_TO_GID_OUT);\r
- }\r
- }\r
- cl_obj_unlock( &pAdapter->obj );\r
- break;\r
- }\r
-\r
- KeReleaseInStackQueuedSpinLock( &hdl );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
- return status;\r
-}\r
-\r
-\r
-static NTSTATUS\r
-__ibat_mac_to_path(\r
- IN IRP *pIrp,\r
- IN IO_STACK_LOCATION *pIoStack )\r
-{\r
- NTSTATUS status = STATUS_INVALID_PARAMETER;\r
- IOCTL_IBAT_MAC_TO_PATH_IN *pIn;\r
- IOCTL_IBAT_MAC_TO_PATH_OUT *pOut;\r
- KLOCK_QUEUE_HANDLE hdl;\r
- cl_list_item_t *pItem;\r
- ipoib_adapter_t *pAdapter;\r
-\r
- IPOIB_ENTER(IPOIB_DBG_IOCTL);\r
-\r
- if( pIoStack->Parameters.DeviceIoControl.InputBufferLength !=\r
- sizeof(IOCTL_IBAT_MAC_TO_PATH_IN) )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Invalid input buffer size.\n") );\r
- return STATUS_INVALID_PARAMETER;\r
- }\r
- \r
- if( pIoStack->Parameters.DeviceIoControl.OutputBufferLength !=\r
- sizeof(IOCTL_IBAT_MAC_TO_PATH_OUT) )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Invalid output buffer size.\n") );\r
- return STATUS_INVALID_PARAMETER;\r
- }\r
-\r
- pIn = pIrp->AssociatedIrp.SystemBuffer;\r
- pOut = pIrp->AssociatedIrp.SystemBuffer;\r
-\r
- if( pIn->Version != IBAT_IOCTL_VERSION )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Invalid version.\n") );\r
- return STATUS_INVALID_PARAMETER;\r
- }\r
-\r
- KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
-\r
- for( pItem = cl_qlist_head( &g_ipoib.adapter_list );\r
- pItem != cl_qlist_end( &g_ipoib.adapter_list );\r
- pItem = cl_qlist_next( pItem ) )\r
- {\r
- pAdapter = CONTAINING_RECORD( pItem, ipoib_adapter_t, entry );\r
- if( pIn->PortGuid != pAdapter->guids.port_guid.guid )\r
- continue;\r
-\r
- /* Found the port - lookup the MAC. */\r
- cl_obj_lock( &pAdapter->obj );\r
- if( pAdapter->p_port )\r
- {\r
- status = ipoib_mac_to_path(\r
- pAdapter->p_port, *(mac_addr_t*)pIn->DestMac, &pOut->Path );\r
-\r
- if( NT_SUCCESS( status ) )\r
- {\r
- pIrp->IoStatus.Information =\r
- sizeof(IOCTL_IBAT_MAC_TO_PATH_OUT);\r
- }\r
- }\r
- cl_obj_unlock( &pAdapter->obj );\r
- break;\r
- }\r
-\r
- KeReleaseInStackQueuedSpinLock( &hdl );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
- return status;\r
-}\r
-\r
-\r
-static NTSTATUS\r
-__ibat_ip_to_port(\r
- IN IRP *pIrp,\r
- IN IO_STACK_LOCATION *pIoStack )\r
-{\r
- IOCTL_IBAT_IP_TO_PORT_IN *pIn;\r
- IOCTL_IBAT_IP_TO_PORT_OUT *pOut;\r
- KLOCK_QUEUE_HANDLE hdl;\r
- cl_list_item_t *pItem;\r
- ipoib_adapter_t *pAdapter;\r
- size_t idx;\r
- net_address_item_t *pAddr;\r
- NTSTATUS status = STATUS_NOT_FOUND;\r
-\r
- IPOIB_ENTER(IPOIB_DBG_IOCTL);\r
-\r
- if( pIoStack->Parameters.DeviceIoControl.InputBufferLength !=\r
- sizeof(IOCTL_IBAT_IP_TO_PORT_IN) )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Invalid input buffer size.\n") );\r
- return STATUS_INVALID_PARAMETER;\r
- }\r
- \r
- if( pIoStack->Parameters.DeviceIoControl.OutputBufferLength !=\r
- sizeof(IOCTL_IBAT_IP_TO_PORT_OUT) )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Invalid output buffer size.\n") );\r
- return STATUS_INVALID_PARAMETER;\r
- }\r
-\r
- pIn = pIrp->AssociatedIrp.SystemBuffer;\r
- pOut = pIrp->AssociatedIrp.SystemBuffer;\r
-\r
- if( pIn->Version != IBAT_IOCTL_VERSION )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Invalid version.\n") );\r
- return STATUS_INVALID_PARAMETER;\r
- }\r
-\r
- if (pIn->Address.IpVersion != 4)\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Invalid IP version (%d). Supported only 4\n", pIn->Address.IpVersion) );\r
- return STATUS_INVALID_PARAMETER;\r
- }\r
-\r
- KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
- for( pItem = cl_qlist_head( &g_ipoib.adapter_list );\r
- pItem != cl_qlist_end( &g_ipoib.adapter_list );\r
- pItem = cl_qlist_next( pItem ) )\r
- {\r
- pAdapter = CONTAINING_RECORD( pItem, ipoib_adapter_t, entry );\r
-\r
- cl_obj_lock( &pAdapter->obj );\r
-\r
- for( idx = 0;\r
- idx < cl_vector_get_size( &pAdapter->ip_vector );\r
- idx++ )\r
- {\r
- pAddr = (net_address_item_t*)\r
- cl_vector_get_ptr( &pAdapter->ip_vector, idx );\r
-\r
- if (!memcmp( &pIn->Address.Address[12], pAddr->address.as_bytes, IPV4_ADDR_SIZE))\r
- {\r
- pOut->Port.CaGuid = pAdapter->guids.ca_guid;\r
- pOut->Port.PortGuid = pAdapter->guids.port_guid.guid;\r
- pOut->Port.PKey = IB_DEFAULT_PKEY;\r
- pOut->Port.PortNum = pAdapter->guids.port_num;\r
- pIrp->IoStatus.Information = sizeof(IOCTL_IBAT_IP_TO_PORT_OUT);\r
- status = STATUS_SUCCESS;\r
- break;\r
- }\r
- }\r
- cl_obj_unlock( &pAdapter->obj );\r
- if (status == STATUS_SUCCESS)\r
- break;\r
- }\r
-\r
- KeReleaseInStackQueuedSpinLock( &hdl );\r
- IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
- return status;\r
-}\r
-\r
-void\r
-ipoib_ref_ibat()\r
-{\r
- UNICODE_STRING DeviceName;\r
- UNICODE_STRING DeviceLinkUnicodeString;\r
- NDIS_DEVICE_OBJECT_ATTRIBUTES DeviceObjectAttributes;\r
- PDRIVER_DISPATCH DispatchTable[IRP_MJ_MAXIMUM_FUNCTION+1];\r
-\r
- NDIS_STATUS Status = NDIS_STATUS_SUCCESS;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_IOCTL );\r
-\r
- if( InterlockedIncrement( &g_ipoib.ibat_ref ) == 1 )\r
- {\r
-\r
- NdisZeroMemory(DispatchTable, (IRP_MJ_MAXIMUM_FUNCTION+1) * sizeof(PDRIVER_DISPATCH));\r
- \r
- DispatchTable[IRP_MJ_CREATE] = __ipoib_create;\r
- DispatchTable[IRP_MJ_CLEANUP] = __ipoib_cleanup;\r
- DispatchTable[IRP_MJ_CLOSE] = __ipoib_close;\r
- DispatchTable[IRP_MJ_DEVICE_CONTROL] = __ipoib_dispatch;\r
- DispatchTable[IRP_MJ_INTERNAL_DEVICE_CONTROL] = __ipoib_dispatch; \r
- \r
- \r
- NdisInitUnicodeString( &DeviceName, IBAT_DEV_NAME );\r
- NdisInitUnicodeString( &DeviceLinkUnicodeString, IBAT_DOS_DEV_NAME );\r
- \r
- \r
- NdisZeroMemory(&DeviceObjectAttributes, sizeof(NDIS_DEVICE_OBJECT_ATTRIBUTES));\r
- \r
- DeviceObjectAttributes.Header.Type = NDIS_OBJECT_TYPE_DEFAULT; // type implicit from the context\r
- DeviceObjectAttributes.Header.Revision = NDIS_DEVICE_OBJECT_ATTRIBUTES_REVISION_1;\r
- DeviceObjectAttributes.Header.Size = sizeof(NDIS_DEVICE_OBJECT_ATTRIBUTES);\r
- DeviceObjectAttributes.DeviceName = &DeviceName;\r
- DeviceObjectAttributes.SymbolicName = &DeviceLinkUnicodeString;\r
- DeviceObjectAttributes.MajorFunctions = &DispatchTable[0];\r
- DeviceObjectAttributes.ExtensionSize = 0;\r
- DeviceObjectAttributes.DefaultSDDLString = NULL;\r
- DeviceObjectAttributes.DeviceClassGuid = 0;\r
- \r
- Status = NdisRegisterDeviceEx(\r
- g_IpoibMiniportDriverHandle,\r
- &DeviceObjectAttributes,\r
- &g_ipoib.h_ibat_dev,\r
- &g_ipoib.h_ibat_dev_handle);\r
-\r
-\r
- \r
- if( Status != NDIS_STATUS_SUCCESS )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, \r
- ("NdisRegisterDeviceEx failed with status of %d\n", Status) );\r
- }\r
- }\r
-\r
- IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
-}\r
-\r
-\r
-void\r
-ipoib_deref_ibat()\r
-{\r
- IPOIB_ENTER( IPOIB_DBG_IOCTL );\r
-\r
- if( InterlockedDecrement( &g_ipoib.ibat_ref ) )\r
- {\r
- IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
- return;\r
- }\r
-\r
- if( g_ipoib.h_ibat_dev )\r
- {\r
- NdisDeregisterDeviceEx( g_ipoib.h_ibat_dev_handle );\r
- g_ipoib.h_ibat_dev = NULL;\r
- g_ipoib.h_ibat_dev_handle = NULL; //TODO set here INVALID_HANDLE_VALUE\r
- }\r
-\r
- IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
-}\r
-\r
-\r
-static NTSTATUS\r
-__ipoib_create(\r
- IN DEVICE_OBJECT* const pDevObj,\r
- IN IRP* const pIrp )\r
-{\r
- IPOIB_ENTER( IPOIB_DBG_IOCTL );\r
-\r
- UNREFERENCED_PARAMETER( pDevObj );\r
-\r
- ipoib_ref_ibat();\r
-\r
- pIrp->IoStatus.Status = STATUS_SUCCESS;\r
- pIrp->IoStatus.Information = 0;\r
- IoCompleteRequest( pIrp, IO_NO_INCREMENT );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
- return STATUS_SUCCESS;\r
-}\r
-\r
-\r
-static NTSTATUS\r
-__ipoib_cleanup(\r
- IN DEVICE_OBJECT* const pDevObj,\r
- IN IRP* const pIrp )\r
-{\r
- IPOIB_ENTER( IPOIB_DBG_IOCTL );\r
-\r
- UNREFERENCED_PARAMETER( pDevObj );\r
-\r
- ipoib_deref_ibat();\r
-\r
- pIrp->IoStatus.Status = STATUS_SUCCESS;\r
- pIrp->IoStatus.Information = 0;\r
- IoCompleteRequest( pIrp, IO_NO_INCREMENT );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
- return STATUS_SUCCESS;\r
-}\r
-\r
-\r
-static NTSTATUS\r
-__ipoib_close(\r
- IN DEVICE_OBJECT* const pDevObj,\r
- IN IRP* const pIrp )\r
-{\r
- IPOIB_ENTER( IPOIB_DBG_IOCTL );\r
-\r
- UNREFERENCED_PARAMETER( pDevObj );\r
-\r
- pIrp->IoStatus.Status = STATUS_SUCCESS;\r
- pIrp->IoStatus.Information = 0;\r
- IoCompleteRequest( pIrp, IO_NO_INCREMENT );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
- return STATUS_SUCCESS;\r
-}\r
-\r
-\r
-static NTSTATUS\r
-__ipoib_dispatch(\r
- IN DEVICE_OBJECT* const pDevObj,\r
- IN IRP* const pIrp )\r
-{\r
- IO_STACK_LOCATION *pIoStack;\r
- NTSTATUS status = STATUS_SUCCESS;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_IOCTL );\r
-\r
- UNREFERENCED_PARAMETER( pDevObj );\r
-\r
- pIoStack = IoGetCurrentIrpStackLocation( pIrp );\r
-\r
- pIrp->IoStatus.Information = 0;\r
-\r
- switch( pIoStack->Parameters.DeviceIoControl.IoControlCode )\r
- {\r
- case IOCTL_IBAT_PORTS:\r
- IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_IOCTL,\r
- ("IOCTL_IBAT_PORTS received\n") );\r
- status = __ibat_get_ports( pIrp, pIoStack );\r
- break;\r
-\r
- case IOCTL_IBAT_IP_ADDRESSES:\r
- IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_IOCTL,\r
- ("IOCTL_IBAT_IP_ADDRESSES received\n" ));\r
- status = __ibat_get_ips( pIrp, pIoStack );\r
- break;\r
-\r
- case IOCTL_IBAT_MAC_TO_GID:\r
- IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_IOCTL,\r
- ("IOCTL_IBAT_MAC_TO_GID received\n" ));\r
- status = __ibat_mac_to_gid( pIrp, pIoStack );\r
- break;\r
-\r
- case IOCTL_IBAT_IP_TO_PORT:\r
- IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_IOCTL,\r
- ("IOCTL_IBAT_IP_TO_PORT received\n" ));\r
- status = __ibat_ip_to_port( pIrp, pIoStack );\r
- break;\r
-\r
- case IOCTL_IBAT_MAC_TO_PATH:\r
- IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_IOCTL,\r
- ("IOCTL_IBAT_MAC_TO_PATH received\n" ));\r
- status = __ibat_mac_to_path( pIrp, pIoStack );\r
- break;\r
-\r
- default:\r
- IPOIB_PRINT( TRACE_LEVEL_VERBOSE, IPOIB_DBG_IOCTL,\r
- ("unknow IOCTL code = 0x%x\n",\r
- pIoStack->Parameters.DeviceIoControl.IoControlCode) );\r
- status = STATUS_INVALID_PARAMETER;\r
- }\r
-\r
- pIrp->IoStatus.Status = status;\r
- IoCompleteRequest( pIrp, IO_NO_INCREMENT );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
- return status;\r
-}\r
-\r
-\r
--- /dev/null
+/*\r
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.\r
+ * Copyright (c) 2005 SilverStorm Technologies. All rights reserved.\r
+ * Portions Copyright (c) 2008 Microsoft Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ * - Redistributions of source code must retain the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer.\r
+ *\r
+ * - Redistributions in binary form must reproduce the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer in the documentation and/or other materials\r
+ * provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id: ipoib_ibat.c 4494 2009-06-22 14:31:08Z xalex $\r
+ */\r
+\r
+\r
+#include "ipoib_driver.h"\r
+#include "ipoib_adapter.h"\r
+#include "ipoib_port.h"\r
+#include "ipoib_debug.h"\r
+#if defined(EVENT_TRACING)\r
+#ifdef offsetof\r
+#undef offsetof\r
+#endif\r
+#include "ipoib_ibat.tmh"\r
+#endif\r
+#include <iba/ib_at_ioctl.h>\r
+\r
+extern PDRIVER_OBJECT g_p_drv_obj;\r
+\r
+static NTSTATUS\r
+__ipoib_create(\r
+ IN DEVICE_OBJECT* const pDevObj,\r
+ IN IRP* const pIrp );\r
+\r
+static NTSTATUS\r
+__ipoib_cleanup(\r
+ IN DEVICE_OBJECT* const pDevObj,\r
+ IN IRP* const pIrp );\r
+\r
+static NTSTATUS\r
+__ipoib_close(\r
+ IN DEVICE_OBJECT* const pDevObj,\r
+ IN IRP* const pIrp );\r
+\r
+static NTSTATUS\r
+__ipoib_dispatch(\r
+ IN DEVICE_OBJECT* const pDevObj,\r
+ IN IRP* const pIrp );\r
+\r
+\r
+static NTSTATUS\r
+__ibat_get_ports(\r
+ IN IRP *pIrp,\r
+ IN IO_STACK_LOCATION *pIoStack )\r
+{\r
+ IOCTL_IBAT_PORTS_IN *pIn;\r
+ IOCTL_IBAT_PORTS_OUT *pOut;\r
+ KLOCK_QUEUE_HANDLE hdl;\r
+ cl_list_item_t *pItem;\r
+ ipoib_adapter_t *pAdapter;\r
+ LONG nPorts;\r
+\r
+ IPOIB_ENTER(IPOIB_DBG_IOCTL);\r
+\r
+ if( pIoStack->Parameters.DeviceIoControl.InputBufferLength !=\r
+ sizeof(IOCTL_IBAT_PORTS_IN) )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Invalid input buffer size.\n") );\r
+ return STATUS_INVALID_PARAMETER;\r
+ }\r
+ \r
+ if( pIoStack->Parameters.DeviceIoControl.OutputBufferLength <\r
+ sizeof(IOCTL_IBAT_PORTS_OUT) )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Invalid output buffer size.\n") );\r
+ return STATUS_INVALID_PARAMETER;\r
+ }\r
+\r
+ pIn = (IOCTL_IBAT_PORTS_IN *) pIrp->AssociatedIrp.SystemBuffer;\r
+ pOut = (IOCTL_IBAT_PORTS_OUT *) pIrp->AssociatedIrp.SystemBuffer;\r
+\r
+ if( pIn->Version != IBAT_IOCTL_VERSION )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Invalid version.\n") );\r
+ return STATUS_INVALID_PARAMETER;\r
+ }\r
+\r
+ KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
+ nPorts = (LONG)cl_qlist_count( &g_ipoib.adapter_list );\r
+ switch( nPorts )\r
+ {\r
+ case 0:\r
+ cl_memclr( pOut->Ports, sizeof(pOut->Ports) );\r
+ /* Fall through */\r
+ case 1:\r
+ pOut->Size = sizeof(IOCTL_IBAT_PORTS_OUT);\r
+ break;\r
+\r
+ default:\r
+ pOut->Size = sizeof(IOCTL_IBAT_PORTS_OUT) + \r
+ (sizeof(IBAT_PORT_RECORD) * (nPorts - 1));\r
+ break;\r
+ }\r
+\r
+ pIrp->IoStatus.Information = pOut->Size;\r
+\r
+ if( pOut->Size > pIoStack->Parameters.DeviceIoControl.OutputBufferLength )\r
+ {\r
+ nPorts = 1 +\r
+ (pIoStack->Parameters.DeviceIoControl.OutputBufferLength -\r
+ sizeof(IOCTL_IBAT_PORTS_OUT)) / sizeof(IBAT_PORT_RECORD);\r
+\r
+ pIrp->IoStatus.Information = sizeof(IOCTL_IBAT_PORTS_OUT) +\r
+ ((nPorts - 1) * sizeof(IBAT_PORT_RECORD));\r
+ }\r
+\r
+ pOut->NumPorts = 0;\r
+ pItem = cl_qlist_head( &g_ipoib.adapter_list );\r
+ while( pOut->NumPorts != nPorts )\r
+ {\r
+ pAdapter = CONTAINING_RECORD( pItem, ipoib_adapter_t, entry );\r
+ pOut->Ports[pOut->NumPorts].CaGuid = pAdapter->guids.ca_guid;\r
+ pOut->Ports[pOut->NumPorts].PortGuid = pAdapter->guids.port_guid.guid;\r
+ pOut->Ports[pOut->NumPorts].PKey = IB_DEFAULT_PKEY;\r
+ pOut->Ports[pOut->NumPorts].PortNum = pAdapter->guids.port_num;\r
+ pOut->NumPorts++;\r
+\r
+ pItem = cl_qlist_next( pItem );\r
+ }\r
+\r
+ KeReleaseInStackQueuedSpinLock( &hdl );\r
+ IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
+ return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+__ibat_get_ips(\r
+ IN IRP *pIrp,\r
+ IN IO_STACK_LOCATION *pIoStack )\r
+{\r
+ IOCTL_IBAT_IP_ADDRESSES_IN *pIn;\r
+ IOCTL_IBAT_IP_ADDRESSES_OUT *pOut;\r
+ KLOCK_QUEUE_HANDLE hdl;\r
+ cl_list_item_t *pItem;\r
+ ipoib_adapter_t *pAdapter;\r
+ LONG nIps, maxIps;\r
+ size_t idx;\r
+ net_address_item_t *pAddr;\r
+ UINT64 PortGuid;\r
+\r
+ IPOIB_ENTER(IPOIB_DBG_IOCTL);\r
+\r
+ if( pIoStack->Parameters.DeviceIoControl.InputBufferLength !=\r
+ sizeof(IOCTL_IBAT_IP_ADDRESSES_IN) )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Invalid input buffer size.\n") );\r
+ return STATUS_INVALID_PARAMETER;\r
+ }\r
+ \r
+ if( pIoStack->Parameters.DeviceIoControl.OutputBufferLength <\r
+ sizeof(IOCTL_IBAT_IP_ADDRESSES_OUT) )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Invalid output buffer size.\n") );\r
+ return STATUS_INVALID_PARAMETER;\r
+ }\r
+\r
+ pIn = (IOCTL_IBAT_IP_ADDRESSES_IN *) pIrp->AssociatedIrp.SystemBuffer;\r
+ pOut = (IOCTL_IBAT_IP_ADDRESSES_OUT *) pIrp->AssociatedIrp.SystemBuffer;\r
+\r
+ if( pIn->Version != IBAT_IOCTL_VERSION )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Invalid version.\n") );\r
+ return STATUS_INVALID_PARAMETER;\r
+ }\r
+\r
+ PortGuid = pIn->PortGuid;\r
+\r
+ nIps = 0;\r
+ pOut->AddressCount = 0;\r
+ maxIps = 1 +\r
+ ((pIoStack->Parameters.DeviceIoControl.OutputBufferLength -\r
+ sizeof(IOCTL_IBAT_IP_ADDRESSES_OUT)) / sizeof(IP_ADDRESS));\r
+\r
+ KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
+ for( pItem = cl_qlist_head( &g_ipoib.adapter_list );\r
+ pItem != cl_qlist_end( &g_ipoib.adapter_list );\r
+ pItem = cl_qlist_next( pItem ) )\r
+ {\r
+ pAdapter = CONTAINING_RECORD( pItem, ipoib_adapter_t, entry );\r
+ if( PortGuid && pAdapter->guids.port_guid.guid != PortGuid )\r
+ continue;\r
+\r
+ cl_obj_lock( &pAdapter->obj );\r
+ nIps += (LONG)cl_vector_get_size( &pAdapter->ip_vector );\r
+\r
+ for( idx = 0;\r
+ idx < cl_vector_get_size( &pAdapter->ip_vector );\r
+ idx++ )\r
+ {\r
+ if( pOut->AddressCount == maxIps )\r
+ break;\r
+\r
+ pAddr = (net_address_item_t*)\r
+ cl_vector_get_ptr( &pAdapter->ip_vector, idx );\r
+\r
+ pOut->Address[pOut->AddressCount].IpVersion = 4;\r
+ cl_memclr( &pOut->Address[pOut->AddressCount].Address,\r
+ sizeof(IP_ADDRESS) );\r
+ cl_memcpy( &pOut->Address[pOut->AddressCount].Address[12],\r
+ pAddr->address.as_bytes, IPV4_ADDR_SIZE );\r
+\r
+ pOut->AddressCount++;\r
+ }\r
+ cl_obj_unlock( &pAdapter->obj );\r
+ }\r
+\r
+ pOut->Size = sizeof(IOCTL_IBAT_IP_ADDRESSES_OUT);\r
+ if( --nIps )\r
+ pOut->Size += sizeof(IP_ADDRESS) * nIps;\r
+\r
+ pIrp->IoStatus.Information = sizeof(IOCTL_IBAT_IP_ADDRESSES_OUT);\r
+ if( --maxIps < nIps )\r
+ pIrp->IoStatus.Information += (sizeof(IP_ADDRESS) * maxIps);\r
+ else\r
+ pIrp->IoStatus.Information += (sizeof(IP_ADDRESS) * nIps);\r
+\r
+ KeReleaseInStackQueuedSpinLock( &hdl );\r
+ IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
+ return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+__ibat_mac_to_gid(\r
+ IN IRP *pIrp,\r
+ IN IO_STACK_LOCATION *pIoStack )\r
+{\r
+ NTSTATUS status = STATUS_INVALID_PARAMETER;\r
+ IOCTL_IBAT_MAC_TO_GID_IN *pIn;\r
+ IOCTL_IBAT_MAC_TO_GID_OUT *pOut;\r
+ KLOCK_QUEUE_HANDLE hdl;\r
+ cl_list_item_t *pItem;\r
+ ipoib_adapter_t *pAdapter;\r
+\r
+ IPOIB_ENTER(IPOIB_DBG_IOCTL);\r
+\r
+ if( pIoStack->Parameters.DeviceIoControl.InputBufferLength !=\r
+ sizeof(IOCTL_IBAT_MAC_TO_GID_IN) )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Invalid input buffer size.\n") );\r
+ return STATUS_INVALID_PARAMETER;\r
+ }\r
+ \r
+ if( pIoStack->Parameters.DeviceIoControl.OutputBufferLength !=\r
+ sizeof(IOCTL_IBAT_MAC_TO_GID_OUT) )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Invalid output buffer size.\n") );\r
+ return STATUS_INVALID_PARAMETER;\r
+ }\r
+\r
+ pIn = (IOCTL_IBAT_MAC_TO_GID_IN *) pIrp->AssociatedIrp.SystemBuffer;\r
+ pOut = (IOCTL_IBAT_MAC_TO_GID_OUT *) pIrp->AssociatedIrp.SystemBuffer;\r
+\r
+ if( pIn->Version != IBAT_IOCTL_VERSION )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Invalid version.\n") );\r
+ return STATUS_INVALID_PARAMETER;\r
+ }\r
+\r
+ KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
+\r
+ for( pItem = cl_qlist_head( &g_ipoib.adapter_list );\r
+ pItem != cl_qlist_end( &g_ipoib.adapter_list );\r
+ pItem = cl_qlist_next( pItem ) )\r
+ {\r
+ pAdapter = CONTAINING_RECORD( pItem, ipoib_adapter_t, entry );\r
+ if( pIn->PortGuid != pAdapter->guids.port_guid.guid )\r
+ continue;\r
+\r
+ /* Found the port - lookup the MAC. */\r
+ cl_obj_lock( &pAdapter->obj );\r
+ if( pAdapter->p_port )\r
+ {\r
+ status = ipoib_mac_to_gid(\r
+ pAdapter->p_port, *(mac_addr_t*)pIn->DestMac, &pOut->DestGid );\r
+ if( NT_SUCCESS( status ) )\r
+ {\r
+ pIrp->IoStatus.Information =\r
+ sizeof(IOCTL_IBAT_MAC_TO_GID_OUT);\r
+ }\r
+ }\r
+ cl_obj_unlock( &pAdapter->obj );\r
+ break;\r
+ }\r
+\r
+ KeReleaseInStackQueuedSpinLock( &hdl );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
+ return status;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+__ibat_mac_to_path(\r
+ IN IRP *pIrp,\r
+ IN IO_STACK_LOCATION *pIoStack )\r
+{\r
+ NTSTATUS status = STATUS_INVALID_PARAMETER;\r
+ IOCTL_IBAT_MAC_TO_PATH_IN *pIn;\r
+ IOCTL_IBAT_MAC_TO_PATH_OUT *pOut;\r
+ KLOCK_QUEUE_HANDLE hdl;\r
+ cl_list_item_t *pItem;\r
+ ipoib_adapter_t *pAdapter;\r
+\r
+ IPOIB_ENTER(IPOIB_DBG_IOCTL);\r
+\r
+ if( pIoStack->Parameters.DeviceIoControl.InputBufferLength !=\r
+ sizeof(IOCTL_IBAT_MAC_TO_PATH_IN) )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Invalid input buffer size.\n") );\r
+ return STATUS_INVALID_PARAMETER;\r
+ }\r
+ \r
+ if( pIoStack->Parameters.DeviceIoControl.OutputBufferLength !=\r
+ sizeof(IOCTL_IBAT_MAC_TO_PATH_OUT) )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Invalid output buffer size.\n") );\r
+ return STATUS_INVALID_PARAMETER;\r
+ }\r
+\r
+ pIn = (IOCTL_IBAT_MAC_TO_PATH_IN *) pIrp->AssociatedIrp.SystemBuffer;\r
+ pOut = (IOCTL_IBAT_MAC_TO_PATH_OUT *) pIrp->AssociatedIrp.SystemBuffer;\r
+\r
+ if( pIn->Version != IBAT_IOCTL_VERSION )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Invalid version.\n") );\r
+ return STATUS_INVALID_PARAMETER;\r
+ }\r
+\r
+ KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
+\r
+ for( pItem = cl_qlist_head( &g_ipoib.adapter_list );\r
+ pItem != cl_qlist_end( &g_ipoib.adapter_list );\r
+ pItem = cl_qlist_next( pItem ) )\r
+ {\r
+ pAdapter = CONTAINING_RECORD( pItem, ipoib_adapter_t, entry );\r
+ if( pIn->PortGuid != pAdapter->guids.port_guid.guid )\r
+ continue;\r
+\r
+ /* Found the port - lookup the MAC. */\r
+ cl_obj_lock( &pAdapter->obj );\r
+ if( pAdapter->p_port )\r
+ {\r
+ status = ipoib_mac_to_path(\r
+ pAdapter->p_port, *(mac_addr_t*)pIn->DestMac, &pOut->Path );\r
+\r
+ if( NT_SUCCESS( status ) )\r
+ {\r
+ pIrp->IoStatus.Information =\r
+ sizeof(IOCTL_IBAT_MAC_TO_PATH_OUT);\r
+ }\r
+ }\r
+ cl_obj_unlock( &pAdapter->obj );\r
+ break;\r
+ }\r
+\r
+ KeReleaseInStackQueuedSpinLock( &hdl );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
+ return status;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+__ibat_ip_to_port(\r
+ IN IRP *pIrp,\r
+ IN IO_STACK_LOCATION *pIoStack )\r
+{\r
+ IOCTL_IBAT_IP_TO_PORT_IN *pIn;\r
+ IOCTL_IBAT_IP_TO_PORT_OUT *pOut;\r
+ KLOCK_QUEUE_HANDLE hdl;\r
+ cl_list_item_t *pItem;\r
+ ipoib_adapter_t *pAdapter;\r
+ size_t idx;\r
+ net_address_item_t *pAddr;\r
+ NTSTATUS status = STATUS_NOT_FOUND;\r
+\r
+ IPOIB_ENTER(IPOIB_DBG_IOCTL);\r
+\r
+ if( pIoStack->Parameters.DeviceIoControl.InputBufferLength !=\r
+ sizeof(IOCTL_IBAT_IP_TO_PORT_IN) )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Invalid input buffer size.\n") );\r
+ return STATUS_INVALID_PARAMETER;\r
+ }\r
+ \r
+ if( pIoStack->Parameters.DeviceIoControl.OutputBufferLength !=\r
+ sizeof(IOCTL_IBAT_IP_TO_PORT_OUT) )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Invalid output buffer size.\n") );\r
+ return STATUS_INVALID_PARAMETER;\r
+ }\r
+\r
+ pIn = (IOCTL_IBAT_IP_TO_PORT_IN *) pIrp->AssociatedIrp.SystemBuffer;\r
+ pOut = (IOCTL_IBAT_IP_TO_PORT_OUT *) pIrp->AssociatedIrp.SystemBuffer;\r
+\r
+ if( pIn->Version != IBAT_IOCTL_VERSION )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Invalid version.\n") );\r
+ return STATUS_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (pIn->Address.IpVersion != 4)\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Invalid IP version (%d). Supported only 4\n", pIn->Address.IpVersion) );\r
+ return STATUS_INVALID_PARAMETER;\r
+ }\r
+\r
+ KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
+ for( pItem = cl_qlist_head( &g_ipoib.adapter_list );\r
+ pItem != cl_qlist_end( &g_ipoib.adapter_list );\r
+ pItem = cl_qlist_next( pItem ) )\r
+ {\r
+ pAdapter = CONTAINING_RECORD( pItem, ipoib_adapter_t, entry );\r
+\r
+ cl_obj_lock( &pAdapter->obj );\r
+\r
+ for( idx = 0;\r
+ idx < cl_vector_get_size( &pAdapter->ip_vector );\r
+ idx++ )\r
+ {\r
+ pAddr = (net_address_item_t*)\r
+ cl_vector_get_ptr( &pAdapter->ip_vector, idx );\r
+\r
+ if (!memcmp( &pIn->Address.Address[12], pAddr->address.as_bytes, IPV4_ADDR_SIZE))\r
+ {\r
+ pOut->Port.CaGuid = pAdapter->guids.ca_guid;\r
+ pOut->Port.PortGuid = pAdapter->guids.port_guid.guid;\r
+ pOut->Port.PKey = IB_DEFAULT_PKEY;\r
+ pOut->Port.PortNum = pAdapter->guids.port_num;\r
+ pIrp->IoStatus.Information = sizeof(IOCTL_IBAT_IP_TO_PORT_OUT);\r
+ status = STATUS_SUCCESS;\r
+ break;\r
+ }\r
+ }\r
+ cl_obj_unlock( &pAdapter->obj );\r
+ if (status == STATUS_SUCCESS)\r
+ break;\r
+ }\r
+\r
+ KeReleaseInStackQueuedSpinLock( &hdl );\r
+ IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
+ return status;\r
+}\r
+\r
+void\r
+ipoib_ref_ibat()\r
+{\r
+ UNICODE_STRING DeviceName;\r
+ UNICODE_STRING DeviceLinkUnicodeString;\r
+ NDIS_DEVICE_OBJECT_ATTRIBUTES DeviceObjectAttributes;\r
+ PDRIVER_DISPATCH DispatchTable[IRP_MJ_MAXIMUM_FUNCTION+1];\r
+\r
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_IOCTL );\r
+\r
+ if( InterlockedIncrement( &g_ipoib.ibat_ref ) == 1 )\r
+ {\r
+\r
+ NdisZeroMemory(DispatchTable, (IRP_MJ_MAXIMUM_FUNCTION+1) * sizeof(PDRIVER_DISPATCH));\r
+ \r
+ DispatchTable[IRP_MJ_CREATE] = __ipoib_create;\r
+ DispatchTable[IRP_MJ_CLEANUP] = __ipoib_cleanup;\r
+ DispatchTable[IRP_MJ_CLOSE] = __ipoib_close;\r
+ DispatchTable[IRP_MJ_DEVICE_CONTROL] = __ipoib_dispatch;\r
+ DispatchTable[IRP_MJ_INTERNAL_DEVICE_CONTROL] = __ipoib_dispatch; \r
+ \r
+ \r
+ NdisInitUnicodeString( &DeviceName, IBAT_DEV_NAME );\r
+ NdisInitUnicodeString( &DeviceLinkUnicodeString, IBAT_DOS_DEV_NAME );\r
+ \r
+ \r
+ NdisZeroMemory(&DeviceObjectAttributes, sizeof(NDIS_DEVICE_OBJECT_ATTRIBUTES));\r
+ \r
+ DeviceObjectAttributes.Header.Type = NDIS_OBJECT_TYPE_DEFAULT; // type implicit from the context\r
+ DeviceObjectAttributes.Header.Revision = NDIS_DEVICE_OBJECT_ATTRIBUTES_REVISION_1;\r
+ DeviceObjectAttributes.Header.Size = sizeof(NDIS_DEVICE_OBJECT_ATTRIBUTES);\r
+ DeviceObjectAttributes.DeviceName = &DeviceName;\r
+ DeviceObjectAttributes.SymbolicName = &DeviceLinkUnicodeString;\r
+ DeviceObjectAttributes.MajorFunctions = &DispatchTable[0];\r
+ DeviceObjectAttributes.ExtensionSize = 0;\r
+ DeviceObjectAttributes.DefaultSDDLString = NULL;\r
+ DeviceObjectAttributes.DeviceClassGuid = 0;\r
+ \r
+ Status = NdisRegisterDeviceEx(\r
+ g_IpoibMiniportDriverHandle,\r
+ &DeviceObjectAttributes,\r
+ &g_ipoib.h_ibat_dev,\r
+ &g_ipoib.h_ibat_dev_handle);\r
+\r
+\r
+ \r
+ if( Status != NDIS_STATUS_SUCCESS )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, \r
+ ("NdisRegisterDeviceEx failed with status of %d\n", Status) );\r
+ }\r
+ }\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
+}\r
+\r
+\r
+void\r
+ipoib_deref_ibat()\r
+{\r
+ IPOIB_ENTER( IPOIB_DBG_IOCTL );\r
+\r
+ if( InterlockedDecrement( &g_ipoib.ibat_ref ) )\r
+ {\r
+ IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
+ return;\r
+ }\r
+\r
+ if( g_ipoib.h_ibat_dev )\r
+ {\r
+ NdisDeregisterDeviceEx( g_ipoib.h_ibat_dev_handle );\r
+ g_ipoib.h_ibat_dev = NULL;\r
+ g_ipoib.h_ibat_dev_handle = NULL; //TODO set here INVALID_HANDLE_VALUE\r
+ }\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
+}\r
+\r
+\r
+static NTSTATUS\r
+__ipoib_create(\r
+ IN DEVICE_OBJECT* const pDevObj,\r
+ IN IRP* const pIrp )\r
+{\r
+ IPOIB_ENTER( IPOIB_DBG_IOCTL );\r
+\r
+ UNREFERENCED_PARAMETER( pDevObj );\r
+\r
+ ipoib_ref_ibat();\r
+\r
+ pIrp->IoStatus.Status = STATUS_SUCCESS;\r
+ pIrp->IoStatus.Information = 0;\r
+ IoCompleteRequest( pIrp, IO_NO_INCREMENT );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
+ return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+__ipoib_cleanup(\r
+ IN DEVICE_OBJECT* const pDevObj,\r
+ IN IRP* const pIrp )\r
+{\r
+ IPOIB_ENTER( IPOIB_DBG_IOCTL );\r
+\r
+ UNREFERENCED_PARAMETER( pDevObj );\r
+\r
+ ipoib_deref_ibat();\r
+\r
+ pIrp->IoStatus.Status = STATUS_SUCCESS;\r
+ pIrp->IoStatus.Information = 0;\r
+ IoCompleteRequest( pIrp, IO_NO_INCREMENT );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
+ return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+__ipoib_close(\r
+ IN DEVICE_OBJECT* const pDevObj,\r
+ IN IRP* const pIrp )\r
+{\r
+ IPOIB_ENTER( IPOIB_DBG_IOCTL );\r
+\r
+ UNREFERENCED_PARAMETER( pDevObj );\r
+\r
+ pIrp->IoStatus.Status = STATUS_SUCCESS;\r
+ pIrp->IoStatus.Information = 0;\r
+ IoCompleteRequest( pIrp, IO_NO_INCREMENT );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
+ return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+__ipoib_dispatch(\r
+ IN DEVICE_OBJECT* const pDevObj,\r
+ IN IRP* const pIrp )\r
+{\r
+ IO_STACK_LOCATION *pIoStack;\r
+ NTSTATUS status = STATUS_SUCCESS;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_IOCTL );\r
+\r
+ UNREFERENCED_PARAMETER( pDevObj );\r
+\r
+ pIoStack = IoGetCurrentIrpStackLocation( pIrp );\r
+\r
+ pIrp->IoStatus.Information = 0;\r
+\r
+ switch( pIoStack->Parameters.DeviceIoControl.IoControlCode )\r
+ {\r
+ case IOCTL_IBAT_PORTS:\r
+ IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_IOCTL,\r
+ ("IOCTL_IBAT_PORTS received\n") );\r
+ status = __ibat_get_ports( pIrp, pIoStack );\r
+ break;\r
+\r
+ case IOCTL_IBAT_IP_ADDRESSES:\r
+ IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_IOCTL,\r
+ ("IOCTL_IBAT_IP_ADDRESSES received\n" ));\r
+ status = __ibat_get_ips( pIrp, pIoStack );\r
+ break;\r
+\r
+ case IOCTL_IBAT_MAC_TO_GID:\r
+ IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_IOCTL,\r
+ ("IOCTL_IBAT_MAC_TO_GID received\n" ));\r
+ status = __ibat_mac_to_gid( pIrp, pIoStack );\r
+ break;\r
+\r
+ case IOCTL_IBAT_IP_TO_PORT:\r
+ IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_IOCTL,\r
+ ("IOCTL_IBAT_IP_TO_PORT received\n" ));\r
+ status = __ibat_ip_to_port( pIrp, pIoStack );\r
+ break;\r
+\r
+ case IOCTL_IBAT_MAC_TO_PATH:\r
+ IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_IOCTL,\r
+ ("IOCTL_IBAT_MAC_TO_PATH received\n" ));\r
+ status = __ibat_mac_to_path( pIrp, pIoStack );\r
+ break;\r
+\r
+ default:\r
+ IPOIB_PRINT( TRACE_LEVEL_VERBOSE, IPOIB_DBG_IOCTL,\r
+ ("unknow IOCTL code = 0x%x\n",\r
+ pIoStack->Parameters.DeviceIoControl.IoControlCode) );\r
+ status = STATUS_INVALID_PARAMETER;\r
+ }\r
+\r
+ pIrp->IoStatus.Status = status;\r
+ IoCompleteRequest( pIrp, IO_NO_INCREMENT );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
+ return status;\r
+}\r
+\r
+\r
+++ /dev/null
-/*\r
- * Copyright (c) 2005 SilverStorm Technologies. All rights reserved.\r
- * Copyright (c) 2006 Mellanox Technologies. All rights reserved.\r
- * Portions Copyright (c) 2008 Microsoft Corporation. All rights reserved.\r
- *\r
- * This software is available to you under the OpenIB.org BSD license\r
- * below:\r
- *\r
- * Redistribution and use in source and binary forms, with or\r
- * without modification, are permitted provided that the following\r
- * conditions are met:\r
- *\r
- * - Redistributions of source code must retain the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer.\r
- *\r
- * - Redistributions in binary form must reproduce the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer in the documentation and/or other materials\r
- * provided with the distribution.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- * SOFTWARE.\r
- *\r
- * $Id: ipoib_port.c 4506 2009-06-23 14:40:54Z xalex $\r
- */\r
-\r
-\r
-\r
-#include "ipoib_endpoint.h"\r
-#include "ipoib_port.h"\r
-#include "ipoib_adapter.h"\r
-#include "ipoib_debug.h"\r
-#if defined(EVENT_TRACING)\r
-#ifdef offsetof\r
-#undef offsetof\r
-#endif\r
-#include "ipoib_port.tmh"\r
-#endif\r
-#include <offload.h>\r
-\r
-#include "wdm.h"\r
-#include <ntddk.h>\r
-\r
-\r
-\r
-ib_gid_t bcast_mgid_template = {\r
- 0xff, /* multicast field */\r
- 0x12, /* scope (to be filled in) */\r
- 0x40, 0x1b, /* IPv4 signature */\r
- 0xff, 0xff, /* 16 bits of P_Key (to be filled in) */\r
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 48 bits of zeros */\r
- 0xff, 0xff, 0xff, 0xff, /* 32 bit IPv4 broadcast address */\r
-};\r
-\r
-\r
-#ifdef _DEBUG_\r
-/* Handy pointer for debug use. */\r
-ipoib_port_t *gp_ipoib_port;\r
-#endif\r
-\r
-static void __port_mcast_garbage_dpc(KDPC *p_gc_dpc,void *context,void *s_arg1, void *s_arg2);\r
-static void __port_do_mcast_garbage(ipoib_port_t* const p_port );\r
-\r
-\r
-static void __recv_cb_dpc(KDPC *p_gc_dpc,void *context,void *s_arg1, void *s_arg2);\r
-\r
-\r
-/******************************************************************************\r
-*\r
-* Declarations\r
-*\r
-******************************************************************************/\r
-static void\r
-__port_construct(\r
- IN ipoib_port_t* const p_port );\r
-\r
-static ib_api_status_t\r
-__port_init(\r
- IN ipoib_port_t* const p_port,\r
- IN ipoib_adapter_t* const p_adapter,\r
- IN ib_pnp_port_rec_t* const p_pnp_rec );\r
-\r
-static void\r
-__port_destroying(\r
- IN cl_obj_t* const p_obj );\r
-\r
-static void\r
-__port_cleanup(\r
- IN cl_obj_t* const p_obj );\r
-\r
-static void\r
-__port_free(\r
- IN cl_obj_t* const p_obj );\r
-\r
-static ib_api_status_t\r
-__port_query_ca_attrs( \r
- IN ipoib_port_t* const p_port,\r
- IN ib_ca_attr_t** pp_ca_attrs );\r
-\r
-static void\r
-__srq_async_event_cb(\r
-IN ib_async_event_rec_t *p_event_rec );\r
-\r
-/******************************************************************************\r
-*\r
-* IB resource manager operations\r
-*\r
-******************************************************************************/\r
-static void\r
-__ib_mgr_construct(\r
- IN ipoib_port_t* const p_port );\r
-\r
-static ib_api_status_t\r
-__ib_mgr_init(\r
- IN ipoib_port_t* const p_port );\r
-\r
-static void\r
-__ib_mgr_destroy(\r
- IN ipoib_port_t* const p_port );\r
-\r
-static void\r
-__qp_event(\r
- IN ib_async_event_rec_t *p_event_rec );\r
-\r
-static void\r
-__cq_event(\r
- IN ib_async_event_rec_t *p_event_rec );\r
-\r
-static ib_api_status_t\r
-__ib_mgr_activate(\r
- IN ipoib_port_t* const p_port );\r
-\r
-/******************************************************************************\r
-*\r
-* Buffer manager operations.\r
-*\r
-******************************************************************************/\r
-static void\r
-__buf_mgr_construct(\r
- IN ipoib_port_t* const p_port );\r
-\r
-static ib_api_status_t\r
-__buf_mgr_init(\r
- IN ipoib_port_t* const p_port );\r
-\r
-static void\r
-__buf_mgr_destroy(\r
- IN ipoib_port_t* const p_port );\r
-\r
-static cl_status_t\r
-__recv_ctor(\r
- IN void* const p_object,\r
- IN void* context,\r
- OUT cl_pool_item_t** const pp_pool_item );\r
-\r
-#if !IPOIB_INLINE_RECV\r
-static void\r
-__recv_dtor(\r
- IN const cl_pool_item_t* const p_pool_item,\r
- IN void *context );\r
-#endif /* IPOIB_INLINE_RECV */\r
-\r
-static inline ipoib_send_desc_t*\r
-__buf_mgr_get_send(\r
- IN ipoib_port_t* const p_port );\r
-\r
-static inline void\r
-__buf_mgr_put_send(\r
- IN ipoib_port_t* const p_port,\r
- IN ipoib_send_desc_t* const p_desc );\r
-\r
-static inline ipoib_recv_desc_t*\r
-__buf_mgr_get_recv(\r
- IN ipoib_port_t* const p_port );\r
-\r
-static inline void\r
-__buf_mgr_put_recv(\r
- IN ipoib_port_t* const p_port,\r
- IN ipoib_recv_desc_t* const p_desc,\r
- IN NET_BUFFER_LIST* const p_net_buffer_list OPTIONAL );\r
-\r
-static inline void\r
-__buf_mgr_put_recv_list(\r
- IN ipoib_port_t* const p_port,\r
- IN cl_qlist_t* const p_list );\r
-\r
-//NDIS60\r
-static inline NET_BUFFER_LIST*\r
-__buf_mgr_get_ndis_pkt(\r
- IN ipoib_port_t* const p_port,\r
- IN ipoib_recv_desc_t* const p_desc );\r
-\r
-\r
-/******************************************************************************\r
-*\r
-* Receive manager operations.\r
-*\r
-******************************************************************************/\r
-static void\r
-__recv_mgr_construct(\r
- IN ipoib_port_t* const p_port );\r
-\r
-static ib_api_status_t\r
-__recv_mgr_init(\r
- IN ipoib_port_t* const p_port );\r
-\r
-static void\r
-__recv_mgr_destroy(\r
- IN ipoib_port_t* const p_port );\r
-\r
-/* Posts receive buffers to the receive queue. */\r
-static ib_api_status_t\r
-__recv_mgr_repost(\r
- IN ipoib_port_t* const p_port );\r
-\r
-static void\r
-__recv_cb(\r
- IN const ib_cq_handle_t h_cq,\r
- IN void *cq_context );\r
-\r
-static void\r
-__recv_get_endpts(\r
- IN ipoib_port_t* const p_port,\r
- IN ipoib_recv_desc_t* const p_desc,\r
- IN ib_wc_t* const p_wc,\r
- OUT ipoib_endpt_t** const pp_src,\r
- OUT ipoib_endpt_t** const pp_dst );\r
-\r
-static int32_t\r
-__recv_mgr_filter(\r
- IN ipoib_port_t* const p_port,\r
- IN ib_wc_t* const p_done_wc_list,\r
- OUT cl_qlist_t* const p_done_list,\r
- OUT cl_qlist_t* const p_bad_list );\r
-\r
-static ib_api_status_t\r
-__recv_gen(\r
- IN const ipoib_pkt_t* const p_ipoib,\r
- OUT eth_pkt_t* const p_eth,\r
- IN ipoib_endpt_t* const p_src,\r
- IN ipoib_endpt_t* const p_dst );\r
-\r
-static ib_api_status_t\r
-__recv_dhcp(\r
- IN ipoib_port_t* const p_port,\r
- IN const ipoib_pkt_t* const p_ipoib,\r
- OUT eth_pkt_t* const p_eth,\r
- IN ipoib_endpt_t* const p_src,\r
- IN ipoib_endpt_t* const p_dst );\r
-\r
-static ib_api_status_t\r
-__recv_arp(\r
- IN ipoib_port_t* const p_port,\r
- IN ib_wc_t* const p_wc,\r
- IN const ipoib_pkt_t* const p_ipoib,\r
- OUT eth_pkt_t* const p_eth,\r
- IN ipoib_endpt_t** const p_src,\r
- IN ipoib_endpt_t* const p_dst );\r
-\r
-static ib_api_status_t\r
-__recv_mgr_prepare_pkt(\r
- IN ipoib_port_t* const p_port,\r
- IN ipoib_recv_desc_t* const p_desc,\r
- OUT NET_BUFFER_LIST** const pp_net_buffer_list );\r
-\r
-static uint32_t\r
-__recv_mgr_build_pkt_array(\r
- IN ipoib_port_t* const p_port,\r
- IN int32_t shortage,\r
- OUT cl_qlist_t* const p_done_list,\r
- OUT int32_t* const p_discarded );\r
-\r
-/******************************************************************************\r
-*\r
-* Send manager operations.\r
-*\r
-******************************************************************************/\r
-static void\r
-__send_mgr_construct(\r
- IN ipoib_port_t* const p_port );\r
-\r
-static void\r
-__send_mgr_destroy(\r
- IN ipoib_port_t* const p_port );\r
-\r
-static NDIS_STATUS\r
-__send_gen(\r
- IN ipoib_port_t* const p_port,\r
- IN ipoib_send_desc_t* const p_desc,\r
- IN SCATTER_GATHER_LIST *p_sgl,\r
- IN INT lso_data_index);\r
-\r
-static NDIS_STATUS\r
-__send_mgr_filter_ip(\r
- IN ipoib_port_t* const p_port,\r
- IN const eth_hdr_t* const p_eth_hdr,\r
- IN MDL* p_mdl,\r
- IN size_t buf_len,\r
- IN SCATTER_GATHER_LIST *p_sgl,\r
- IN OUT ipoib_send_desc_t* const p_desc );\r
-\r
-static NDIS_STATUS\r
-__send_mgr_filter_igmp_v2(\r
- IN ipoib_port_t* const p_port,\r
- IN const ip_hdr_t* const p_ip_hdr,\r
- IN size_t iph_options_size,\r
- IN MDL* p_mdl,\r
- IN size_t buf_len );\r
-\r
-static NDIS_STATUS\r
-__send_mgr_filter_udp(\r
- IN ipoib_port_t* const p_port,\r
- IN const ip_hdr_t* const p_ip_hdr,\r
- IN MDL* p_mdl,\r
- IN size_t buf_len,\r
- IN SCATTER_GATHER_LIST *p_sgl,\r
- IN OUT ipoib_send_desc_t* const p_desc );\r
-\r
-static NDIS_STATUS\r
-__send_mgr_filter_dhcp(\r
- IN ipoib_port_t* const p_port,\r
- IN const udp_hdr_t* const p_udp_hdr,\r
- IN MDL* p_mdl,\r
- IN size_t buf_len,\r
- IN OUT ipoib_send_desc_t* const p_desc );\r
-\r
-static NDIS_STATUS\r
-__send_mgr_filter_arp(\r
- IN ipoib_port_t* const p_port,\r
- IN const eth_hdr_t* const p_eth_hdr,\r
- IN MDL* p_mdl,\r
- IN size_t buf_len,\r
- IN OUT ipoib_send_desc_t* const p_desc );\r
-\r
-static void\r
-__process_failed_send(\r
- IN ipoib_port_t* const p_port,\r
- IN ipoib_send_desc_t* const p_desc,\r
- IN const NDIS_STATUS status,\r
- IN ULONG send_complete_flags );\r
-\r
-static inline NDIS_STATUS\r
-__send_mgr_queue(\r
- IN ipoib_port_t* const p_port,\r
- IN eth_hdr_t* const p_eth_hdr,\r
- OUT ipoib_endpt_t** const pp_endpt );\r
-\r
-static NDIS_STATUS\r
-__build_send_desc(\r
- IN ipoib_port_t* const p_port,\r
- IN eth_hdr_t* const p_eth_hdr,\r
- IN MDL* const p_mdl,\r
- IN const size_t mdl_len,\r
- IN SCATTER_GATHER_LIST *p_sgl,\r
- IN OUT ipoib_send_desc_t* const p_desc );\r
-\r
-\r
-static void\r
-__send_cb(\r
- IN const ib_cq_handle_t h_cq,\r
- IN void *cq_context );\r
-\r
-static NDIS_STATUS \r
-GetLsoHeaderSize(\r
- IN PNET_BUFFER pNetBuffer,\r
- IN LsoData *pLsoData,\r
- OUT UINT *IndexOfData,\r
- IN ipoib_hdr_t *ipoib_hdr );\r
-\r
-\r
-static NDIS_STATUS\r
-__build_lso_desc(\r
- IN ipoib_port_t* const p_port,\r
- IN OUT ipoib_send_desc_t* const p_desc,\r
- IN ULONG mss,\r
- IN SCATTER_GATHER_LIST *p_sgl,\r
- IN int32_t hdr_idx,\r
- IN PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO p_lso_info );\r
-\r
-static NDIS_STATUS\r
-__send_fragments(\r
- IN ipoib_port_t* const p_port,\r
- IN ipoib_send_desc_t* const p_desc,\r
- IN eth_hdr_t* const p_eth_hdr,\r
- IN ip_hdr_t* const p_ip_hdr,\r
- IN uint32_t buf_len,\r
- IN NDIS_BUFFER* p_ndis_buf );\r
-\r
-static void\r
-__update_fragment_ip_hdr(\r
-IN ip_hdr_t* const p_ip_hdr,\r
-IN uint16_t fragment_size, \r
-IN uint16_t fragment_offset, \r
-IN BOOLEAN more_fragments );\r
-\r
-static void\r
-__copy_ip_options(\r
-IN uint8_t* p_buf,\r
-IN uint8_t* p_options,\r
-IN uint32_t options_len,\r
-IN BOOLEAN copy_all );\r
-/******************************************************************************\r
-*\r
-* Endpoint manager operations\r
-*\r
-******************************************************************************/\r
-static void\r
-__endpt_mgr_construct(\r
- IN ipoib_port_t* const p_port );\r
-\r
-static ib_api_status_t\r
-__endpt_mgr_init(\r
- IN ipoib_port_t* const p_port );\r
-\r
-static void\r
-__endpt_mgr_destroy(\r
- IN ipoib_port_t* const p_port );\r
-\r
-/****f* IPoIB/__endpt_mgr_remove_all\r
-* NAME\r
-* __endpt_mgr_remove_all\r
-*\r
-* DESCRIPTION\r
-* Removes all enpoints from the port, dereferencing them to initiate\r
-* destruction.\r
-*\r
-* SYNOPSIS\r
-*/\r
-static void\r
-__endpt_mgr_remove_all(\r
- IN ipoib_port_t* const p_port );\r
-/*\r
-********/\r
-\r
-static void\r
-__endpt_mgr_remove(\r
- IN ipoib_port_t* const p_port,\r
- IN ipoib_endpt_t* const p_endpt );\r
-\r
-static void\r
-__endpt_mgr_reset_all(\r
- IN ipoib_port_t* const p_port );\r
-\r
-static inline NDIS_STATUS\r
-__endpt_mgr_ref(\r
- IN ipoib_port_t* const p_port,\r
- IN const mac_addr_t mac,\r
- OUT ipoib_endpt_t** const pp_endpt );\r
-\r
-static inline NDIS_STATUS\r
-__endpt_mgr_get_gid_qpn(\r
- IN ipoib_port_t* const p_port,\r
- IN const mac_addr_t mac,\r
- OUT ib_gid_t* const p_gid,\r
- OUT UNALIGNED net32_t* const p_qpn );\r
-\r
-static inline ipoib_endpt_t*\r
-__endpt_mgr_get_by_gid(\r
- IN ipoib_port_t* const p_port,\r
- IN const ib_gid_t* const p_gid );\r
-\r
-static inline ipoib_endpt_t*\r
-__endpt_mgr_get_by_lid(\r
- IN ipoib_port_t* const p_port,\r
- IN const net16_t lid );\r
-\r
-static inline ib_api_status_t\r
-__endpt_mgr_insert_locked(\r
- IN ipoib_port_t* const p_port,\r
- IN const mac_addr_t mac,\r
- IN ipoib_endpt_t* const p_endpt );\r
-\r
-static inline ib_api_status_t\r
-__endpt_mgr_insert(\r
- IN ipoib_port_t* const p_port,\r
- IN const mac_addr_t mac,\r
- IN ipoib_endpt_t* const p_endpt );\r
-\r
-static ib_api_status_t\r
-__endpt_mgr_add_local(\r
- IN ipoib_port_t* const p_port,\r
- IN ib_port_info_t* const p_port_info );\r
-\r
-static ib_api_status_t\r
-__endpt_mgr_add_bcast(\r
- IN ipoib_port_t* const p_port,\r
- IN ib_mcast_rec_t *p_mcast_rec );\r
-\r
-/******************************************************************************\r
-*\r
-* MCast operations.\r
-*\r
-******************************************************************************/\r
-static ib_api_status_t\r
-__port_get_bcast(\r
- IN ipoib_port_t* const p_port );\r
-\r
-static ib_api_status_t\r
-__port_join_bcast(\r
- IN ipoib_port_t* const p_port,\r
- IN ib_member_rec_t* const p_member_rec );\r
-\r
-static ib_api_status_t\r
-__port_create_bcast(\r
- IN ipoib_port_t* const p_port );\r
-\r
-\r
-\r
-static void\r
-__bcast_get_cb(\r
- IN ib_query_rec_t *p_query_rec );\r
-\r
-\r
-static void\r
-__bcast_cb(\r
- IN ib_mcast_rec_t *p_mcast_rec );\r
-\r
-\r
-static void\r
-__mcast_cb(\r
- IN ib_mcast_rec_t *p_mcast_rec );\r
-\r
-void\r
-__leave_error_mcast_cb(\r
- IN void *context );\r
-\r
-\r
-static intn_t\r
-__gid_cmp(\r
- IN const void* const p_key1,\r
- IN const void* const p_key2 )\r
-{\r
- return cl_memcmp( p_key1, p_key2, sizeof(ib_gid_t) );\r
-}\r
-\r
-\r
-inline void ipoib_port_ref( ipoib_port_t * p_port, int type )\r
-{\r
- cl_obj_ref( &p_port->obj );\r
-#if DBG\r
- cl_atomic_inc( &p_port->ref[type % ref_mask] );\r
- if ((p_port->obj.ref_cnt % 20)==0)\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OBJ,\r
- ("ref type %d ref_cnt %d\n", type, p_port->obj.ref_cnt) );\r
- //TODO remove\r
- //ASSERT (p_port->obj.ref_cnt < 100);\r
-#else\r
- UNREFERENCED_PARAMETER(type);\r
-#endif\r
-}\r
-\r
-\r
-inline void ipoib_port_deref(ipoib_port_t * p_port, int type)\r
-{\r
-#if DBG\r
- cl_atomic_dec( &p_port->ref[type % ref_mask] );\r
- if ((p_port->obj.ref_cnt % 20) == 0)\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OBJ,\r
- ("deref type %d ref_cnt %d\n", type, p_port->obj.ref_cnt) );\r
-#else\r
- UNREFERENCED_PARAMETER(type);\r
-#endif\r
- cl_obj_deref( &p_port->obj );\r
-\r
-}\r
-\r
-/* function returns pointer to payload that is going after IP header.\r
-* asssuming that payload and IP header are in the same buffer\r
-*/\r
-static void* GetIpPayloadPtr(const ip_hdr_t* const p_ip_hdr)\r
-{\r
- return (void*)((uint8_t*)p_ip_hdr + IP_HEADER_LENGTH(p_ip_hdr));\r
-}\r
-\r
-/******************************************************************************\r
-*\r
-* Implementation\r
-*\r
-******************************************************************************/\r
-ib_api_status_t\r
-ipoib_create_port(\r
- IN ipoib_adapter_t* const p_adapter,\r
- IN ib_pnp_port_rec_t* const p_pnp_rec,\r
- OUT ipoib_port_t** const pp_port )\r
-{\r
- ib_api_status_t status;\r
- ipoib_port_t *p_port;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-\r
- CL_ASSERT( !p_adapter->p_port );\r
-\r
- p_port = cl_zalloc( sizeof(ipoib_port_t) +\r
- (sizeof(ipoib_hdr_t) * (p_adapter->params.sq_depth - 1)) );\r
- if( !p_port )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Failed to allocate ipoib_port_t (%d bytes)\n",\r
- sizeof(ipoib_port_t)) );\r
- return IB_INSUFFICIENT_MEMORY;\r
- }\r
-\r
-#ifdef _DEBUG_\r
- gp_ipoib_port = p_port;\r
-#endif\r
-\r
- __port_construct( p_port );\r
-\r
- status = __port_init( p_port, p_adapter, p_pnp_rec );\r
- if( status != IB_SUCCESS )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ipoib_port_init returned %s.\n", \r
- p_adapter->p_ifc->get_err_str( status )) );\r
- __port_cleanup( &p_port->obj );\r
- __port_free( &p_port->obj );\r
- return status;\r
- }\r
-\r
- *pp_port = p_port;\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
- return IB_SUCCESS;\r
-}\r
-\r
-\r
-void\r
-ipoib_port_destroy(\r
- IN ipoib_port_t* const p_port )\r
-{\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-\r
- CL_ASSERT( p_port );\r
- CL_ASSERT( p_port->p_adapter );\r
- CL_ASSERT( !p_port->p_adapter->p_port );\r
-\r
- cl_obj_destroy( &p_port->obj );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
-}\r
-\r
-\r
-static void\r
-__port_construct(\r
- IN ipoib_port_t* const p_port )\r
-{\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-\r
- p_port->state = IB_QPS_RESET;\r
-\r
- cl_obj_construct( &p_port->obj, IPOIB_OBJ_PORT );\r
- cl_spinlock_construct( &p_port->send_lock );\r
- cl_spinlock_construct( &p_port->recv_lock );\r
- __ib_mgr_construct( p_port );\r
- __buf_mgr_construct( p_port );\r
-\r
- __recv_mgr_construct( p_port );\r
- __send_mgr_construct( p_port );\r
-\r
- __endpt_mgr_construct( p_port );\r
-\r
- KeInitializeEvent( &p_port->sa_event, NotificationEvent, TRUE );\r
- KeInitializeEvent( &p_port->leave_mcast_event, NotificationEvent, TRUE );\r
- \r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
-}\r
-\r
-\r
-static ib_api_status_t\r
-__port_init(\r
- IN ipoib_port_t* const p_port,\r
- IN ipoib_adapter_t* const p_adapter,\r
- IN ib_pnp_port_rec_t* const p_pnp_rec )\r
-{\r
- cl_status_t cl_status;\r
- ib_api_status_t status;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-\r
- p_port->port_num = p_pnp_rec->p_port_attr->port_num;\r
- p_port->p_adapter = p_adapter;\r
-\r
- cl_status = cl_spinlock_init( &p_port->send_lock );\r
- if( cl_status != CL_SUCCESS )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("cl_spinlock_init returned %#x\n", cl_status) );\r
- return IB_ERROR;\r
- }\r
-\r
- cl_status = cl_spinlock_init( &p_port->recv_lock );\r
- if( cl_status != CL_SUCCESS )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("cl_spinlock_init returned %#x\n", cl_status) );\r
- return IB_ERROR;\r
- }\r
-\r
- /* Initialize the IB resource manager. */\r
- status = __ib_mgr_init( p_port );\r
- if( status != IB_SUCCESS )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("__ib_mgr_init returned %s\n", \r
- p_adapter->p_ifc->get_err_str( status )) );\r
- return status;\r
- }\r
-\r
- /* Initialize the buffer manager. */\r
- status = __buf_mgr_init( p_port );\r
- if( status != IB_SUCCESS )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("__buf_mgr_init returned %s\n", \r
- p_adapter->p_ifc->get_err_str( status )) );\r
- return status;\r
- }\r
-\r
- /* Initialize the receive manager. */\r
- status = __recv_mgr_init( p_port );\r
- if( status != IB_SUCCESS )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("__recv_mgr_init returned %s\n", \r
- p_adapter->p_ifc->get_err_str( status )) );\r
- return status;\r
- }\r
-\r
- /* Initialize the endpoint manager. */\r
- status = __endpt_mgr_init( p_port );\r
- if( status != IB_SUCCESS )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("__endpt_mgr_init returned %s\n", \r
- p_adapter->p_ifc->get_err_str( status )) );\r
- return status;\r
- }\r
-\r
- KeInitializeDpc(&p_port->recv_dpc,(PKDEFERRED_ROUTINE)__recv_cb_dpc,p_port);\r
-\r
-\r
- /* Initialize multicast garbage collector timer and DPC object */\r
- KeInitializeDpc(&p_port->gc_dpc,(PKDEFERRED_ROUTINE)__port_mcast_garbage_dpc,p_port);\r
- KeInitializeTimerEx(&p_port->gc_timer,SynchronizationTimer);\r
-\r
- /* We only ever destroy from the PnP callback thread. */\r
- cl_status = cl_obj_init( &p_port->obj, CL_DESTROY_SYNC,\r
- __port_destroying, __port_cleanup, __port_free );\r
-\r
-#if DBG\r
- cl_atomic_inc( &p_port->ref[ref_init] );\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OBJ,\r
- ("ref type %d ref_cnt %d\n", ref_init, p_port->obj.ref_cnt) );\r
-#endif\r
-\r
- if( cl_status != CL_SUCCESS )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("cl_obj_init returned %#x\n", cl_status) );\r
- return IB_ERROR;\r
- }\r
-\r
- cl_status = cl_obj_insert_rel( &p_port->rel, &p_adapter->obj, &p_port->obj );\r
- if( cl_status != CL_SUCCESS )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("cl_obj_insert_rel returned %#x\n", cl_status) );\r
- cl_obj_destroy( &p_port->obj );\r
- return IB_ERROR;\r
- }\r
-\r
-#if DBG\r
- cl_atomic_inc( &p_port->ref[ref_init] );\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_OBJ,\r
- ("ref type %d ref_cnt %d\n", ref_init, p_port->obj.ref_cnt) );\r
-#endif\r
-\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
- return IB_SUCCESS;\r
-}\r
-\r
-\r
-static void\r
-__port_destroying(\r
- IN cl_obj_t* const p_obj )\r
-{\r
- ipoib_port_t *p_port;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-\r
- CL_ASSERT( p_obj );\r
-\r
- p_port = PARENT_STRUCT( p_obj, ipoib_port_t, obj );\r
-\r
- ipoib_port_down( p_port );\r
-\r
- __endpt_mgr_remove_all( p_port );\r
-\r
-#if 0\r
- if( p_port->p_adapter->params.cm_enabled )\r
- {\r
- endpt_cm_buf_mgr_destroy( p_port );\r
- ipoib_port_srq_destroy( p_port );\r
- p_port->endpt_mgr.thread_is_done = 1;\r
- cl_event_signal( &p_port->endpt_mgr.event );\r
- }\r
-#endif\r
- ASSERT(FALSE);\r
- //TODO NDIS6.0\r
- ipoib_port_resume( p_port, FALSE );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
-}\r
-\r
-\r
-static void\r
-__port_cleanup(\r
- IN cl_obj_t* const p_obj )\r
-{\r
- ipoib_port_t *p_port;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-\r
- CL_ASSERT( p_obj );\r
-\r
- p_port = PARENT_STRUCT( p_obj, ipoib_port_t, obj );\r
-\r
- /* Wait for all sends and receives to get flushed. */\r
- while( p_port->send_mgr.depth || p_port->recv_mgr.depth )\r
- cl_thread_suspend( 0 );\r
-\r
- /* Destroy the send and receive managers before closing the CA. */\r
- __ib_mgr_destroy( p_port );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
-}\r
-\r
-\r
-static void\r
-__port_free(\r
- IN cl_obj_t* const p_obj )\r
-{\r
- ipoib_port_t *p_port;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-\r
- CL_ASSERT( p_obj );\r
-\r
- p_port = PARENT_STRUCT( p_obj, ipoib_port_t, obj );\r
-\r
- KeCancelTimer(&p_port->gc_timer);\r
- KeFlushQueuedDpcs();\r
- __endpt_mgr_destroy( p_port );\r
- __recv_mgr_destroy( p_port );\r
- __send_mgr_destroy( p_port );\r
- __buf_mgr_destroy( p_port );\r
-\r
- cl_spinlock_destroy( &p_port->send_lock );\r
- cl_spinlock_destroy( &p_port->recv_lock );\r
-\r
- cl_obj_deinit( p_obj );\r
- if( p_port->p_ca_attrs )\r
- {\r
- cl_free ( p_port->p_ca_attrs );\r
- }\r
- cl_free( p_port );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
-}\r
-\r
-\r
-\r
-/******************************************************************************\r
-*\r
-* IB resource manager implementation.\r
-*\r
-******************************************************************************/\r
-static void\r
-__ib_mgr_construct(\r
- IN ipoib_port_t* const p_port )\r
-{\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-\r
- cl_memclr( &p_port->ib_mgr, sizeof(ipoib_ib_mgr_t) );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
-}\r
-\r
-\r
-static ib_api_status_t\r
-__ib_mgr_init(\r
- IN ipoib_port_t* const p_port )\r
-{\r
- ib_api_status_t status;\r
- ib_cq_create_t cq_create;\r
- ib_qp_create_t qp_create;\r
- ib_phys_create_t phys_create;\r
- ib_phys_range_t phys_range;\r
- uint64_t vaddr;\r
- net32_t rkey;\r
- ib_qp_attr_t qp_attr;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-\r
- /* Open the CA. */\r
- status = p_port->p_adapter->p_ifc->open_ca(\r
- p_port->p_adapter->h_al, p_port->p_adapter->guids.ca_guid,\r
- NULL, p_port, &p_port->ib_mgr.h_ca );\r
- if( status != IB_SUCCESS )\r
- {\r
- NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
- EVENT_IPOIB_OPEN_CA, 1, status );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ib_open_ca returned %s\n", \r
- p_port->p_adapter->p_ifc->get_err_str( status )) );\r
- return status;\r
- }\r
-\r
- status = __port_query_ca_attrs( p_port, &p_port->p_ca_attrs );\r
- if( status != IB_SUCCESS )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Query CA attributes failed\n" ) );\r
- return status;\r
- }\r
-#if 0\r
- if( p_port->p_adapter->params.cm_enabled )\r
- {\r
- uint32_t payload_mtu = __port_attr_to_mtu_size( \r
- p_port->p_ca_attrs->p_port_attr[p_port->port_num - 1].mtu )\r
- - sizeof(ipoib_hdr_t);\r
- /* adjust ipoib UD payload MTU to actual port MTU size. */\r
- p_port->p_adapter->params.payload_mtu = \r
- max( DEFAULT_PAYLOAD_MTU, payload_mtu );\r
- p_port->p_adapter->params.xfer_block_size = \r
- (sizeof(eth_hdr_t) + p_port->p_adapter->params.payload_mtu);\r
- }\r
-#endif\r
-#if IPOIB_USE_DMA\r
- /* init DMA only once while running MiniportInitialize */\r
- if ( !p_port->p_adapter->reset )\r
- {\r
- ULONG max_phys_mapping;\r
- if( p_port->p_adapter->params.cm_enabled )\r
- {\r
- max_phys_mapping = p_port->p_adapter->params.cm_xfer_block_size;\r
- }\r
- else if( p_port->p_adapter->params.lso )\r
- {\r
- max_phys_mapping = LARGE_SEND_OFFLOAD_SIZE;\r
- }\r
- else\r
- {\r
- max_phys_mapping = p_port->p_adapter->params.xfer_block_size;\r
- }\r
- /*if( NdisMInitializeScatterGatherDma( p_port->p_adapter->h_adapter,\r
- TRUE, max_phys_mapping )!= NDIS_STATUS_SUCCESS )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("NdisMInitializeScatterGatherDma failed\n" ) );\r
- return IB_INSUFFICIENT_RESOURCES;\r
- }*/\r
- }\r
-#endif\r
-\r
- /* Allocate the PD. */\r
- status = p_port->p_adapter->p_ifc->alloc_pd(\r
- p_port->ib_mgr.h_ca, IB_PDT_UD, p_port, &p_port->ib_mgr.h_pd );\r
- if( status != IB_SUCCESS )\r
- {\r
- NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
- EVENT_IPOIB_ALLOC_PD, 1, status );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ib_alloc_pd returned %s\n", \r
- p_port->p_adapter->p_ifc->get_err_str( status )) );\r
- return status;\r
- }\r
-\r
- /* Allocate receive CQ. */\r
- cq_create.size = p_port->p_adapter->params.rq_depth;\r
- cq_create.pfn_comp_cb = __recv_cb;\r
- cq_create.h_wait_obj = NULL;\r
-\r
- status = p_port->p_adapter->p_ifc->create_cq(\r
- p_port->ib_mgr.h_ca, &cq_create, p_port,\r
- __cq_event, &p_port->ib_mgr.h_recv_cq );\r
- if( status != IB_SUCCESS )\r
- {\r
- NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
- EVENT_IPOIB_CREATE_RECV_CQ, 1, status );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ib_create_cq returned %s.\n", \r
- p_port->p_adapter->p_ifc->get_err_str( status )) );\r
- return status;\r
- }\r
-\r
- /* Allocate send CQ. */\r
- cq_create.size = p_port->p_adapter->params.sq_depth;\r
- cq_create.pfn_comp_cb = __send_cb;\r
-\r
- status = p_port->p_adapter->p_ifc->create_cq(\r
- p_port->ib_mgr.h_ca, &cq_create, p_port,\r
- __cq_event, &p_port->ib_mgr.h_send_cq );\r
- if( status != IB_SUCCESS )\r
- {\r
- NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
- EVENT_IPOIB_CREATE_SEND_CQ, 1, status );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ib_create_cq returned %s.\n", \r
- p_port->p_adapter->p_ifc->get_err_str( status )) );\r
- return status;\r
- }\r
- \r
- /* Allocate the QP. */\r
- cl_memclr( &qp_create, sizeof(qp_create) );\r
- qp_create.qp_type = IB_QPT_UNRELIABLE_DGRM;\r
- qp_create.rq_depth = p_port->p_adapter->params.rq_depth;\r
- qp_create.rq_sge = 2; /* To support buffers spanning pages. */\r
- qp_create.h_rq_cq = p_port->ib_mgr.h_recv_cq;\r
- qp_create.sq_depth = p_port->p_adapter->params.sq_depth;\r
-\r
-#define UD_QP_USED_SGE 3\r
- qp_create.sq_sge = MAX_SEND_SGE < p_port->p_ca_attrs->max_sges ? \r
- MAX_SEND_SGE : ( p_port->p_ca_attrs->max_sges - UD_QP_USED_SGE );\r
- if ( !p_port->p_ca_attrs->ipoib_csum ) \r
- { \r
- /* checksum is not supported by device\r
- user must specify BYPASS to explicitly cancel checksum calculation */\r
- if (p_port->p_adapter->params.send_chksum_offload == CSUM_ENABLED)\r
- p_port->p_adapter->params.send_chksum_offload = CSUM_DISABLED;\r
- if (p_port->p_adapter->params.recv_chksum_offload == CSUM_ENABLED)\r
- p_port->p_adapter->params.recv_chksum_offload = CSUM_DISABLED;\r
- }\r
-\r
- qp_create.h_sq_cq = p_port->ib_mgr.h_send_cq;\r
- qp_create.sq_signaled = FALSE;\r
- status = p_port->p_adapter->p_ifc->create_qp(\r
- p_port->ib_mgr.h_pd, &qp_create, p_port,\r
- __qp_event, &p_port->ib_mgr.h_qp );\r
- if( status != IB_SUCCESS )\r
- {\r
- NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
- EVENT_IPOIB_CREATE_QP, 1, status );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ib_create_qp returned %s\n", \r
- p_port->p_adapter->p_ifc->get_err_str( status )) );\r
- return status;\r
- }\r
- /* Query the QP so we can get our QPN. */\r
- status = p_port->p_adapter->p_ifc->query_qp(\r
- p_port->ib_mgr.h_qp, &qp_attr );\r
- if( status != IB_SUCCESS )\r
- {\r
- NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
- EVENT_IPOIB_QUERY_QP, 1, status );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ib_query_qp returned %s\n", \r
- p_port->p_adapter->p_ifc->get_err_str( status )) );\r
- return status;\r
- }\r
- p_port->ib_mgr.qpn = qp_attr.num;\r
-\r
- /* Register all of physical memory */\r
- phys_create.length = MEM_REG_SIZE;\r
- phys_create.num_ranges = 1;\r
- phys_create.range_array = &phys_range;\r
- phys_create.buf_offset = 0;\r
- phys_create.hca_page_size = PAGE_SIZE;\r
- phys_create.access_ctrl = IB_AC_LOCAL_WRITE;\r
- phys_range.base_addr = 0;\r
- phys_range.size = MEM_REG_SIZE;\r
- vaddr = 0;\r
- status = p_port->p_adapter->p_ifc->reg_phys(\r
- p_port->ib_mgr.h_pd, &phys_create, &vaddr,\r
- &p_port->ib_mgr.lkey, &rkey, &p_port->ib_mgr.h_mr );\r
- if( status != IB_SUCCESS )\r
- {\r
- NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
- EVENT_IPOIB_REG_PHYS, 1, status );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ib_reg_phys returned %s\n", \r
- p_port->p_adapter->p_ifc->get_err_str( status )) );\r
- return status;\r
- }\r
-\r
- status = ipoib_port_srq_init( p_port );\r
- if( status != IB_SUCCESS )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ipoib_port_srq_init failed %s\n",\r
- p_port->p_adapter->p_ifc->get_err_str( status )) );\r
- /* disable further CM initialization */\r
- p_port->p_adapter->params.cm_enabled = FALSE;\r
-\r
- NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
- EVENT_IPOIB_CONNECTED_MODE_ERR, 1, 0xbadc0de1 );\r
-\r
- }\r
-//CM\r
-#if 0\r
- if( p_port->p_adapter->params.cm_enabled )\r
- {\r
- status = endpt_cm_buf_mgr_init( p_port );\r
- if( status != IB_SUCCESS )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("CM Init buf mgr failed status %#x\n", status ) );\r
- ipoib_port_srq_destroy( p_port );\r
- p_port->p_adapter->params.cm_enabled = FALSE;\r
-\r
- NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
- EVENT_IPOIB_CONNECTED_MODE_ERR, 1, 0xbadc0de2 );\r
- }\r
- else \r
- {\r
- if ( p_port->p_adapter->params.send_chksum_offload )\r
- p_port->p_adapter->params.send_chksum_offload = CSUM_DISABLED;\r
- }\r
- }\r
-#endif\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
- return IB_SUCCESS;\r
-}\r
-\r
-static void\r
-__srq_async_event_cb(\r
-IN ib_async_event_rec_t *p_event_rec )\r
-{\r
- ipoib_port_t* p_port = \r
- (ipoib_port_t *)p_event_rec->context;\r
-\r
- switch( p_event_rec->code )\r
- {\r
- case IB_AE_SRQ_LIMIT_REACHED:\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("SRQ ASYNC EVENT CODE %d: %s\n", \r
- p_event_rec->code, "IB_AE_SRQ_LIMIT_REACHED" ) );\r
- break;\r
- case IB_AE_SRQ_CATAS_ERROR:\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("SRQ ASYNC EVENT CODE %d: %s\n", \r
- p_event_rec->code, "IB_AE_SRQ_CATAS_ERROR" ) );\r
- /*SRQ is in err state, must reinitialize */\r
- p_port->p_adapter->hung = TRUE;\r
- break;\r
- case IB_AE_SRQ_QP_LAST_WQE_REACHED:\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("SRQ ASYNC EVENT CODE %d: %s\n", \r
- p_event_rec->code, "IB_AE_SRQ_QP_LAST_WQE_REACHED" ) );\r
- /*SRQ is in err state, must reinitialize */\r
- p_port->p_adapter->hung = TRUE;\r
- break;\r
- default:\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ASYNC EVENT CODE ARRIVED %d(%#x)\n", \r
- p_event_rec->code, p_event_rec->code ) );\r
- }\r
-}\r
-\r
-ib_api_status_t\r
-ipoib_port_srq_init(\r
- IN ipoib_port_t* const p_port )\r
-{\r
- ib_api_status_t ib_status;\r
- ib_srq_handle_t h_srq;\r
- ib_srq_attr_t srq_attr;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
- \r
- if( !p_port->p_adapter->params.cm_enabled )\r
- return IB_SUCCESS;\r
-\r
- srq_attr.max_sge = min( 2, p_port->p_ca_attrs->max_srq_sges );\r
- srq_attr.srq_limit = 10;\r
- srq_attr.max_wr = \r
- min( (uint32_t)p_port->p_adapter->params.rq_depth * 8,\r
- p_port->p_ca_attrs->max_srq_wrs/2 );\r
-\r
- ib_status = p_port->p_adapter->p_ifc->create_srq( \r
- p_port->ib_mgr.h_pd, \r
- &srq_attr, \r
- p_port, \r
- __srq_async_event_cb, \r
- &h_srq );\r
- if( ib_status != IB_SUCCESS )\r
- {\r
- NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
- EVENT_IPOIB_CREATE_QP, 1, ib_status );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ib_create_srq failed status %s\n", \r
- p_port->p_adapter->p_ifc->get_err_str( ib_status )) );\r
- return ib_status;\r
- }\r
- p_port->ib_mgr.h_srq = h_srq;\r
-\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
-\r
- return ib_status;\r
-}\r
-\r
-/* __port_query_ca_attrs() \r
- * returns a pointer to allocated memory.\r
- * must be released by caller.\r
- */\r
-static ib_api_status_t\r
-__port_query_ca_attrs( \r
- IN ipoib_port_t* const p_port,\r
- IN ib_ca_attr_t** pp_ca_attrs )\r
-{\r
- ib_api_status_t ib_status;\r
- uint32_t attr_size;\r
- ib_ca_attr_t* p_ca_attrs;\r
-\r
- *pp_ca_attrs = NULL;\r
-\r
- ib_status = \r
- p_port->p_adapter->p_ifc->query_ca( p_port->ib_mgr.h_ca, NULL , &attr_size );\r
- if( ib_status != IB_INSUFFICIENT_MEMORY )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ib_query_ca failed status %s\n",\r
- p_port->p_adapter->p_ifc->get_err_str( ib_status )) );\r
- goto done;\r
- }\r
- CL_ASSERT( attr_size );\r
-\r
- p_ca_attrs = cl_zalloc( attr_size );\r
- if ( p_ca_attrs == NULL )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Allocate %d bytes failed for CA Attributes\n", attr_size ));\r
- ib_status = IB_INSUFFICIENT_MEMORY;\r
- goto done;\r
- }\r
-\r
- ib_status = \r
- p_port->p_adapter->p_ifc->query_ca( p_port->ib_mgr.h_ca, p_ca_attrs , &attr_size );\r
- if ( ib_status != IB_SUCCESS )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("CA attributes query failed\n") );\r
- cl_free ( p_ca_attrs );\r
- goto done;\r
- }\r
-\r
- *pp_ca_attrs = p_ca_attrs;\r
-done:\r
- return ib_status;\r
-}\r
-\r
-void\r
-ipoib_port_srq_destroy( \r
- IN ipoib_port_t* const p_port )\r
-{\r
- ib_api_status_t status;\r
-\r
- if( p_port->ib_mgr.h_srq )\r
- {\r
- status =\r
- p_port->p_adapter->p_ifc->destroy_srq( p_port->ib_mgr.h_srq, NULL );\r
- CL_ASSERT( status == IB_SUCCESS );\r
- p_port->ib_mgr.h_srq = NULL;\r
- }\r
-}\r
-\r
-static void\r
-__ib_mgr_destroy(\r
- IN ipoib_port_t* const p_port )\r
-{\r
- ib_api_status_t status;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-\r
- if( p_port->ib_mgr.h_ca )\r
- {\r
- status =\r
- p_port->p_adapter->p_ifc->close_ca( p_port->ib_mgr.h_ca, NULL );\r
- CL_ASSERT( status == IB_SUCCESS );\r
- p_port->ib_mgr.h_ca = NULL;\r
- }\r
-\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
-}\r
-\r
-\r
-\r
-/******************************************************************************\r
-*\r
-* Buffer manager implementation.\r
-*\r
-******************************************************************************/\r
-static void\r
-__buf_mgr_construct(\r
- IN ipoib_port_t* const p_port )\r
-{\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-\r
- cl_qpool_construct( &p_port->buf_mgr.recv_pool );\r
-\r
- p_port->buf_mgr.h_packet_pool = NULL;\r
- p_port->buf_mgr.h_buffer_pool = NULL;\r
-\r
- NdisInitializeNPagedLookasideList( &p_port->buf_mgr.send_buf_list,\r
- NULL, NULL, 0, MAX_XFER_BLOCK_SIZE, 'bipi', 0 );\r
-\r
- p_port->buf_mgr.h_send_pkt_pool = NULL;\r
- p_port->buf_mgr.h_send_buf_pool = NULL;\r
-\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
-}\r
-\r
-\r
-static ib_api_status_t\r
-__buf_mgr_init(\r
- IN ipoib_port_t* const p_port )\r
-{\r
- cl_status_t cl_status;\r
- ipoib_params_t *p_params;\r
- NET_BUFFER_LIST_POOL_PARAMETERS pool_parameters;\r
- IPOIB_ENTER(IPOIB_DBG_INIT );\r
-\r
- CL_ASSERT( p_port );\r
- CL_ASSERT( p_port->p_adapter );\r
-\r
- p_params = &p_port->p_adapter->params;\r
-\r
- /* Allocate the receive descriptor pool */\r
- cl_status = cl_qpool_init( &p_port->buf_mgr.recv_pool,\r
- p_params->rq_depth * p_params->recv_pool_ratio,\r
-#if IPOIB_INLINE_RECV\r
- 0, 0, sizeof(ipoib_recv_desc_t), __recv_ctor, NULL, p_port );\r
-#else /* IPOIB_INLINE_RECV */\r
- 0, 0, sizeof(ipoib_recv_desc_t), __recv_ctor, __recv_dtor, p_port );\r
-#endif /* IPOIB_INLINE_RECV */\r
- if( cl_status != CL_SUCCESS )\r
- {\r
- NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
- EVENT_IPOIB_RECV_POOL, 1, cl_status );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("cl_qpool_init for recvs returned %#x\n",\r
- cl_status) );\r
- return IB_INSUFFICIENT_MEMORY;\r
- }\r
-\r
- /* Allocate the NET BUFFER list pools for receive indication. */\r
- NdisZeroMemory(&pool_parameters, sizeof(NET_BUFFER_LIST_POOL_PARAMETERS));\r
- pool_parameters.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;\r
- pool_parameters.Header.Revision = NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;\r
- pool_parameters.Header.Size = sizeof(pool_parameters);\r
- pool_parameters.ProtocolId = 0;\r
- pool_parameters.ContextSize = 0;\r
- pool_parameters.fAllocateNetBuffer = TRUE;\r
- pool_parameters.PoolTag = 'CRPI';\r
-\r
- p_port->buf_mgr.h_packet_pool = NdisAllocateNetBufferListPool(\r
- p_port->p_adapter->h_adapter,\r
- &pool_parameters); \r
-\r
- if( !p_port->buf_mgr.h_packet_pool )\r
- {\r
- NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
- EVENT_IPOIB_RECV_PKT_POOL, 1, NDIS_STATUS_RESOURCES );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("NdisAllocatePacketPool returned %08X\n", (UINT)NDIS_STATUS_RESOURCES) );\r
- return IB_INSUFFICIENT_RESOURCES;\r
- }\r
-/*\r
- NdisAllocateBufferPool( &ndis_status, &p_port->buf_mgr.h_buffer_pool,\r
- p_params->rq_depth );\r
- if( ndis_status != NDIS_STATUS_SUCCESS )\r
- {\r
- NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
- EVENT_IPOIB_RECV_BUF_POOL, 1, ndis_status );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("NdisAllocateBufferPool returned %08X\n", ndis_status) );\r
- return IB_INSUFFICIENT_RESOURCES;\r
- }\r
-*/\r
- /* Allocate the NET buffer list pool for send formatting. */\r
- pool_parameters.PoolTag = 'XTPI';\r
-\r
- p_port->buf_mgr.h_send_pkt_pool = NdisAllocateNetBufferListPool(\r
- p_port->p_adapter->h_adapter,\r
- &pool_parameters); \r
- if( !p_port->buf_mgr.h_send_pkt_pool)\r
- {\r
- NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
- EVENT_IPOIB_SEND_PKT_POOL, 1, NDIS_STATUS_RESOURCES );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("NdisAllocatePacketPool returned %08X\n", (UINT)NDIS_STATUS_RESOURCES) );\r
- return IB_INSUFFICIENT_RESOURCES;\r
- }\r
-/*\r
- NdisAllocateBufferPool( &ndis_status,\r
- &p_port->buf_mgr.h_send_buf_pool, 1 );\r
- if( ndis_status != NDIS_STATUS_SUCCESS )\r
- {\r
- NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
- EVENT_IPOIB_SEND_BUF_POOL, 1, ndis_status );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("NdisAllocateBufferPool returned %08X\n", ndis_status) );\r
- return IB_INSUFFICIENT_RESOURCES;\r
- }\r
-*/\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
- return IB_SUCCESS;\r
-}\r
-\r
-\r
-static void\r
-__buf_mgr_destroy(\r
- IN ipoib_port_t* const p_port )\r
-{\r
- IPOIB_ENTER(IPOIB_DBG_INIT );\r
-\r
- CL_ASSERT( p_port );\r
-\r
- /* Destroy the send packet and buffer pools. \r
- if( p_port->buf_mgr.h_send_buf_pool )\r
- NdisFreeBufferPool( p_port->buf_mgr.h_send_buf_pool );*/\r
- if( p_port->buf_mgr.h_send_pkt_pool )\r
- NdisFreeNetBufferListPool ( p_port->buf_mgr.h_send_pkt_pool );\r
-\r
- /* Destroy the receive packet and buffer pools. \r
- if( p_port->buf_mgr.h_buffer_pool )\r
- NdisFreeBufferPool( p_port->buf_mgr.h_buffer_pool );*/\r
- if( p_port->buf_mgr.h_packet_pool )\r
- NdisFreeNetBufferListPool ( p_port->buf_mgr.h_packet_pool );\r
-\r
- /* Free the receive and send descriptors. */\r
- cl_qpool_destroy( &p_port->buf_mgr.recv_pool );\r
-\r
- /* Free the lookaside list of scratch buffers. */\r
- NdisDeleteNPagedLookasideList( &p_port->buf_mgr.send_buf_list );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
-}\r
-\r
-\r
-static cl_status_t\r
-__recv_ctor(\r
- IN void* const p_object,\r
- IN void* context,\r
- OUT cl_pool_item_t** const pp_pool_item )\r
-{\r
- ipoib_recv_desc_t *p_desc;\r
- ipoib_port_t *p_port;\r
-\r
-#if IPOIB_INLINE_RECV\r
- uint32_t ds0_len;\r
-#endif\r
-\r
- IPOIB_ENTER( IPOIB_DBG_ALLOC );\r
-\r
- CL_ASSERT( p_object );\r
- CL_ASSERT( context );\r
-\r
- p_desc = (ipoib_recv_desc_t*)p_object;\r
- p_port = (ipoib_port_t*)context;\r
-\r
- /* Setup the work request. */\r
- p_desc->wr.ds_array = p_desc->local_ds;\r
- p_desc->wr.wr_id = (uintn_t)p_desc;\r
-\r
-#if IPOIB_INLINE_RECV\r
- /* Sanity check on the receive buffer layout */\r
- CL_ASSERT( (void*)&p_desc->buf.eth.pkt.type ==\r
- (void*)&p_desc->buf.ib.pkt.type );\r
- CL_ASSERT( sizeof(recv_buf_t) == sizeof(ipoib_pkt_t) + sizeof(ib_grh_t) );\r
-\r
- /* Setup the local data segment. */\r
- p_desc->local_ds[0].vaddr = cl_get_physaddr( &p_desc->buf );\r
- p_desc->local_ds[0].lkey = p_port->ib_mgr.lkey;\r
- ds0_len =\r
- PAGE_SIZE - ((uint32_t)p_desc->local_ds[0].vaddr & (PAGE_SIZE - 1));\r
- if( ds0_len >= sizeof(recv_buf_t) )\r
- {\r
- /* The whole buffer is within a page. */\r
- p_desc->local_ds[0].length = ds0_len;\r
- p_desc->wr.num_ds = 1;\r
- }\r
- else\r
- {\r
- /* The buffer crosses page boundaries. */\r
- p_desc->local_ds[0].length = ds0_len;\r
- p_desc->local_ds[1].vaddr = cl_get_physaddr( \r
- ((uint8_t*)&p_desc->buf) + ds0_len );\r
- p_desc->local_ds[1].lkey = p_port->ib_mgr.lkey;\r
- p_desc->local_ds[1].length = sizeof(recv_buf_t) - ds0_len;\r
- p_desc->wr.num_ds = 2;\r
- }\r
-#else /* IPOIB_INLINE_RECV */\r
- /* Allocate the receive buffer. */\r
- p_desc->p_buf = (recv_buf_t*)cl_zalloc( sizeof(recv_buf_t) );\r
- if( !p_desc->p_buf )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Failed to allocate receive buffer.\n") );\r
- return CL_INSUFFICIENT_MEMORY;\r
- }\r
-\r
- /* Sanity check on the receive buffer layout */\r
- CL_ASSERT( (void*)&p_desc->p_buf->eth.pkt.type ==\r
- (void*)&p_desc->p_buf->ib.pkt.type );\r
-\r
- /* Setup the local data segment. */\r
- p_desc->local_ds[0].vaddr = cl_get_physaddr( p_desc->p_buf );\r
- p_desc->local_ds[0].length = sizeof(ipoib_pkt_t) + sizeof(ib_grh_t);\r
- p_desc->local_ds[0].lkey = p_port->ib_mgr.lkey;\r
- p_desc->wr.num_ds = 1;\r
-#endif /* IPOIB_INLINE_RECV */\r
-\r
- *pp_pool_item = &p_desc->item;\r
-\r
- IPOIB_EXIT( IPOIB_DBG_ALLOC );\r
- return CL_SUCCESS;\r
-}\r
-\r
-\r
-#if !IPOIB_INLINE_RECV\r
-static void\r
-__recv_dtor(\r
- IN const cl_pool_item_t* const p_pool_item,\r
- IN void *context )\r
-{\r
- ipoib_recv_desc_t *p_desc;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_ALLOC );\r
-\r
- UNUSED_PARAM( context );\r
-\r
- p_desc = PARENT_STRUCT( p_pool_item, ipoib_recv_desc_t, item );\r
-\r
- if( p_desc->p_buf )\r
- cl_free( p_desc->p_buf );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_ALLOC );\r
-}\r
-#endif\r
-\r
-\r
-static inline ipoib_recv_desc_t*\r
-__buf_mgr_get_recv(\r
- IN ipoib_port_t* const p_port )\r
-{\r
- ipoib_recv_desc_t *p_desc;\r
- IPOIB_ENTER( IPOIB_DBG_RECV );\r
- p_desc = (ipoib_recv_desc_t*)cl_qpool_get( &p_port->buf_mgr.recv_pool );\r
- /* Reference the port object for the send. */\r
- if( p_desc )\r
- {\r
- ipoib_port_ref( p_port, ref_get_recv );\r
- CL_ASSERT( p_desc->wr.wr_id == (uintn_t)p_desc );\r
-#if IPOIB_INLINE_RECV\r
- CL_ASSERT( p_desc->local_ds[0].vaddr ==\r
- cl_get_physaddr( &p_desc->buf ) );\r
-#else /* IPOIB_INLINE_RECV */\r
- CL_ASSERT( p_desc->local_ds[0].vaddr ==\r
- cl_get_physaddr( p_desc->p_buf ) );\r
- CL_ASSERT( p_desc->local_ds[0].length ==\r
- (sizeof(ipoib_pkt_t) + sizeof(ib_grh_t)) );\r
-#endif /* IPOIB_INLINE_RECV */\r
- CL_ASSERT( p_desc->local_ds[0].lkey == p_port->ib_mgr.lkey );\r
- }\r
- IPOIB_EXIT( IPOIB_DBG_RECV );\r
- return p_desc;\r
-}\r
-\r
-\r
-//NDIS60\r
-static inline void\r
-__buf_mgr_put_recv(\r
- IN ipoib_port_t* const p_port,\r
- IN ipoib_recv_desc_t* const p_desc,\r
- IN NET_BUFFER_LIST* const p_net_buffer_list OPTIONAL )\r
-{\r
- NET_BUFFER *p_buf = NULL;\r
- MDL *p_mdl = NULL;\r
- IPOIB_ENTER(IPOIB_DBG_RECV );\r
-\r
- if( p_net_buffer_list )\r
- {\r
- NET_BUFFER_LIST_NEXT_NBL(p_net_buffer_list) = NULL;\r
- p_buf = NET_BUFFER_LIST_FIRST_NB(p_net_buffer_list);\r
- CL_ASSERT( p_buf );\r
- p_mdl = NET_BUFFER_FIRST_MDL(p_buf);\r
- CL_ASSERT( p_mdl );\r
- NdisFreeMdl(p_mdl);\r
- NdisFreeNetBufferList(p_net_buffer_list);\r
- }\r
-\r
- /* Return the descriptor to its pools. */\r
- cl_qpool_put( &p_port->buf_mgr.recv_pool, &p_desc->item );\r
-\r
- /*\r
- * Dereference the port object since the receive is no longer outstanding.\r
- */\r
- ipoib_port_deref( p_port, ref_get_recv );\r
- IPOIB_EXIT( IPOIB_DBG_RECV );\r
-}\r
-\r
-\r
-static inline void\r
-__buf_mgr_put_recv_list(\r
- IN ipoib_port_t* const p_port,\r
- IN cl_qlist_t* const p_list )\r
-{\r
- //IPOIB_ENTER( IPOIB_DBG_RECV );\r
- cl_qpool_put_list( &p_port->buf_mgr.recv_pool, p_list );\r
- //IPOIB_EXIT( IPOIB_DBG_RECV );\r
-}\r
-\r
-\r
-static inline NET_BUFFER_LIST*\r
-__buf_mgr_get_ndis_pkt(\r
- IN ipoib_port_t* const p_port,\r
- IN ipoib_recv_desc_t* const p_desc )\r
-{\r
- NET_BUFFER_LIST *p_net_buffer_list;\r
- MDL *p_mdl;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_RECV );\r
-\r
- p_mdl = NdisAllocateMdl(p_port->p_adapter->h_adapter,\r
- &p_desc->buf.eth.pkt,\r
- p_desc->len );\r
- if( !p_mdl )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Failed to allocate MDL\n") );\r
- return NULL;\r
- }\r
-\r
- p_net_buffer_list = NdisAllocateNetBufferAndNetBufferList(\r
- p_port->buf_mgr.h_packet_pool,\r
- 0,\r
- 0,\r
- p_mdl,\r
- 0,\r
- 0);\r
-\r
- if( !p_net_buffer_list )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Failed to allocate NET_BUFFER_LIST\n") );\r
- NdisFreeMdl(p_mdl);\r
- return NULL;\r
- }\r
-\r
- NET_BUFFER_LIST_NEXT_NBL(p_net_buffer_list) = NULL;\r
- IPOIB_PORT_FROM_PACKET( p_net_buffer_list ) = p_port;\r
- IPOIB_RECV_FROM_PACKET( p_net_buffer_list ) = p_desc;\r
- p_net_buffer_list->SourceHandle = p_port->p_adapter->h_adapter;\r
-\r
- IPOIB_EXIT( IPOIB_DBG_RECV );\r
- return p_net_buffer_list;\r
-}\r
-\r
-\r
-/******************************************************************************\r
-*\r
-* Receive manager implementation.\r
-*\r
-******************************************************************************/\r
-static void\r
-__recv_mgr_construct(\r
- IN ipoib_port_t* const p_port )\r
-{\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-\r
- cl_qlist_init( &p_port->recv_mgr.done_list );\r
-\r
- p_port->recv_mgr.recv_pkt_array = NULL;\r
-\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
-}\r
-\r
-\r
-static ib_api_status_t\r
-__recv_mgr_init(\r
- IN ipoib_port_t* const p_port )\r
-{\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-\r
- /* Allocate the NDIS_PACKET pointer array for indicating receives. */\r
- p_port->recv_mgr.recv_pkt_array = cl_malloc(\r
- sizeof(NET_BUFFER_LIST*) * p_port->p_adapter->params.rq_depth );\r
- if( !p_port->recv_mgr.recv_pkt_array )\r
- {\r
- NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
- EVENT_IPOIB_RECV_PKT_ARRAY, 0 );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("cl_malloc for PNDIS_PACKET array failed.\n") );\r
- return IB_INSUFFICIENT_MEMORY;\r
- }\r
-\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
- return IB_SUCCESS;\r
-}\r
-\r
-\r
-static void\r
-__recv_mgr_destroy(\r
- IN ipoib_port_t* const p_port )\r
-{\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-\r
- CL_ASSERT( cl_is_qlist_empty( &p_port->recv_mgr.done_list ) );\r
- CL_ASSERT( !p_port->recv_mgr.depth );\r
-\r
- if( p_port->recv_mgr.recv_pkt_array )\r
- cl_free( p_port->recv_mgr.recv_pkt_array );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
-}\r
-\r
-\r
-/*\r
- * Posts receive buffers to the receive queue and returns the number\r
- * of receives needed to bring the RQ to its low water mark. Note\r
- * that the value is signed, and can go negative. All tests must\r
- * be for > 0.\r
- */\r
-static int32_t\r
-__recv_mgr_repost(\r
- IN ipoib_port_t* const p_port )\r
-{\r
- ipoib_recv_desc_t *p_head = NULL, *p_tail = NULL, *p_next;\r
- ib_api_status_t status;\r
- ib_recv_wr_t *p_failed;\r
- PERF_DECLARE( GetRecv );\r
- PERF_DECLARE( PostRecv );\r
-\r
- IPOIB_ENTER( IPOIB_DBG_RECV );\r
-\r
- CL_ASSERT( p_port );\r
- cl_obj_lock( &p_port->obj );\r
- if( p_port->state != IB_QPS_RTS )\r
- {\r
- cl_obj_unlock( &p_port->obj );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_RECV,\r
- ("Port in invalid state. Not reposting.\n") );\r
- return 0;\r
- }\r
- ipoib_port_ref( p_port, ref_repost );\r
- cl_obj_unlock( &p_port->obj );\r
-\r
- while( p_port->recv_mgr.depth < p_port->p_adapter->params.rq_depth )\r
- {\r
- /* Pull receives out of the pool and chain them up. */\r
- cl_perf_start( GetRecv );\r
- p_next = __buf_mgr_get_recv( p_port );\r
- cl_perf_stop( &p_port->p_adapter->perf, GetRecv );\r
- if( !p_next )\r
- {\r
- IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_RECV,\r
- ("Out of receive descriptors! recv queue depth 0x%x\n",p_port->recv_mgr.depth) );\r
- break;\r
- }\r
-\r
- if( !p_tail )\r
- {\r
- p_tail = p_next;\r
- p_next->wr.p_next = NULL;\r
- }\r
- else\r
- {\r
- p_next->wr.p_next = &p_head->wr;\r
- }\r
-\r
- p_head = p_next;\r
-\r
- p_port->recv_mgr.depth++;\r
- }\r
-\r
- if( p_head )\r
- {\r
- cl_perf_start( PostRecv );\r
- status = p_port->p_adapter->p_ifc->post_recv(\r
- p_port->ib_mgr.h_qp, &p_head->wr, &p_failed );\r
- cl_perf_stop( &p_port->p_adapter->perf, PostRecv );\r
-\r
- if( status != IB_SUCCESS )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ip_post_recv returned %s\n", \r
- p_port->p_adapter->p_ifc->get_err_str( status )) );\r
- /* return the descriptors to the pool */\r
- while( p_failed )\r
- {\r
- p_head = PARENT_STRUCT( p_failed, ipoib_recv_desc_t, wr );\r
- p_failed = p_failed->p_next;\r
-\r
- __buf_mgr_put_recv( p_port, p_head, NULL );\r
- p_port->recv_mgr.depth--;\r
- }\r
- }\r
- }\r
-\r
- ipoib_port_deref( p_port, ref_repost );\r
- IPOIB_EXIT( IPOIB_DBG_RECV );\r
- return p_port->p_adapter->params.rq_low_watermark - p_port->recv_mgr.depth;\r
-}\r
-\r
-void\r
-ipoib_return_net_buffer_list(\r
- IN NDIS_HANDLE adapter_context,\r
- IN NET_BUFFER_LIST *p_net_buffer_lists,\r
- IN ULONG return_flags)\r
-{\r
-// cl_list_item_t *p_item;\r
- ipoib_port_t *p_port;\r
- ipoib_recv_desc_t *p_desc;\r
- NET_BUFFER_LIST *cur_net_buffer_list,*next_net_buffer_list;\r
-// ib_api_status_t status = IB_NOT_DONE;\r
-// int32_t shortage;\r
-// ULONG complete_flags = 0;\r
- PERF_DECLARE( ReturnPacket );\r
- PERF_DECLARE( ReturnPutRecv );\r
- PERF_DECLARE( ReturnRepostRecv );\r
- PERF_DECLARE( ReturnPreparePkt );\r
- PERF_DECLARE( ReturnNdisIndicate );\r
-\r
- IPOIB_ENTER( IPOIB_DBG_RECV );\r
-\r
- UNUSED_PARAM( return_flags );\r
-\r
- p_port = ((ipoib_adapter_t*)adapter_context)->p_port;\r
- CL_ASSERT( p_net_buffer_lists );\r
-\r
- cl_perf_start( ReturnPacket );\r
- cl_spinlock_acquire( &p_port->recv_lock );\r
- for (cur_net_buffer_list = p_net_buffer_lists;\r
- cur_net_buffer_list != NULL;\r
- cur_net_buffer_list = next_net_buffer_list)\r
- {\r
- next_net_buffer_list = NET_BUFFER_LIST_NEXT_NBL(cur_net_buffer_list);\r
-\r
- /* Get the port and descriptor from the packet. */\r
- CL_ASSERT(p_port == IPOIB_PORT_FROM_PACKET( cur_net_buffer_list ));\r
- p_desc = IPOIB_RECV_FROM_PACKET( cur_net_buffer_list );\r
-\r
- \r
- //TODO: NDIS60, rewrite this block\r
- /* Get descriptor from the packet. */\r
-#if 0\r
- if( p_desc->type == PKT_TYPE_CM_UCAST )\r
- {\r
- NDIS_BUFFER *p_buf;\r
-\r
- /* Unchain the NDIS buffer. */\r
- NdisUnchainBufferAtFront( p_packet, &p_buf );\r
- CL_ASSERT( p_buf );\r
- /* Return the NDIS packet and NDIS buffer to their pools. */\r
- NdisDprFreePacketNonInterlocked( p_packet );\r
- NdisFreeBuffer( p_buf );\r
-\r
- endpt_cm_buf_mgr_put_recv( &p_port->cm_buf_mgr, (ipoib_cm_desc_t *)p_desc );\r
- status = endpt_cm_post_recv( p_port );\r
- if( status != IB_SUCCESS )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Post Recv QP failed\n" ) );\r
- }\r
- cl_spinlock_release( &p_port->recv_lock );\r
- return;\r
- }\r
-#endif\r
-\r
- cl_perf_start( ReturnPutRecv );\r
- __buf_mgr_put_recv( p_port, p_desc, cur_net_buffer_list );\r
- cl_perf_stop( &p_port->p_adapter->perf, ReturnPutRecv );\r
- }\r
-#if 0 \r
- /* Repost buffers. */\r
- cl_perf_start( ReturnRepostRecv );\r
- shortage = __recv_mgr_repost( p_port );\r
- cl_perf_stop( &p_port->p_adapter->perf, ReturnRepostRecv );\r
-\r
- for( p_item = cl_qlist_remove_head( &p_port->recv_mgr.done_list );\r
- p_item != cl_qlist_end( &p_port->recv_mgr.done_list );\r
- p_item = cl_qlist_remove_head( &p_port->recv_mgr.done_list ) )\r
- {\r
- p_desc = (ipoib_recv_desc_t*)p_item;\r
-\r
- cl_perf_start( ReturnPreparePkt );\r
- status = __recv_mgr_prepare_pkt( p_port, p_desc, &cur_net_buffer_list );\r
- cl_perf_stop( &p_port->p_adapter->perf, ReturnPreparePkt );\r
- if( status == IB_SUCCESS )\r
- {\r
- if( shortage > 0 )\r
- NET_BUFFER_LIST_STATUS( cur_net_buffer_list) = NDIS_STATUS_RESOURCES;\r
- else\r
- NET_BUFFER_LIST_STATUS( cur_net_buffer_list) = NDIS_STATUS_SUCCESS;\r
-\r
- cl_spinlock_release( &p_port->recv_lock );\r
- NET_BUFFER_LIST_NEXT_NBL(cur_net_buffer_list) = NULL;\r
- cl_perf_start( ReturnNdisIndicate );\r
- NdisMRecvIndicate( p_port->p_adapter->h_adapter,\r
- cur_net_buffer_list, complete_flags );\r
- cl_perf_stop( &p_port->p_adapter->perf, ReturnNdisIndicate );\r
- cl_spinlock_acquire( &p_port->recv_lock );\r
-\r
- if( shortage > 0 )\r
- {\r
- cl_perf_start( ReturnPutRecv );\r
- __buf_mgr_put_recv( p_port, p_desc, cur_net_buffer_list );\r
- cl_perf_stop( &p_port->p_adapter->perf, ReturnPutRecv );\r
-\r
- /* Repost buffers. */\r
- cl_perf_start( ReturnRepostRecv );\r
- shortage = __recv_mgr_repost( p_port );\r
- cl_perf_stop( &p_port->p_adapter->perf, ReturnRepostRecv );\r
- }\r
- }\r
- else if( status != IB_NOT_DONE )\r
- {\r
- IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_RECV,\r
- ("__recv_mgr_prepare_pkt returned %s\n",\r
- p_port->p_adapter->p_ifc->get_err_str( status )) );\r
- /* Return the item to the head of the list. */\r
- cl_qlist_insert_head( &p_port->recv_mgr.done_list, p_item );\r
- break;\r
- }\r
- }\r
- #endif\r
- cl_spinlock_release( &p_port->recv_lock );\r
- cl_perf_stop( &p_port->p_adapter->perf, ReturnPacket );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_RECV );\r
-}\r
-\r
-static void __recv_cb_dpc(KDPC *p_gc_dpc,void *context,void * s_arg1 , void * s_arg2)\r
-{\r
-\r
- ipoib_port_t *p_port = context;\r
-\r
- UNREFERENCED_PARAMETER(p_gc_dpc);\r
- UNREFERENCED_PARAMETER(s_arg1);\r
- UNREFERENCED_PARAMETER(s_arg2);\r
-\r
-\r
- __recv_cb(NULL, p_port);\r
- ipoib_port_deref( p_port, ref_recv_cb );\r
-\r
-\r
-}\r
-\r
-\r
-static void\r
-__recv_cb(\r
- IN const ib_cq_handle_t h_cq,\r
- IN void *cq_context )\r
-{\r
- ipoib_port_t *p_port;\r
- ib_api_status_t status;\r
- ib_wc_t wc[MAX_RECV_WC], *p_free, *p_wc;\r
- int32_t pkt_cnt, recv_cnt = 0, shortage, discarded;\r
- cl_qlist_t done_list, bad_list;\r
- size_t i;\r
- ULONG recv_complete_flags = 0;\r
-\r
- PERF_DECLARE( RecvCompBundle );\r
- PERF_DECLARE( RecvCb );\r
- PERF_DECLARE( PollRecv );\r
- PERF_DECLARE( RepostRecv );\r
- PERF_DECLARE( FilterRecv );\r
- PERF_DECLARE( BuildPktArray );\r
- PERF_DECLARE( RecvNdisIndicate );\r
- PERF_DECLARE( RearmRecv );\r
- PERF_DECLARE( PutRecvList );\r
-\r
- IPOIB_ENTER( IPOIB_DBG_RECV );\r
-\r
- cl_perf_clr( RecvCompBundle );\r
-\r
- cl_perf_start( RecvCb );\r
-//return ;\r
- UNUSED_PARAM( h_cq );\r
-\r
- NDIS_SET_SEND_COMPLETE_FLAG(recv_complete_flags, NDIS_RECEIVE_FLAGS_DISPATCH_LEVEL );\r
-\r
- p_port = (ipoib_port_t*)cq_context;\r
-\r
- cl_qlist_init( &done_list );\r
- cl_qlist_init( &bad_list );\r
-\r
- ipoib_port_ref( p_port, ref_recv_cb );\r
- for( i = 0; i < MAX_RECV_WC; i++ )\r
- wc[i].p_next = &wc[i + 1];\r
- wc[MAX_RECV_WC - 1].p_next = NULL;\r
-\r
- /*\r
- * We'll be accessing the endpoint map so take a reference\r
- * on it to prevent modifications.\r
- */\r
- cl_obj_lock( &p_port->obj );\r
- cl_atomic_inc( &p_port->endpt_rdr );\r
- cl_obj_unlock( &p_port->obj );\r
-\r
- do\r
- {\r
- /* If we get here, then the list of WCs is intact. */\r
- p_free = wc;\r
-\r
- cl_perf_start( PollRecv );\r
- status = p_port->p_adapter->p_ifc->poll_cq(\r
- p_port->ib_mgr.h_recv_cq, &p_free, &p_wc );\r
- cl_perf_stop( &p_port->p_adapter->perf, PollRecv );\r
- CL_ASSERT( status == IB_SUCCESS || status == IB_NOT_FOUND );\r
-\r
- /* Look at the payload now and filter ARP and DHCP packets. */\r
- cl_perf_start( FilterRecv );\r
- recv_cnt += __recv_mgr_filter( p_port, p_wc, &done_list, &bad_list );\r
- cl_perf_stop( &p_port->p_adapter->perf, FilterRecv );\r
-\r
- } while( (!p_free) && (recv_cnt < 128));\r
-\r
- /* We're done looking at the endpoint map, release the reference. */\r
- cl_atomic_dec( &p_port->endpt_rdr );\r
-\r
- cl_perf_log( &p_port->p_adapter->perf, RecvCompBundle, recv_cnt );\r
-\r
- cl_spinlock_acquire( &p_port->recv_lock );\r
-\r
- /* Update our posted depth. */\r
- p_port->recv_mgr.depth -= recv_cnt;\r
-\r
- /* Return any discarded receives to the pool */\r
- cl_perf_start( PutRecvList );\r
- __buf_mgr_put_recv_list( p_port, &bad_list );\r
- cl_perf_stop( &p_port->p_adapter->perf, PutRecvList );\r
-\r
- do\r
- {\r
- int32_t cnt;\r
- /* Repost ASAP so we don't starve the RQ. */\r
- cl_perf_start( RepostRecv );\r
- shortage = __recv_mgr_repost( p_port );\r
- cl_perf_stop( &p_port->p_adapter->perf, RepostRecv );\r
-\r
- cl_perf_start( BuildPktArray );\r
- /* Notify NDIS of any and all possible receive buffers. */\r
- pkt_cnt = __recv_mgr_build_pkt_array(\r
- p_port, shortage, &done_list, &discarded );\r
- cl_perf_stop( &p_port->p_adapter->perf, BuildPktArray );\r
-\r
- /* Only indicate receives if we actually had any. */\r
- if( discarded && shortage > 0 )\r
- {\r
- /* We may have thrown away packets, and have a shortage */\r
- cl_perf_start( RepostRecv );\r
- __recv_mgr_repost( p_port );\r
- cl_perf_stop( &p_port->p_adapter->perf, RepostRecv );\r
- }\r
-\r
- if( !pkt_cnt )\r
- break;\r
-\r
- cl_spinlock_release( &p_port->recv_lock );\r
- for( cnt = 0; cnt < pkt_cnt -1; cnt++)\r
- {\r
- NET_BUFFER_LIST_NEXT_NBL(p_port->recv_mgr.recv_pkt_array[cnt]) = \r
- p_port->recv_mgr.recv_pkt_array[cnt + 1];\r
- }\r
- cl_perf_start( RecvNdisIndicate );\r
-#ifndef NDIS_DEFAULT_PORT_NUMBER\r
-#define NDIS_DEFAULT_PORT_NUMBER 0\r
-#endif\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Indicate NDIS with %d received NBs\n",\r
- pkt_cnt) );\r
- NdisMIndicateReceiveNetBufferLists(\r
- p_port->p_adapter->h_adapter,\r
- p_port->recv_mgr.recv_pkt_array[0],\r
- NDIS_DEFAULT_PORT_NUMBER,\r
- pkt_cnt,\r
- recv_complete_flags);\r
-\r
- cl_perf_stop( &p_port->p_adapter->perf, RecvNdisIndicate );\r
-\r
- /*\r
- * Cap the number of receives to put back to what we just indicated\r
- * with NDIS_STATUS_RESOURCES.\r
- */\r
- if( shortage > 0 )\r
- {\r
- if( pkt_cnt < shortage )\r
- shortage = pkt_cnt;\r
-\r
- /* Return all but the last packet to the pool. */\r
- cl_spinlock_acquire( &p_port->recv_lock );\r
- while( shortage-- > 1 )\r
- {\r
- __buf_mgr_put_recv( p_port,\r
- (ipoib_recv_desc_t *)IPOIB_RECV_FROM_PACKET( p_port->recv_mgr.recv_pkt_array[shortage] ),\r
- p_port->recv_mgr.recv_pkt_array[shortage] );\r
- }\r
- cl_spinlock_release( &p_port->recv_lock );\r
-\r
- /*\r
- * Return the last packet as if NDIS returned it, so that we repost\r
- * and report any other pending receives.\r
- */\r
- ipoib_return_net_buffer_list( NULL, p_port->recv_mgr.recv_pkt_array[0],recv_complete_flags );\r
- }\r
- cl_spinlock_acquire( &p_port->recv_lock );\r
-\r
- } while( pkt_cnt );\r
- cl_spinlock_release( &p_port->recv_lock );\r
-\r
- if (p_free ) {\r
- /*\r
- * Rearm after filtering to prevent contention on the enpoint maps\r
- * and eliminate the possibility of having a call to\r
- * __endpt_mgr_insert find a duplicate.\r
- */\r
- cl_perf_start( RearmRecv );\r
- status = p_port->p_adapter->p_ifc->rearm_cq(\r
- p_port->ib_mgr.h_recv_cq, FALSE );\r
- cl_perf_stop( &p_port->p_adapter->perf, RearmRecv );\r
- CL_ASSERT( status == IB_SUCCESS );\r
-\r
- ipoib_port_deref( p_port, ref_recv_cb );\r
- } else {\r
- // Please note the reference is still up\r
- KeInsertQueueDpc(&p_port->recv_dpc, NULL, NULL);\r
- }\r
-\r
- cl_perf_stop( &p_port->p_adapter->perf, RecvCb );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_RECV );\r
-}\r
-\r
-\r
-static void\r
-__recv_get_endpts(\r
- IN ipoib_port_t* const p_port,\r
- IN ipoib_recv_desc_t* const p_desc,\r
- IN ib_wc_t* const p_wc,\r
- OUT ipoib_endpt_t** const pp_src,\r
- OUT ipoib_endpt_t** const pp_dst )\r
-{\r
- ib_api_status_t status;\r
- mac_addr_t mac;\r
- PERF_DECLARE( GetEndptByGid );\r
- PERF_DECLARE( GetEndptByLid );\r
- PERF_DECLARE( EndptInsert );\r
-\r
- IPOIB_ENTER( IPOIB_DBG_RECV );\r
-\r
- /* Setup our shortcut pointers based on whether GRH is valid. */\r
- if( p_wc->recv.ud.recv_opt & IB_RECV_OPT_GRH_VALID )\r
- {\r
- /* Lookup the source endpoints based on GID. */\r
- cl_perf_start( GetEndptByGid );\r
- *pp_src =\r
-#if IPOIB_INLINE_RECV\r
- __endpt_mgr_get_by_gid( p_port, &p_desc->buf.ib.grh.src_gid );\r
-#else /* IPOIB_INLINE_RECV */\r
- __endpt_mgr_get_by_gid( p_port, &p_desc->p_buf->ib.grh.src_gid );\r
-#endif /* IPOIB_INLINE_RECV */\r
- cl_perf_stop( &p_port->p_adapter->perf, GetEndptByGid );\r
-\r
- /*\r
- * Lookup the destination endpoint based on GID.\r
- * This is used along with the packet filter to determine\r
- * whether to report this to NDIS.\r
- */\r
- cl_perf_start( GetEndptByGid );\r
- *pp_dst =\r
-#if IPOIB_INLINE_RECV\r
- __endpt_mgr_get_by_gid( p_port, &p_desc->buf.ib.grh.dest_gid );\r
-#else /* IPOIB_INLINE_RECV */\r
- __endpt_mgr_get_by_gid( p_port, &p_desc->p_buf->ib.grh.dest_gid );\r
-#endif /* IPOIB_INLINE_RECV */\r
- cl_perf_stop( &p_port->p_adapter->perf, GetEndptByGid );\r
-\r
- /*\r
- * Create the source endpoint if it does not exist. Note that we\r
- * can only do this for globally routed traffic since we need the\r
- * information from the GRH to generate the MAC.\r
- */\r
- if( !*pp_src )\r
- {\r
- status = ipoib_mac_from_guid(\r
-#if IPOIB_INLINE_RECV\r
- p_desc->buf.ib.grh.src_gid.unicast.interface_id, p_port->p_adapter->params.guid_mask, &mac );\r
-#else /* IPOIB_INLINE_RECV */\r
- p_desc->p_buf->ib.grh.src_gid.unicast.interface_id, p_port->p_adapter->params.guid_mask, &mac );\r
-#endif /* IPOIB_INLINE_RECV */\r
- if( status != IB_SUCCESS )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ipoib_mac_from_guid returned %s\n",\r
- p_port->p_adapter->p_ifc->get_err_str( status )) );\r
- return;\r
- }\r
-\r
- /* Create the endpoint. */\r
-#if IPOIB_INLINE_RECV\r
- *pp_src = ipoib_endpt_create( &p_desc->buf.ib.grh.src_gid,\r
-#else /* IPOIB_INLINE_RECV */\r
- *pp_src = ipoib_endpt_create( &p_desc->p_buf->ib.grh.src_gid,\r
-#endif /* IPOIB_INLINE_RECV */\r
- p_wc->recv.ud.remote_lid, p_wc->recv.ud.remote_qp );\r
- if( !*pp_src )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ipoib_endpt_create failed\n") );\r
- return;\r
- }\r
- cl_perf_start( EndptInsert );\r
- cl_obj_lock( &p_port->obj );\r
- status = __endpt_mgr_insert( p_port, mac, *pp_src );\r
- if( status != IB_SUCCESS )\r
- {\r
- cl_obj_unlock( &p_port->obj );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("__endpt_mgr_insert returned %s\n",\r
- p_port->p_adapter->p_ifc->get_err_str( status )) );\r
- *pp_src = NULL;\r
- return;\r
- }\r
- cl_obj_unlock( &p_port->obj );\r
- cl_perf_stop( &p_port->p_adapter->perf, EndptInsert );\r
- }\r
- }\r
- else\r
- {\r
- /*\r
- * Lookup the remote endpoint based on LID. Note that only\r
- * unicast traffic can be LID routed.\r
- */\r
- cl_perf_start( GetEndptByLid );\r
- *pp_src = __endpt_mgr_get_by_lid( p_port, p_wc->recv.ud.remote_lid );\r
- cl_perf_stop( &p_port->p_adapter->perf, GetEndptByLid );\r
- *pp_dst = p_port->p_local_endpt;\r
- CL_ASSERT( *pp_dst );\r
- }\r
-\r
- if( *pp_src && !ipoib_is_voltaire_router_gid( &(*pp_src)->dgid ) &&\r
- (*pp_src)->qpn != p_wc->recv.ud.remote_qp )\r
- {\r
- /* Update the QPN for the endpoint. */\r
- IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_RECV,\r
- ("Updating QPN for MAC: %02X-%02X-%02X-%02X-%02X-%02X\n",\r
- (*pp_src )->mac.addr[0], (*pp_src )->mac.addr[1],\r
- (*pp_src )->mac.addr[2], (*pp_src )->mac.addr[3],\r
- (*pp_src )->mac.addr[4], (*pp_src )->mac.addr[5]) );\r
-// (*pp_src)->qpn = p_wc->recv.ud.remote_qp;\r
- }\r
-\r
- if( *pp_src && *pp_dst )\r
- {\r
- IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_RECV,\r
- ("Recv:\n"\r
- "\tsrc MAC: %02X-%02X-%02X-%02X-%02X-%02X\n"\r
- "\tdst MAC: %02X-%02X-%02X-%02X-%02X-%02X\n",\r
- (*pp_src )->mac.addr[0], (*pp_src )->mac.addr[1],\r
- (*pp_src )->mac.addr[2], (*pp_src )->mac.addr[3],\r
- (*pp_src )->mac.addr[4], (*pp_src )->mac.addr[5],\r
- (*pp_dst )->mac.addr[0], (*pp_dst )->mac.addr[1],\r
- (*pp_dst )->mac.addr[2], (*pp_dst )->mac.addr[3],\r
- (*pp_dst )->mac.addr[4], (*pp_dst )->mac.addr[5]) );\r
- }\r
-\r
- IPOIB_EXIT( IPOIB_DBG_RECV );\r
-}\r
-\r
-\r
-static int32_t\r
-__recv_mgr_filter(\r
- IN ipoib_port_t* const p_port,\r
- IN ib_wc_t* const p_done_wc_list,\r
- OUT cl_qlist_t* const p_done_list,\r
- OUT cl_qlist_t* const p_bad_list )\r
-{\r
- ipoib_recv_desc_t *p_desc;\r
- ib_wc_t *p_wc;\r
- ipoib_pkt_t *p_ipoib;\r
- eth_pkt_t *p_eth;\r
- ipoib_endpt_t *p_src, *p_dst;\r
- ib_api_status_t status;\r
- uint32_t len;\r
- int32_t recv_cnt = 0;\r
- PERF_DECLARE( GetRecvEndpts );\r
- PERF_DECLARE( RecvGen );\r
- PERF_DECLARE( RecvTcp );\r
- PERF_DECLARE( RecvUdp );\r
- PERF_DECLARE( RecvDhcp );\r
- PERF_DECLARE( RecvArp );\r
-\r
- IPOIB_ENTER( IPOIB_DBG_RECV );\r
-\r
- for( p_wc = p_done_wc_list; p_wc; p_wc = p_wc->p_next )\r
- {\r
- CL_ASSERT( p_wc->status != IB_WCS_SUCCESS || p_wc->wc_type == IB_WC_RECV );\r
- p_desc = (ipoib_recv_desc_t*)(uintn_t)p_wc->wr_id;\r
- recv_cnt++;\r
-\r
- if( p_wc->status != IB_WCS_SUCCESS )\r
- {\r
- if( p_wc->status != IB_WCS_WR_FLUSHED_ERR )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Failed completion %s (vendor specific %#x)\n",\r
- p_port->p_adapter->p_ifc->get_wc_status_str( p_wc->status ),\r
- (int)p_wc->vendor_specific) );\r
- ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_ERROR, 0, 0 );\r
- }\r
- else\r
- {\r
- IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_RECV,\r
- ("Flushed completion %s\n",\r
- p_port->p_adapter->p_ifc->get_wc_status_str( p_wc->status )) );\r
- ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_DROPPED, 0, 0 );\r
- }\r
- cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item );\r
- /* Dereference the port object on behalf of the failed receive. */\r
- ipoib_port_deref( p_port, ref_failed_recv_wc );\r
- continue;\r
- }\r
-\r
- len = p_wc->length - sizeof(ib_grh_t);\r
-\r
- if( len < sizeof(ipoib_hdr_t) )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Received ETH packet < min size\n") );\r
- ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_ERROR, 0, 0 );\r
- cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item );\r
- ipoib_port_deref( p_port, ref_recv_inv_len );\r
- continue;\r
- }\r
-\r
- if((len - sizeof(ipoib_hdr_t)) > p_port->p_adapter->params.payload_mtu)\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Received ETH packet len %d > payload MTU (%d)\n",\r
- (len - sizeof(ipoib_hdr_t)),\r
- p_port->p_adapter->params.payload_mtu) );\r
- ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_ERROR, 0, 0 );\r
- cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item );\r
- ipoib_port_deref( p_port, ref_recv_inv_len );\r
- continue;\r
- \r
- }\r
- /* Successful completion. Get the receive information. */\r
- p_desc->ndis_csum.Value = ( ( p_wc->recv.ud.recv_opt & IB_RECV_OPT_CSUM_MASK ) >> 8 );\r
- p_desc->len = len + 14 - 4 ;\r
- cl_perf_start( GetRecvEndpts );\r
- __recv_get_endpts( p_port, p_desc, p_wc, &p_src, &p_dst );\r
- cl_perf_stop( &p_port->p_adapter->perf, GetRecvEndpts );\r
-\r
-#if IPOIB_INLINE_RECV\r
- p_ipoib = &p_desc->buf.ib.pkt;\r
- p_eth = &p_desc->buf.eth.pkt;\r
-#else /* IPOIB_INLINE_RECV */\r
- p_ipoib = &p_desc->p_buf->ib.pkt;\r
- p_eth = &p_desc->p_buf->eth.pkt;\r
-#endif /*IPOIB_INLINE_RECV */\r
-\r
- if( p_src )\r
- {\r
- /* Don't report loopback traffic - we requested SW loopback. */\r
- if( !cl_memcmp( &p_port->p_adapter->params.conf_mac,\r
- &p_src->mac, sizeof(p_port->p_adapter->params.conf_mac) ) )\r
- {\r
- /*\r
- * "This is not the packet you're looking for" - don't update\r
- * receive statistics, the packet never happened.\r
- */\r
- cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item );\r
- /* Dereference the port object on behalf of the failed recv. */\r
- ipoib_port_deref( p_port, ref_recv_loopback );\r
- continue;\r
- }\r
- }\r
-\r
- switch( p_ipoib->hdr.type )\r
- {\r
- case ETH_PROT_TYPE_IP:\r
- if( len < (sizeof(ipoib_hdr_t) + sizeof(ip_hdr_t)) )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Received IP packet < min size\n") );\r
- status = IB_INVALID_SETTING;\r
- break;\r
- }\r
-\r
- if( p_ipoib->type.ip.hdr.offset ||\r
- p_ipoib->type.ip.hdr.prot != IP_PROT_UDP )\r
- {\r
- /* Unfiltered. Setup the ethernet header and report. */\r
- cl_perf_start( RecvTcp );\r
- status = __recv_gen( p_ipoib, p_eth, p_src, p_dst );\r
- cl_perf_stop( &p_port->p_adapter->perf, RecvTcp );\r
- break;\r
- }\r
-\r
- /* First packet of a UDP transfer. */\r
- if( len <\r
- (sizeof(ipoib_hdr_t) + sizeof(ip_hdr_t) + sizeof(udp_hdr_t)) )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Received UDP packet < min size\n") );\r
- status = IB_INVALID_SETTING;\r
- break;\r
- }\r
-\r
- /* Check if DHCP conversion is required. */\r
- if( (p_ipoib->type.ip.prot.udp.hdr.dst_port == DHCP_PORT_SERVER &&\r
- p_ipoib->type.ip.prot.udp.hdr.src_port == DHCP_PORT_CLIENT) ||\r
- (p_ipoib->type.ip.prot.udp.hdr.dst_port == DHCP_PORT_CLIENT &&\r
- p_ipoib->type.ip.prot.udp.hdr.src_port == DHCP_PORT_SERVER) )\r
- {\r
- if( len < (sizeof(ipoib_hdr_t) + sizeof(ip_hdr_t) +\r
- sizeof(udp_hdr_t) + DHCP_MIN_SIZE) )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Received DHCP < min size\n") );\r
- status = IB_INVALID_SETTING;\r
- break;\r
- }\r
- if ((p_ipoib->type.ip.hdr.ver_hl & 0x0f) != 5 ) {\r
- // If there are IP options in this message, we are in trouble in any case\r
- status = IB_INVALID_SETTING;\r
- break; \r
- }\r
- /* UDP packet with BOOTP ports in src/dst port numbers. */\r
- cl_perf_start( RecvDhcp );\r
- status = __recv_dhcp( p_port, p_ipoib, p_eth, p_src, p_dst );\r
- cl_perf_stop( &p_port->p_adapter->perf, RecvDhcp );\r
- }\r
- else\r
- {\r
- /* Unfiltered. Setup the ethernet header and report. */\r
- cl_perf_start( RecvUdp );\r
- status = __recv_gen( p_ipoib, p_eth, p_src, p_dst );\r
- cl_perf_stop( &p_port->p_adapter->perf, RecvUdp );\r
- }\r
- break;\r
-\r
- case ETH_PROT_TYPE_ARP:\r
- if( len < (sizeof(ipoib_hdr_t) + sizeof(ipoib_arp_pkt_t)) )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Received ARP < min size\n") );\r
- status = IB_INVALID_SETTING;\r
- break;\r
- }\r
- cl_perf_start( RecvArp );\r
- status = __recv_arp( p_port, p_wc, p_ipoib, p_eth, &p_src, p_dst );\r
- cl_perf_stop( &p_port->p_adapter->perf, RecvArp );\r
- len = sizeof(ipoib_hdr_t) + sizeof(arp_pkt_t);\r
- break;\r
-\r
- default:\r
- /* Unfiltered. Setup the ethernet header and report. */\r
- cl_perf_start( RecvGen );\r
- status = __recv_gen( p_ipoib, p_eth, p_src, p_dst );\r
- cl_perf_stop( &p_port->p_adapter->perf, RecvGen );\r
- }\r
-\r
- if( status != IB_SUCCESS )\r
- {\r
- /* Update stats. */\r
- ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_ERROR, 0, 0 );\r
- cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item );\r
- /* Dereference the port object on behalf of the failed receive. */\r
- ipoib_port_deref( p_port, ref_recv_filter );\r
- }\r
- else\r
- {\r
- ip_stat_sel_t ip_stat;\r
- p_desc->len =\r
- len + sizeof(eth_hdr_t) - sizeof(ipoib_hdr_t);\r
- if( p_dst->h_mcast)\r
- {\r
- if( p_dst->dgid.multicast.raw_group_id[10] == 0xFF &&\r
- p_dst->dgid.multicast.raw_group_id[11] == 0xFF &&\r
- p_dst->dgid.multicast.raw_group_id[12] == 0xFF &&\r
- p_dst->dgid.multicast.raw_group_id[13] == 0xFF )\r
- {\r
- p_desc->type = PKT_TYPE_BCAST;\r
- ip_stat = IP_STAT_BCAST_BYTES;\r
- }\r
- else\r
- {\r
- p_desc->type = PKT_TYPE_MCAST;\r
- ip_stat = IP_STAT_MCAST_BYTES;\r
- }\r
- }\r
- else\r
- {\r
- p_desc->type = PKT_TYPE_UCAST;\r
- ip_stat = IP_STAT_UCAST_BYTES;\r
- \r
- }\r
- cl_qlist_insert_tail( p_done_list, &p_desc->item.list_item );\r
- ipoib_inc_recv_stat( p_port->p_adapter, ip_stat, len, 1 ); \r
- }\r
- }\r
-\r
- IPOIB_EXIT( IPOIB_DBG_RECV );\r
- return recv_cnt;\r
-}\r
-\r
-\r
-static ib_api_status_t\r
-__recv_gen(\r
- IN const ipoib_pkt_t* const p_ipoib,\r
- OUT eth_pkt_t* const p_eth,\r
- IN ipoib_endpt_t* const p_src,\r
- IN ipoib_endpt_t* const p_dst )\r
-{\r
- IPOIB_ENTER( IPOIB_DBG_RECV );\r
-\r
- if( !p_src || !p_dst )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Received packet with no matching endpoints.\n") );\r
- return IB_NOT_DONE;\r
- }\r
-\r
- /*\r
- * Fill in the ethernet header. Note that doing so will overwrite\r
- * the IPoIB header, so start by moving the information from the IPoIB\r
- * header.\r
- */\r
- p_eth->hdr.type = p_ipoib->hdr.type;\r
- p_eth->hdr.src = p_src->mac;\r
- p_eth->hdr.dst = p_dst->mac;\r
-\r
- if ( p_eth->hdr.dst.addr[0] == 1 && \r
- p_eth->hdr.type == ETH_PROT_TYPE_IP &&\r
- p_eth->hdr.dst.addr[2] == 0x5E) \r
- {\r
- p_eth->hdr.dst.addr[1] = 0;\r
- p_eth->hdr.dst.addr[3] = p_eth->hdr.dst.addr[3] & 0x7f;\r
- }\r
- if (p_dst->h_mcast)\r
- p_dst->is_in_use = TRUE;\r
-\r
- IPOIB_EXIT( IPOIB_DBG_RECV );\r
- return IB_SUCCESS;\r
-}\r
-\r
-\r
-static ib_api_status_t\r
-__recv_dhcp(\r
- IN ipoib_port_t* const p_port,\r
- IN const ipoib_pkt_t* const p_ipoib,\r
- OUT eth_pkt_t* const p_eth,\r
- IN ipoib_endpt_t* const p_src,\r
- IN ipoib_endpt_t* const p_dst )\r
-{\r
- ib_api_status_t status;\r
- dhcp_pkt_t *p_dhcp;\r
- uint8_t *p_option;\r
- uint8_t *p_cid = NULL;\r
- ib_gid_t gid;\r
- uint8_t msg = 0;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_RECV );\r
-\r
- UNUSED_PARAM( p_port );\r
-\r
- /* Create the ethernet header. */\r
- status = __recv_gen( p_ipoib, p_eth, p_src, p_dst );\r
- if( status != IB_SUCCESS )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("__recv_gen returned %s.\n", \r
- p_port->p_adapter->p_ifc->get_err_str( status )) );\r
- return status;\r
- }\r
-\r
- /* Fixup the payload. */\r
- p_dhcp = &p_eth->type.ip.prot.udp.dhcp;\r
- if( p_dhcp->op != DHCP_REQUEST && p_dhcp->op != DHCP_REPLY )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Invalid DHCP op code.\n") );\r
- return IB_INVALID_SETTING;\r
- }\r
-\r
- /*\r
- * Find the client identifier option, making sure to skip\r
- * the "magic cookie".\r
- */\r
- p_option = &p_dhcp->options[0];\r
- if ( *(uint32_t *)p_option != DHCP_COOKIE )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("DHCP cookie corrupted.\n") );\r
- return IB_INVALID_PARAMETER;\r
- }\r
-\r
- p_option = &p_dhcp->options[4];\r
- while( *p_option != DHCP_OPT_END && p_option < &p_dhcp->options[312] )\r
- {\r
- switch( *p_option )\r
- {\r
- case DHCP_OPT_PAD:\r
- p_option++;\r
- break;\r
-\r
- case DHCP_OPT_MSG:\r
- msg = p_option[2];\r
- p_option += 3;\r
- break;\r
-\r
- case DHCP_OPT_CLIENT_ID:\r
- p_cid = p_option;\r
- /* Fall through. */\r
-\r
- default:\r
- /*\r
- * All other options have a length byte following the option code.\r
- * Offset by the length to get to the next option.\r
- */\r
- p_option += (p_option[1] + 2);\r
- }\r
- }\r
-\r
- switch( msg )\r
- {\r
- /* message from client */\r
- case DHCPDISCOVER:\r
- case DHCPREQUEST:\r
- case DHCPDECLINE:\r
- case DHCPRELEASE:\r
- case DHCPINFORM:\r
- if( !p_cid )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Failed to find required Client-identifier option.\n") );\r
- return IB_INVALID_SETTING;\r
- }\r
- if( p_dhcp->htype != DHCP_HW_TYPE_IB )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Invalid hardware address type.\n") );\r
- return IB_INVALID_SETTING;\r
- }\r
- break;\r
- /* message from DHCP server */\r
- case DHCPOFFER:\r
- case DHCPACK:\r
- case DHCPNAK:\r
- break;\r
-\r
- default:\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Invalide message type.\n") );\r
- return IB_INVALID_PARAMETER;\r
- }\r
- p_eth->type.ip.prot.udp.hdr.chksum = 0;\r
- p_dhcp->htype = DHCP_HW_TYPE_ETH;\r
- p_dhcp->hlen = HW_ADDR_LEN;\r
-\r
- if( p_cid ) /* from client */\r
- {\r
- /* Validate that the length and type of the option is as required. */\r
- if( p_cid[1] != 21 )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Client-identifier length not 21 as required.\n") );\r
- return IB_INVALID_SETTING;\r
- }\r
- if( p_cid[2] != DHCP_HW_TYPE_IB )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Client-identifier type is wrong.\n") );\r
- return IB_INVALID_SETTING;\r
- }\r
- /*\r
- * Copy the GID value from the option so that we can make aligned\r
- * accesses to the contents.\r
- * Recover CID to standard type.\r
- */\r
- cl_memcpy( &gid, &p_cid[7], sizeof(ib_gid_t) );\r
- p_cid[1] = HW_ADDR_LEN +1;// CID length \r
- p_cid[2] = DHCP_HW_TYPE_ETH;// CID type \r
- status = ipoib_mac_from_guid( gid.unicast.interface_id, p_port->p_adapter->params.guid_mask, (mac_addr_t*)&p_cid[3] );\r
- if (status == IB_INVALID_GUID_MASK)\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_ERROR,\r
- ("Invalid GUID mask received, rejecting it") );\r
- ipoib_create_log(p_port->p_adapter->h_adapter, GUID_MASK_LOG_INDEX, EVENT_IPOIB_WRONG_PARAMETER_WRN);\r
- status = IB_SUCCESS;\r
- }\r
- p_cid[HW_ADDR_LEN + 3] = DHCP_OPT_END; //terminate tag\r
- }\r
- IPOIB_EXIT( IPOIB_DBG_RECV );\r
- return status;\r
-}\r
-\r
-\r
-static ib_api_status_t\r
-__recv_arp(\r
- IN ipoib_port_t* const p_port,\r
- IN ib_wc_t* const p_wc,\r
- IN const ipoib_pkt_t* const p_ipoib,\r
- OUT eth_pkt_t* const p_eth,\r
- IN ipoib_endpt_t** const pp_src,\r
- IN ipoib_endpt_t* const p_dst )\r
-{\r
- ib_api_status_t status;\r
- arp_pkt_t *p_arp;\r
- const ipoib_arp_pkt_t *p_ib_arp;\r
- ib_gid_t gid;\r
- mac_addr_t mac;\r
- ipoib_hw_addr_t null_hw = {0};\r
- uint8_t cm_capable = 0;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_RECV );\r
-\r
- if( !p_dst )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Unknown destination endpoint\n") );\r
- return IB_INVALID_SETTING;\r
- }\r
-\r
- p_ib_arp = &p_ipoib->type.arp;\r
- p_arp = &p_eth->type.arp;\r
-\r
- if( p_ib_arp->hw_type != ARP_HW_TYPE_IB )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ARP hardware type is not IB\n") );\r
- return IB_INVALID_SETTING;\r
- }\r
-\r
- if( p_ib_arp->hw_size != sizeof(ipoib_hw_addr_t) )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ARP hardware address size is not sizeof(ipoib_hw_addr_t)\n") );\r
- return IB_INVALID_SETTING;\r
- }\r
-\r
- if( p_ib_arp->prot_type != ETH_PROT_TYPE_IP )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ARP protocal type not IP\n") );\r
- return IB_INVALID_SETTING;\r
- }\r
-\r
- cm_capable = ipoib_addr_get_flags( &p_ib_arp->src_hw );\r
-\r
- /*\r
- * If we don't have a source, lookup the endpoint specified in the payload.\r
- */\r
- if( !*pp_src )\r
- *pp_src = __endpt_mgr_get_by_gid( p_port, &p_ib_arp->src_hw.gid );\r
-\r
- /*\r
- * If the endpoint exists for the GID, make sure\r
- * the dlid and qpn match the arp.\r
- */\r
- if( *pp_src )\r
- {\r
- if( cl_memcmp( &(*pp_src)->dgid, &p_ib_arp->src_hw.gid,\r
- sizeof(ib_gid_t) ) )\r
- {\r
- /*\r
- * GIDs for the endpoint are different. The ARP must\r
- * have been proxied. Dereference it.\r
- */\r
- *pp_src = NULL;\r
- }\r
- else if( (*pp_src)->dlid &&\r
- (*pp_src)->dlid != p_wc->recv.ud.remote_lid )\r
- {\r
- /* Out of date! Destroy the endpoint and replace it. */\r
- __endpt_mgr_remove( p_port, *pp_src );\r
- *pp_src = NULL;\r
- }\r
- else if ( ! ((*pp_src)->dlid)) {\r
- /* Out of date! Destroy the endpoint and replace it. */\r
- __endpt_mgr_remove( p_port, *pp_src );\r
- *pp_src = NULL;\r
- }\r
- else if( ipoib_is_voltaire_router_gid( &(*pp_src)->dgid ) )\r
- {\r
- if( (*pp_src)->qpn != ipoib_addr_get_qpn( &p_ib_arp->src_hw ) &&\r
- p_wc->recv.ud.remote_qp != ipoib_addr_get_qpn( &p_ib_arp->src_hw ) )\r
- {\r
- /* Out of date! Destroy the endpoint and replace it. */\r
- __endpt_mgr_remove( p_port, *pp_src );\r
- *pp_src = NULL;\r
- }\r
- }\r
- else if( (*pp_src)->qpn != p_wc->recv.ud.remote_qp )\r
- {\r
- /* Out of date! Destroy the endpoint and replace it. */\r
- __endpt_mgr_remove( p_port, *pp_src );\r
- *pp_src = NULL;\r
- }\r
- }\r
-\r
- /* Do we need to create an endpoint for this GID? */\r
- if( !*pp_src )\r
- {\r
- /* Copy the src GID to allow aligned access */\r
- cl_memcpy( &gid, &p_ib_arp->src_hw.gid, sizeof(ib_gid_t) );\r
- status = ipoib_mac_from_guid( gid.unicast.interface_id, p_port->p_adapter->params.guid_mask, &mac );\r
- if (status == IB_INVALID_GUID_MASK)\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_ERROR,\r
- ("Invalid GUID mask received, rejecting it") );\r
- ipoib_create_log(p_port->p_adapter->h_adapter, GUID_MASK_LOG_INDEX, EVENT_IPOIB_WRONG_PARAMETER_WRN);\r
- }\r
- else if( status != IB_SUCCESS )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ipoib_mac_from_guid returned %s\n",\r
- p_port->p_adapter->p_ifc->get_err_str( status )) );\r
- return status;\r
- }\r
- /*\r
- * Create the endpoint.\r
- */\r
- *pp_src = ipoib_endpt_create( &p_ib_arp->src_hw.gid,\r
- p_wc->recv.ud.remote_lid, ipoib_addr_get_qpn( &p_ib_arp->src_hw ) );\r
-\r
- if( !*pp_src )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ipoib_endpt_create failed\n") );\r
- return status;\r
- }\r
-\r
- cl_obj_lock( &p_port->obj );\r
- status = __endpt_mgr_insert( p_port, mac, *pp_src );\r
- if( status != IB_SUCCESS )\r
- {\r
- cl_obj_unlock( &p_port->obj );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("__endpt_mgr_insert return %s \n",\r
- p_port->p_adapter->p_ifc->get_err_str( status )) );\r
- return status;\r
- }\r
-\r
- cl_obj_unlock( &p_port->obj );\r
- }\r
-\r
- (*pp_src)->cm_flag = cm_capable;\r
-\r
- CL_ASSERT( !cl_memcmp(\r
- &(*pp_src)->dgid, &p_ib_arp->src_hw.gid, sizeof(ib_gid_t) ) );\r
- CL_ASSERT( ipoib_is_voltaire_router_gid( &(*pp_src)->dgid ) ||\r
- (*pp_src)->qpn == ipoib_addr_get_qpn( &p_ib_arp->src_hw ) );\r
-#if 0\r
- if( p_port->p_adapter->params.cm_enabled &&\r
- p_ib_arp->op == ARP_OP_REQ &&\r
- cm_capable == IPOIB_CM_FLAG_RC )\r
- {\r
- /* if we've got ARP request and RC flag is set, \r
- save SID for connect REQ to be sent in ARP reply\r
- when requestor's path get resolved */\r
- if( endpt_cm_get_state( (*pp_src) ) == IPOIB_CM_DISCONNECTED )\r
- {\r
- (*pp_src)->cm_flag = cm_capable;\r
- ipoib_addr_set_sid( \r
- &(*pp_src)->conn.service_id,\r
- ipoib_addr_get_qpn( &p_ib_arp->src_hw ) );\r
- }\r
- }\r
-#endif\r
-#if 0 //DBG\r
- if( p_port->p_adapter->params.cm_enabled )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
- (" ARP %s from ENDPT[%p] state %d CM cap: %d QPN: %#x MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",\r
- ((p_ib_arp->op == ARP_OP_REQ )? "REQUEST" : "REPLY"),\r
- *pp_src, endpt_cm_get_state( *pp_src ), \r
- ((cm_capable == IPOIB_CM_FLAG_RC)? 1: 0),\r
- cl_ntoh32( ipoib_addr_get_qpn( &p_ib_arp->src_hw ) ),\r
- (*pp_src)->mac.addr[0], (*pp_src)->mac.addr[1],\r
- (*pp_src)->mac.addr[2], (*pp_src)->mac.addr[3],\r
- (*pp_src)->mac.addr[4], (*pp_src)->mac.addr[5] ));\r
- }\r
-#endif\r
-\r
- /* Now swizzle the data. */\r
- p_arp->hw_type = ARP_HW_TYPE_ETH;\r
- p_arp->hw_size = sizeof(mac_addr_t);\r
- p_arp->src_hw = (*pp_src)->mac;\r
- p_arp->src_ip = p_ib_arp->src_ip;\r
-\r
- if( cl_memcmp( &p_ib_arp->dst_hw, &null_hw, sizeof(ipoib_hw_addr_t) ) )\r
- {\r
- if( cl_memcmp( &p_dst->dgid, &p_ib_arp->dst_hw.gid, sizeof(ib_gid_t) ) )\r
- {\r
- /*\r
- * We received bcast ARP packet that means\r
- * remote port lets everyone know it was changed IP/MAC\r
- * or just activated\r
- */\r
-\r
- /* Guy: TODO: Check why this check fails in case of Voltaire IPR */\r
-\r
- if ( !ipoib_is_voltaire_router_gid( &(*pp_src)->dgid ) &&\r
- !ib_gid_is_multicast( (const ib_gid_t*)&p_dst->dgid ) )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ARP: is not ARP MCAST\n") );\r
- return IB_INVALID_SETTING;\r
- }\r
-\r
- p_arp->dst_hw = p_port->p_local_endpt->mac;\r
- p_dst->mac = p_port->p_local_endpt->mac;\r
- /*\r
- * we don't care what receiver ip addr is,\r
- * as long as OS' ARP table is global ???\r
- */\r
- p_arp->dst_ip = (net32_t)0;\r
- }\r
- else /* we've got reply to our ARP request */\r
- {\r
- p_arp->dst_hw = p_dst->mac;\r
- p_arp->dst_ip = p_ib_arp->dst_ip;\r
- CL_ASSERT( p_dst->qpn == ipoib_addr_get_qpn( &p_ib_arp->dst_hw ) );\r
- }\r
- }\r
- else /* we got ARP reqeust */\r
- {\r
- cl_memclr( &p_arp->dst_hw, sizeof(mac_addr_t) );\r
- p_arp->dst_ip = p_ib_arp->dst_ip;\r
- }\r
-\r
- /*\r
- * Create the ethernet header. Note that this is done last so that\r
- * we have a chance to create a new endpoint.\r
- */\r
- status = __recv_gen( p_ipoib, p_eth, *pp_src, p_dst );\r
- if( status != IB_SUCCESS )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("__recv_gen returned %s.\n", \r
- p_port->p_adapter->p_ifc->get_err_str( status )) );\r
- return status;\r
- }\r
-\r
- IPOIB_EXIT( IPOIB_DBG_RECV );\r
- return IB_SUCCESS;\r
-}\r
-\r
-\r
-static ib_api_status_t\r
-__recv_mgr_prepare_pkt(\r
- IN ipoib_port_t* const p_port,\r
- IN ipoib_recv_desc_t* const p_desc,\r
- OUT NET_BUFFER_LIST** const pp_net_buffer_list )\r
-{\r
- NDIS_STATUS status;\r
- uint32_t pkt_filter;\r
- ip_stat_sel_t type;\r
- //NDIS60\r
- NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO chksum;\r
- //NDIS_TCP_IP_CHECKSUM_PACKET_INFO chksum;\r
-\r
- PERF_DECLARE( GetNdisPkt );\r
-\r
- IPOIB_ENTER( IPOIB_DBG_RECV );\r
-\r
- pkt_filter = p_port->p_adapter->packet_filter;\r
- /* Check the packet filter. */\r
- switch( p_desc->type )\r
- {\r
- default:\r
- case PKT_TYPE_UCAST:\r
- \r
- if( pkt_filter & NDIS_PACKET_TYPE_PROMISCUOUS ||\r
- pkt_filter & NDIS_PACKET_TYPE_ALL_FUNCTIONAL ||\r
- pkt_filter & NDIS_PACKET_TYPE_SOURCE_ROUTING ||\r
- pkt_filter & NDIS_PACKET_TYPE_DIRECTED )\r
- {\r
- /* OK to report. */\r
- type = IP_STAT_UCAST_BYTES;\r
- status = NDIS_STATUS_SUCCESS;\r
- IPOIB_PRINT( TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR,\r
- ("Received UCAST PKT.\n"));\r
- }\r
- else\r
- {\r
- type = IP_STAT_DROPPED;\r
- status = NDIS_STATUS_FAILURE;\r
- IPOIB_PRINT( TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR,\r
- ("Received UCAST PKT with ERROR !!!!\n"));\r
- }\r
- break;\r
- case PKT_TYPE_BCAST:\r
- if( pkt_filter & NDIS_PACKET_TYPE_PROMISCUOUS ||\r
- pkt_filter & NDIS_PACKET_TYPE_BROADCAST )\r
- {\r
- /* OK to report. */\r
- type = IP_STAT_BCAST_BYTES;\r
- status = NDIS_STATUS_SUCCESS;\r
- IPOIB_PRINT( TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR,\r
- ("Received BCAST PKT.\n"));\r
- }\r
- else\r
- {\r
- type = IP_STAT_DROPPED;\r
- status = NDIS_STATUS_FAILURE;\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Received BCAST PKT with ERROR !!!!\n"));\r
- }\r
- break;\r
- case PKT_TYPE_MCAST:\r
- if( pkt_filter & NDIS_PACKET_TYPE_PROMISCUOUS ||\r
- pkt_filter & NDIS_PACKET_TYPE_ALL_MULTICAST ||\r
- pkt_filter & NDIS_PACKET_TYPE_MULTICAST )\r
- {\r
- /* OK to report. */\r
- type = IP_STAT_MCAST_BYTES;\r
- status = NDIS_STATUS_SUCCESS;\r
- IPOIB_PRINT( TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR,\r
- ("Received UCAST PKT.\n"));\r
- }\r
- else\r
- {\r
- type = IP_STAT_DROPPED;\r
- status = NDIS_STATUS_FAILURE;\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Received MCAST PKT with ERROR !!!!\n"));\r
- }\r
- break;\r
- }\r
-\r
- if( status != NDIS_STATUS_SUCCESS )\r
- {\r
- ipoib_inc_recv_stat( p_port->p_adapter, type, 0, 0 );\r
- /* Return the receive descriptor to the pool. */\r
- __buf_mgr_put_recv( p_port, p_desc, NULL );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_RECV,\r
- ("Packet filter doesn't match receive. Dropping.\n") );\r
- /*\r
- * Return IB_NOT_DONE since the packet has been completed,\r
- * but has not consumed an array entry.\r
- */\r
- return IB_NOT_DONE;\r
- }\r
-\r
- cl_perf_start( GetNdisPkt );\r
- *pp_net_buffer_list = __buf_mgr_get_ndis_pkt( p_port, p_desc );\r
- cl_perf_stop( &p_port->p_adapter->perf, GetNdisPkt );\r
- if( !*pp_net_buffer_list )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("__buf_mgr_get_ndis_pkt failed\n") );\r
- return IB_INSUFFICIENT_RESOURCES;\r
- }\r
-\r
- chksum.Value = 0;\r
-\r
-{\r
- PNET_BUFFER NetBuffer = NET_BUFFER_LIST_FIRST_NB(*pp_net_buffer_list);\r
- NET_BUFFER_DATA_LENGTH(NetBuffer) = p_desc->len;\r
-}\r
- \r
- switch( p_port->p_adapter->params.recv_chksum_offload )\r
- {\r
- default:\r
- CL_ASSERT( FALSE );\r
- case CSUM_DISABLED:\r
- //NDIS60\r
- //NDIS_PER_PACKET_INFO_FROM_PACKET( *pp_packet, TcpIpChecksumPacketInfo ) =\r
- //(void*)(uintn_t)chksum.Value;\r
- NET_BUFFER_LIST_INFO(*pp_net_buffer_list, TcpIpChecksumNetBufferListInfo) = \r
- (void*)(uintn_t)chksum.Value;\r
- break;\r
- case CSUM_ENABLED:\r
- /* Get the checksums directly from packet information. */\r
- /* In this case, no one of cheksum's cat get false value */\r
- /* If hardware checksum failed or wasn't calculated, NDIS will recalculate it again */\r
- //NDIS60\r
- //NDIS_PER_PACKET_INFO_FROM_PACKET( *pp_packet, TcpIpChecksumPacketInfo ) = \r
- NET_BUFFER_LIST_INFO(*pp_net_buffer_list, TcpIpChecksumNetBufferListInfo) =\r
- (void*)(uintn_t)(p_desc->ndis_csum.Value);\r
- break;\r
- case CSUM_BYPASS:\r
- /* Flag the checksums as having been calculated. */\r
- chksum.Receive.TcpChecksumSucceeded = TRUE;\r
- chksum.Receive.UdpChecksumSucceeded = TRUE;\r
- chksum.Receive.IpChecksumSucceeded = TRUE;\r
- //NDIS60\r
- //NDIS_PER_PACKET_INFO_FROM_PACKET( *pp_packet, TcpIpChecksumPacketInfo ) =\r
- NET_BUFFER_LIST_INFO(*pp_net_buffer_list, TcpIpChecksumNetBufferListInfo) =\r
- (void*)(uintn_t)chksum.Value;\r
- break;\r
- }\r
- ipoib_inc_recv_stat( p_port->p_adapter, type, p_desc->len, 1 );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_RECV );\r
- return IB_SUCCESS;\r
-}\r
-\r
-\r
-static uint32_t\r
-__recv_mgr_build_pkt_array(\r
- IN ipoib_port_t* const p_port,\r
- IN int32_t shortage,\r
- OUT cl_qlist_t* const p_done_list,\r
- OUT int32_t* const p_discarded )\r
-{\r
- cl_list_item_t *p_item;\r
- ipoib_recv_desc_t *p_desc;\r
- uint32_t i = 0;\r
- ib_api_status_t status;\r
- PERF_DECLARE( PreparePkt );\r
-\r
- IPOIB_ENTER( IPOIB_DBG_RECV );\r
-\r
- *p_discarded = 0;\r
-\r
- /* Move any existing receives to the head to preserve ordering. */\r
- cl_qlist_insert_list_head( p_done_list, &p_port->recv_mgr.done_list );\r
- p_item = cl_qlist_remove_head( p_done_list );\r
- while( p_item != cl_qlist_end( p_done_list ) )\r
- {\r
- p_desc = (ipoib_recv_desc_t*)p_item;\r
-\r
- cl_perf_start( PreparePkt );\r
- status = __recv_mgr_prepare_pkt( p_port, p_desc,\r
- &p_port->recv_mgr.recv_pkt_array[i] );\r
- cl_perf_stop( &p_port->p_adapter->perf, PreparePkt );\r
- if( status == IB_SUCCESS )\r
- {\r
- CL_ASSERT( p_port->recv_mgr.recv_pkt_array[i] );\r
- if( shortage-- > 0 )\r
- {\r
- NET_BUFFER_LIST_STATUS(p_port->recv_mgr.recv_pkt_array[i])= NDIS_STATUS_RESOURCES; \r
- }\r
- else\r
- {\r
- NET_BUFFER_LIST_STATUS(p_port->recv_mgr.recv_pkt_array[i])= NDIS_STATUS_SUCCESS;\r
- }\r
- i++;\r
- }\r
- else if( status == IB_NOT_DONE )\r
- {\r
- (*p_discarded)++;\r
- }\r
- else\r
- {\r
- IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_RECV,\r
- ("__recv_mgr_prepare_pkt returned %s\n",\r
- p_port->p_adapter->p_ifc->get_err_str( status )) );\r
- /* Put all completed receives on the port's done list. */\r
- cl_qlist_insert_tail( &p_port->recv_mgr.done_list, p_item );\r
- cl_qlist_insert_list_tail( &p_port->recv_mgr.done_list, p_done_list );\r
- break;\r
- }\r
-\r
- p_item = cl_qlist_remove_head( p_done_list );\r
- }\r
-\r
- IPOIB_EXIT( IPOIB_DBG_RECV );\r
- return i;\r
-}\r
-\r
-\r
-\r
-\r
-/******************************************************************************\r
-*\r
-* Send manager implementation.\r
-*\r
-******************************************************************************/\r
-static void\r
-__send_mgr_construct(\r
- IN ipoib_port_t* const p_port )\r
-{\r
- IPOIB_ENTER( IPOIB_DBG_SEND );\r
- p_port->send_mgr.depth = 0;\r
- cl_qlist_init( &p_port->send_mgr.pending_list );\r
- IPOIB_EXIT( IPOIB_DBG_SEND );\r
-}\r
-\r
-\r
-static void \r
-__pending_list_destroy(\r
- IN ipoib_port_t* const p_port )\r
-{\r
- cl_list_item_t *p_item;\r
- NET_BUFFER_LIST **pp_net_buffer_list, *p_head;\r
- \r
- p_head = NULL;\r
- cl_spinlock_acquire( &p_port->send_lock );\r
- /* Complete any pending packets. */\r
- pp_net_buffer_list = &p_head;\r
- for( p_item = cl_qlist_remove_head( &p_port->send_mgr.pending_list );\r
- p_item != cl_qlist_end( &p_port->send_mgr.pending_list );\r
- p_item = cl_qlist_remove_head( &p_port->send_mgr.pending_list ) )\r
- {\r
- *pp_net_buffer_list = IPOIB_PACKET_FROM_LIST_ITEM( p_item );\r
- NET_BUFFER_LIST_STATUS(*pp_net_buffer_list) = NDIS_STATUS_RESET_IN_PROGRESS;\r
- pp_net_buffer_list = &(NET_BUFFER_LIST_NEXT_NBL(*pp_net_buffer_list));\r
- }\r
- cl_spinlock_release( &p_port->send_lock );\r
- if(p_head)\r
- NdisMSendNetBufferListsComplete(\r
- p_port->p_adapter->h_adapter,\r
- p_head,\r
- 0); \r
-}\r
-\r
-static void\r
-__send_mgr_destroy(\r
- IN ipoib_port_t* const p_port )\r
-{\r
- IPOIB_ENTER( IPOIB_DBG_SEND );\r
- __pending_list_destroy(p_port);\r
-\r
- IPOIB_EXIT( IPOIB_DBG_SEND );\r
-}\r
-\r
-\r
-static NDIS_STATUS\r
-__send_mgr_filter(\r
- IN ipoib_port_t* const p_port,\r
- IN const eth_hdr_t* const p_eth_hdr,\r
- IN MDL* const p_mdl,\r
- IN size_t buf_len,\r
- IN SCATTER_GATHER_LIST *p_sgl,\r
- IN OUT ipoib_send_desc_t* const p_desc )\r
-{\r
- NDIS_STATUS status;\r
-\r
- PERF_DECLARE( FilterIp );\r
- PERF_DECLARE( FilterArp );\r
- PERF_DECLARE( SendGen );\r
-\r
- IPOIB_ENTER( IPOIB_DBG_SEND );\r
-\r
- /*\r
- * We already checked the ethernet header length, so we know it's safe\r
- * to decrement the buf_len without underflowing.\r
- */\r
- buf_len -= sizeof(eth_hdr_t);\r
-\r
- switch( p_eth_hdr->type )\r
- {\r
- case ETH_PROT_TYPE_IP:\r
- cl_perf_start( FilterIp );\r
- status = __send_mgr_filter_ip(\r
- p_port, p_eth_hdr, p_mdl, buf_len, p_sgl, p_desc);\r
- cl_perf_stop( &p_port->p_adapter->perf, FilterIp );\r
- break;\r
-\r
- case ETH_PROT_TYPE_ARP:\r
- cl_perf_start( FilterArp );\r
- status = __send_mgr_filter_arp(\r
- p_port, p_eth_hdr, p_mdl, buf_len, p_desc );\r
- p_desc->send_dir = SEND_UD_QP;\r
- cl_perf_stop( &p_port->p_adapter->perf, FilterArp );\r
- break;\r
-\r
- default:\r
- /*\r
- * The IPoIB spec doesn't define how to send non IP or ARP packets.\r
- * Just send the payload and hope for the best.\r
- */\r
-\r
- p_desc->send_dir = SEND_UD_QP;\r
- cl_perf_start( SendGen );\r
- status = __send_gen( p_port, p_desc, p_sgl, 0 );\r
- cl_perf_stop( &p_port->p_adapter->perf, SendGen );\r
- break;\r
- }\r
-\r
- IPOIB_EXIT( IPOIB_DBG_SEND );\r
- return status;\r
-}\r
-\r
-\r
-static NDIS_STATUS\r
-__send_copy(\r
- IN ipoib_port_t* const p_port,\r
- IN ipoib_send_desc_t* const p_desc )\r
-{\r
- NET_BUFFER_LIST *p_net_buffer_list;\r
- NET_BUFFER *p_netbuffer;\r
- MDL *p_mdl;\r
- UINT tot_len = 0;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_SEND );\r
-\r
- UNREFERENCED_PARAMETER(p_port);\r
- UNREFERENCED_PARAMETER(p_desc);\r
-\r
- p_desc->p_buf = \r
- NdisAllocateFromNPagedLookasideList( &p_port->buf_mgr.send_buf_list );\r
- if( !p_desc->p_buf )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Failed to allocate buffer for packet copy.\n") );\r
- return NDIS_STATUS_RESOURCES;\r
- }\r
-\r
- p_mdl = NdisAllocateMdl(p_port->p_adapter->h_adapter,\r
- p_desc->p_buf,\r
- p_port->p_adapter->params.xfer_block_size );\r
- if( !p_mdl )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Failed to allocate MDL\n") );\r
- return NDIS_STATUS_RESOURCES;\r
- }\r
-\r
- p_net_buffer_list = NdisAllocateNetBufferAndNetBufferList(\r
- p_port->buf_mgr.h_send_buf_pool,\r
- 0,\r
- 0,\r
- p_mdl,\r
- 0,\r
- 0);\r
-\r
- if( !p_net_buffer_list )\r
- {\r
- NdisFreeMdl(p_mdl);\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_WARNING, IPOIB_DBG_SEND,\r
- ("Failed to allocate NDIS_PACKET for copy.\n") );\r
- return NDIS_STATUS_RESOURCES;\r
- }\r
-\r
- for (p_netbuffer = NET_BUFFER_LIST_FIRST_NB(p_net_buffer_list); \r
- p_netbuffer != NULL;\r
- p_netbuffer = NET_BUFFER_NEXT_NB(p_netbuffer))\r
- {\r
- tot_len +=NET_BUFFER_DATA_LENGTH(p_netbuffer);\r
- }\r
-\r
- /* Setup the work request. */\r
- p_desc->send_wr[0].local_ds[1].vaddr = cl_get_physaddr(\r
- ((uint8_t*)p_desc->p_buf) + sizeof(eth_hdr_t) );\r
- p_desc->send_wr[0].local_ds[1].length = tot_len - sizeof(eth_hdr_t);\r
- p_desc->send_wr[0].local_ds[1].lkey = p_port->ib_mgr.lkey;\r
- p_desc->send_wr[0].wr.num_ds = 2;\r
- \r
- /* Free our temp packet now that the data is copied. */\r
- NdisFreeMdl(p_mdl);\r
- NdisFreeNetBufferList(p_net_buffer_list);\r
-\r
- IPOIB_EXIT( IPOIB_DBG_SEND );\r
- return NDIS_STATUS_SUCCESS;\r
-}\r
-\r
-static inline NDIS_STATUS\r
-__send_mgr_get_eth_hdr(\r
- IN PNET_BUFFER p_net_buffer,\r
- OUT MDL** const pp_mdl,\r
- OUT eth_hdr_t** const pp_eth_hdr,\r
- OUT UINT* p_mdl_len)\r
-{\r
- PUCHAR p_head = NULL;\r
- IPOIB_ENTER( IPOIB_DBG_SEND );\r
-\r
- *pp_mdl = NET_BUFFER_FIRST_MDL(p_net_buffer);\r
-\r
- NdisQueryMdl(*pp_mdl,&p_head,p_mdl_len,NormalPagePriority);\r
- if( ! p_head )\r
- {\r
- /* Failed to get first buffer. */\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("NdisQueryMdl failed.\n") );\r
- return NDIS_STATUS_FAILURE;\r
- }\r
-\r
- if( *p_mdl_len < sizeof(eth_hdr_t) )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("First buffer in packet smaller than eth_hdr_t: %d.\n",\r
- *p_mdl_len) );\r
- return NDIS_STATUS_BUFFER_TOO_SHORT;\r
- }\r
-\r
- *pp_eth_hdr = (eth_hdr_t*)(p_head + NET_BUFFER_CURRENT_MDL_OFFSET(p_net_buffer));\r
-\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_SEND,\r
- ("Ethernet header:\n"\r
- "\tsrc MAC: %02X-%02X-%02X-%02X-%02X-%02X\n"\r
- "\tdst MAC: %02X-%02X-%02X-%02X-%02X-%02X\n"\r
- "\tprotocol type: %04X\n",\r
- (*pp_eth_hdr)->src.addr[0], (*pp_eth_hdr)->src.addr[1],\r
- (*pp_eth_hdr)->src.addr[2], (*pp_eth_hdr)->src.addr[3],\r
- (*pp_eth_hdr)->src.addr[4], (*pp_eth_hdr)->src.addr[5],\r
- (*pp_eth_hdr)->dst.addr[0], (*pp_eth_hdr)->dst.addr[1],\r
- (*pp_eth_hdr)->dst.addr[2], (*pp_eth_hdr)->dst.addr[3],\r
- (*pp_eth_hdr)->dst.addr[4], (*pp_eth_hdr)->dst.addr[5],\r
- cl_ntoh16( (*pp_eth_hdr)->type )) );\r
-\r
- return NDIS_STATUS_SUCCESS;\r
-}\r
-\r
-\r
-#if !IPOIB_USE_DMA\r
-/* Send using the MDL's page information rather than the SGL. */\r
-static ib_api_status_t\r
-__send_gen(\r
- IN ipoib_port_t* const p_port,\r
- IN ipoib_send_desc_t* const p_desc )\r
-{\r
- uint32_t i, j = 1;\r
- ULONG offset;\r
- MDL *p_mdl;\r
- UINT num_pages, tot_len;\r
- ULONG buf_len;\r
- PPFN_NUMBER page_array;\r
- boolean_t hdr_done = FALSE;\r
- ib_api_status_t status;\r
- PNET_BUFFER p_net_buf;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_SEND );\r
- p_net_buf = NET_BUFFER_LIST_FIRST_NB(p_desc->p_netbuf_list);\r
- NdisQueryBuffer( p_net_buf, &num_pages, NULL, &p_mdl,\r
- &tot_len );\r
-\r
- if( !p_mdl )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("No buffers associated with packet.\n") );\r
- return IB_ERROR;\r
- }\r
-\r
- /* Remember that one of the DS entries is reserved for the IPoIB header. */\r
- if( num_pages >= MAX_SEND_SGE )\r
- {\r
- IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_SEND,\r
- ("Too many buffers to fit in WR ds_array. Copying data.\n") );\r
- status = __send_copy( p_port, p_desc );\r
- IPOIB_EXIT( IPOIB_DBG_SEND );\r
- return status;\r
- }\r
-\r
- CL_ASSERT( tot_len > sizeof(eth_hdr_t) );\r
- CL_ASSERT( tot_len <= p_port->p_adapter->params.xfer_block_size );\r
- /*\r
- * Assume that the ethernet header is always fully contained\r
- * in the first page of the first MDL. This makes for much\r
- * simpler code.\r
- */\r
- offset = MmGetMdlByteOffset( p_mdl ) + sizeof(eth_hdr_t);\r
- CL_ASSERT( offset <= PAGE_SIZE );\r
-\r
- while( tot_len )\r
- {\r
- buf_len = MmGetMdlByteCount( p_mdl );\r
- page_array = MmGetMdlPfnArray( p_mdl );\r
- CL_ASSERT( page_array );\r
- i = 0;\r
- if( !hdr_done )\r
- {\r
- CL_ASSERT( buf_len >= sizeof(eth_hdr_t) );\r
- /* Skip the ethernet header. */\r
- buf_len -= sizeof(eth_hdr_t);\r
- CL_ASSERT( buf_len <= p_port->p_adapter->params.payload_mtu );\r
- if( buf_len )\r
- {\r
- /* The ethernet header is a subset of this MDL. */\r
- CL_ASSERT( i == 0 );\r
- if( offset < PAGE_SIZE )\r
- {\r
- p_desc->send_wr[0].local_ds[j].lkey = p_port->ib_mgr.lkey;\r
- p_desc->send_wr[0].local_ds[j].vaddr = (page_array[i] << PAGE_SHIFT);\r
- /* Add the byte offset since we're on the 1st page. */\r
- p_desc->send_wr[0].local_ds[j].vaddr += offset;\r
- if( offset + buf_len > PAGE_SIZE )\r
- {\r
- p_desc->send_wr[0].local_ds[j].length = PAGE_SIZE - offset;\r
- buf_len -= p_desc->send_wr[0].local_ds[j].length;\r
- }\r
- else\r
- {\r
- p_desc->send_wr[0].local_ds[j].length = buf_len;\r
- buf_len = 0;\r
- }\r
- /* This data segment is done. Move to the next. */\r
- j++;\r
- }\r
- /* This page is done. Move to the next. */\r
- i++;\r
- }\r
- /* Done handling the ethernet header. */\r
- hdr_done = TRUE;\r
- }\r
-\r
- /* Finish this MDL */\r
- while( buf_len )\r
- {\r
- p_desc->send_wr[0].local_ds[j].lkey = p_port->ib_mgr.lkey;\r
- p_desc->send_wr[0].local_ds[j].vaddr = (page_array[i] << PAGE_SHIFT);\r
- /* Add the first page's offset if we're on the first page. */\r
- if( i == 0 )\r
- p_desc->send_wr[0].local_ds[j].vaddr += MmGetMdlByteOffset( p_mdl );\r
-\r
- if( i == 0 && (MmGetMdlByteOffset( p_mdl ) + buf_len) > PAGE_SIZE )\r
- {\r
- /* Buffers spans pages. */\r
- p_desc->send_wr[0].local_ds[j].length =\r
- PAGE_SIZE - MmGetMdlByteOffset( p_mdl );\r
- buf_len -= p_desc->send_wr[0].local_ds[j].length;\r
- /* This page is done. Move to the next. */\r
- i++;\r
- }\r
- else\r
- {\r
- /* Last page of the buffer. */\r
- p_desc->send_wr[0].local_ds[j].length = buf_len;\r
- buf_len = 0;\r
- }\r
- /* This data segment is done. Move to the next. */\r
- j++;\r
- }\r
-\r
- tot_len -= MmGetMdlByteCount( p_mdl );\r
- if( !tot_len )\r
- break;\r
-\r
- NdisGetNextBuffer( p_mdl, &p_mdl );\r
- if( !p_mdl )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Failed to get next buffer.\n") );\r
- return IB_ERROR;\r
- }\r
- }\r
-\r
- /* Set the number of data segments. */\r
- p_desc->send_wr[0].wr.num_ds = j;\r
-\r
- IPOIB_EXIT( IPOIB_DBG_SEND );\r
- return IB_SUCCESS;\r
-}\r
-\r
-#else\r
-\r
-#if 0\r
-void \r
-ipoib_process_sg_list1(\r
- IN PDEVICE_OBJECT pDO,\r
- IN PVOID pIrp,\r
- IN PSCATTER_GATHER_LIST p_sgl,\r
- IN PVOID context\r
- )\r
-{\r
- int i;\r
- char temp[200];\r
- for (i = 0 ; i < 1;i++)\r
- temp[i] = 5;\r
-}\r
-#endif\r
-\r
-void \r
-ipoib_process_sg_list(\r
- IN PDEVICE_OBJECT pDO,\r
- IN PVOID pIrp,\r
- IN PSCATTER_GATHER_LIST p_sgl,\r
- IN PVOID context\r
- )\r
-{ \r
- NDIS_STATUS status;\r
- ipoib_port_t *p_port;\r
- MDL *p_mdl;\r
- eth_hdr_t *p_eth_hdr;\r
- UINT mdl_len;\r
- static ipoib_send_desc_t *p_desc = NULL;\r
- ib_send_wr_t *p_wr_failed;\r
- NET_BUFFER_LIST *p_net_buffer_list;\r
- NET_BUFFER *p_netbuf;\r
- boolean_t from_queue;\r
- ib_api_status_t ib_status;\r
- ULONG complete_flags = 0;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_SEND );\r
-\r
- UNREFERENCED_PARAMETER(pDO);\r
- UNREFERENCED_PARAMETER(pIrp);\r
-\r
- PERF_DECLARE( SendCopy );\r
- PERF_DECLARE( BuildSendDesc );\r
- PERF_DECLARE( GetEthHdr );\r
- PERF_DECLARE( QueuePacket );\r
- PERF_DECLARE( SendMgrQueue );\r
- PERF_DECLARE( PostSend );\r
- PERF_DECLARE( ProcessFailedSends );\r
- PERF_DECLARE( GetEndpt );\r
-\r
-\r
- p_netbuf = (NET_BUFFER*)context;\r
- p_net_buffer_list = (NET_BUFFER_LIST*)IPOIB_NET_BUFFER_LIST_FROM_NETBUFFER(p_netbuf);\r
- p_port = (ipoib_port_t*)IPOIB_PORT_FROM_PACKET(p_net_buffer_list);\r
- NDIS_SET_SEND_COMPLETE_FLAG(complete_flags, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL);\r
-\r
-\r
- cl_spinlock_acquire( &p_port->send_lock );\r
- if (p_desc == NULL) {\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_SEND, ("Allocating send_desc First Time\n") );\r
- p_desc = ExAllocatePoolWithTag(NonPagedPool ,sizeof (ipoib_send_desc_t), 'XMXA');\r
- }\r
- ASSERT(p_desc);\r
- p_desc->p_netbuf_list = p_net_buffer_list;\r
- p_desc->p_endpt = NULL;\r
- p_desc->p_buf = NULL;\r
- p_desc->num_wrs = 1;\r
-\r
- //IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_SEND,\r
- // ("\n*******\nRECEIVED NB= %x with SG= %x\n********\n", p_netbuf, p_sgl) );\r
- /* Get the ethernet header so we can find the endpoint. */\r
- cl_perf_start( GetEthHdr );\r
- status = __send_mgr_get_eth_hdr(\r
- p_netbuf, &p_mdl, &p_eth_hdr, &mdl_len );\r
- cl_perf_stop( &p_port->p_adapter->perf, GetEthHdr );\r
-\r
- if( status != NDIS_STATUS_SUCCESS )\r
- {\r
- cl_perf_start( ProcessFailedSends );\r
- /* fail net buffer list */\r
- __process_failed_send( p_port, p_desc, status, complete_flags);\r
- cl_perf_stop( &p_port->p_adapter->perf, ProcessFailedSends );\r
- goto send_end;\r
- }\r
- //from_queue = (boolean_t)(IPOIB_FROM_QUEUE(p_netbuf) == (void*)1);\r
- from_queue = (boolean_t)(IPOIB_FROM_QUEUE(p_netbuf) != NULL);\r
- if (from_queue)\r
- {\r
- cl_perf_start( GetEndpt );\r
- status = __endpt_mgr_ref( p_port, p_eth_hdr->dst, &p_desc->p_endpt );\r
- cl_perf_stop( &p_port->p_adapter->perf, GetEndpt );\r
- if( status == NDIS_STATUS_PENDING )\r
- {\r
- IPOIB_FROM_QUEUE(p_netbuf) = p_sgl;\r
- cl_qlist_insert_head( &p_port->send_mgr.pending_list,\r
- IPOIB_LIST_ITEM_FROM_PACKET( p_desc->p_netbuf_list ) );\r
- goto send_end;\r
- }\r
- else if( status != NDIS_STATUS_SUCCESS )\r
- {\r
- ASSERT( status == NDIS_STATUS_NO_ROUTE_TO_DESTINATION );\r
-\r
- if( ETH_IS_MULTICAST( p_eth_hdr->dst.addr ) )\r
- {\r
- if( ipoib_port_join_mcast( p_port, p_eth_hdr->dst,\r
- IB_MC_REC_STATE_FULL_MEMBER) == IB_SUCCESS )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_SEND,\r
- ("Multicast Mac - trying to join.\n") );\r
- IPOIB_FROM_QUEUE(p_netbuf) = p_sgl;\r
- cl_qlist_insert_head( &p_port->send_mgr.pending_list,\r
- IPOIB_LIST_ITEM_FROM_PACKET( p_desc->p_netbuf_list ) );\r
- goto send_end;\r
- }\r
- }\r
- /*\r
- * Complete the send as if we sent it - WHQL tests don't like the\r
- * sends to fail.\r
- */\r
- cl_perf_start( ProcessFailedSends );\r
- __process_failed_send( p_port, p_desc, NDIS_STATUS_SUCCESS,complete_flags );\r
- cl_perf_stop( &p_port->p_adapter->perf, ProcessFailedSends );\r
- goto send_end;\r
- }\r
- }\r
- else\r
- {\r
- cl_perf_start( SendMgrQueue );\r
- if ( ETH_IS_MULTICAST( p_eth_hdr->dst.addr ) && \r
- p_eth_hdr->type == ETH_PROT_TYPE_IP &&\r
- !ETH_IS_BROADCAST( p_eth_hdr->dst.addr ) ) \r
- {\r
- ip_hdr_t *p_ip_hdr;\r
- uint8_t *p_tmp;\r
- MDL *p_ip_hdr_mdl;\r
- UINT ip_hdr_mdl_len;\r
-\r
- if(mdl_len >= sizeof(ip_hdr_t) + sizeof(eth_hdr_t))\r
- {\r
- p_ip_hdr = (ip_hdr_t*)(p_eth_hdr + 1);\r
- }\r
- else\r
- {\r
- NdisGetNextMdl(p_mdl,&p_ip_hdr_mdl);\r
- // Extract the ip hdr \r
- if( !p_ip_hdr_mdl )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Failed to get IP header buffer.\n") );\r
- goto mc_end;\r
- } \r
- NdisQueryMdl(p_ip_hdr_mdl,&p_tmp,&ip_hdr_mdl_len,NormalPagePriority);\r
- if( !p_tmp )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Failed to get IP header.\n") );\r
- goto mc_end;\r
- } \r
- if( ip_hdr_mdl_len < sizeof(ip_hdr_t) )\r
- {\r
- /* This buffer is done for. Get the next buffer. */\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Buffer too small for IP packet.\n") );\r
- goto mc_end;\r
- }\r
- p_ip_hdr = (ip_hdr_t*)(p_tmp + NET_BUFFER_CURRENT_MDL_OFFSET(p_netbuf));\r
- p_eth_hdr->dst.addr[1] = ((unsigned char*)&p_ip_hdr->dst_ip)[0] & 0x0f;\r
- p_eth_hdr->dst.addr[3] = ((unsigned char*)&p_ip_hdr->dst_ip)[1];\r
- }\r
- }\r
-mc_end:\r
- status = __send_mgr_queue( p_port, p_eth_hdr, &p_desc->p_endpt );\r
- cl_perf_stop( &p_port->p_adapter->perf, SendMgrQueue );\r
- if( status == NDIS_STATUS_PENDING )\r
- {\r
- /* Queue net buffer list. */\r
- cl_perf_start( QueuePacket );\r
- NET_BUFFER_LIST_NEXT_NBL(p_net_buffer_list) = NULL;\r
- IPOIB_FROM_QUEUE(p_netbuf) = p_sgl;\r
- cl_qlist_insert_tail( &p_port->send_mgr.pending_list,\r
- IPOIB_LIST_ITEM_FROM_PACKET(p_net_buffer_list) );\r
- cl_perf_stop( &p_port->p_adapter->perf, QueuePacket );\r
- goto send_end;\r
- }\r
- if( status != NDIS_STATUS_SUCCESS )\r
- {\r
- ASSERT( status == NDIS_STATUS_NO_ROUTE_TO_DESTINATION );\r
- /*\r
- * Complete the send as if we sent it - WHQL tests don't like the\r
- * sends to fail.\r
- */\r
- cl_perf_start( ProcessFailedSends );\r
- __process_failed_send( p_port, p_desc, NDIS_STATUS_SUCCESS, complete_flags );\r
- cl_perf_stop( &p_port->p_adapter->perf, ProcessFailedSends );\r
- goto send_end;\r
- }\r
- }\r
- cl_perf_start( BuildSendDesc );\r
- status = __build_send_desc( p_port, p_eth_hdr, p_mdl, mdl_len, p_sgl, p_desc );\r
- cl_perf_stop( &p_port->p_adapter->perf, BuildSendDesc );\r
-\r
- if( status != NDIS_STATUS_SUCCESS )\r
- {\r
- cl_perf_start( ProcessFailedSends );\r
- __process_failed_send( p_port, p_desc, status, complete_flags );\r
- cl_perf_stop( &p_port->p_adapter->perf, ProcessFailedSends );\r
- goto send_end;\r
- }\r
-\r
- /* Post the WR. */\r
- cl_perf_start( PostSend );\r
- cl_msg_out("sending packet with wr-id =0x%x\n",&p_desc->send_wr[0].wr.wr_id );\r
- 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 );\r
- cl_perf_stop( &p_port->p_adapter->perf, PostSend );\r
- if( ib_status != IB_SUCCESS )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ib_post_send returned %s\n", \r
- p_port->p_adapter->p_ifc->get_err_str( ib_status )) );\r
- cl_perf_start( ProcessFailedSends );\r
- __process_failed_send( p_port, p_desc, NDIS_STATUS_FAILURE, complete_flags );\r
- cl_perf_stop( &p_port->p_adapter->perf, ProcessFailedSends );\r
- /* Flag the adapter as hung since posting is busted. */\r
- p_port->p_adapter->hung = TRUE;\r
- }\r
- cl_atomic_inc( &p_port->send_mgr.depth );\r
-\r
-send_end:\r
- if (status != NDIS_STATUS_SUCCESS) {\r
-// IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_SEND,\r
- // ("Free S/G List: 0x%x.\n", (UINT) (PVOID) p_sgl) );\r
- /*NdisMFreeNetBufferSGList(\r
- p_port->p_adapter->NdisMiniportDmaHandle,\r
- p_sgl,\r
- p_netbuf);*/\r
- \r
- }\r
- \r
- \r
- cl_spinlock_release( &p_port->send_lock );\r
- IPOIB_EXIT( IPOIB_DBG_SEND );\r
-}\r
-\r
-static NDIS_STATUS\r
-__send_gen(\r
- IN ipoib_port_t* const p_port,\r
- IN ipoib_send_desc_t* const p_desc,\r
- IN SCATTER_GATHER_LIST *p_sgl,\r
- IN INT lso_data_index\r
- )\r
-{\r
- ib_api_status_t status;\r
- uint32_t i, j = 1;\r
- uint32_t offset = sizeof(eth_hdr_t);\r
- PERF_DECLARE( SendCopy );\r
-\r
- IPOIB_ENTER( IPOIB_DBG_SEND );\r
-\r
- if( !p_sgl )\r
- {\r
- ASSERT( p_sgl );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Failed to get SGL from packet.\n") );\r
- return NDIS_STATUS_FAILURE;\r
- }\r
-\r
- /* Remember that one of the DS entries is reserved for the IPoIB header. */\r
- if( ( p_sgl->NumberOfElements >= MAX_SEND_SGE ||\r
- p_sgl->Elements[0].Length < sizeof(eth_hdr_t)) )\r
- {\r
-\r
- IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_SEND,\r
- ("Too many buffers %d to fit in WR ds_array[%d] \\r
- Or buffer[0] length %d < Eth header. Copying data.\n",\r
- p_sgl->NumberOfElements, MAX_SEND_SGE, p_sgl->Elements[0].Length ) );\r
- status = NDIS_STATUS_RESOURCES;\r
- if( !p_port->p_adapter->params.cm_enabled )\r
- {\r
- cl_perf_start( SendCopy );\r
- status = __send_copy( p_port, p_desc );\r
- cl_perf_stop( &p_port->p_adapter->perf, SendCopy );\r
- }\r
- IPOIB_EXIT( IPOIB_DBG_SEND );\r
- return status;\r
- }\r
-\r
- /*\r
- * Skip the ethernet header. It is either the first element,\r
- * or part of it.\r
- */\r
- i = 0;\r
- if( lso_data_index )\r
- { /* we have an LSO packet */\r
- i = lso_data_index;\r
- j = 0;\r
- }\r
- else while( offset )\r
- {\r
- if( p_sgl->Elements[i].Length <= offset )\r
- {\r
- offset -= p_sgl->Elements[i++].Length;\r
- }\r
- else\r
- {\r
- p_desc->send_wr[0].local_ds[j].vaddr =\r
- p_sgl->Elements[i].Address.QuadPart + offset;\r
- p_desc->send_wr[0].local_ds[j].length =\r
- p_sgl->Elements[i].Length - offset;\r
- p_desc->send_wr[0].local_ds[j].lkey = p_port->ib_mgr.lkey;\r
- i++;\r
- j++;\r
- break;\r
- }\r
- }\r
- /* Now fill in the rest of the local data segments. */\r
- while( i < p_sgl->NumberOfElements )\r
- {\r
- p_desc->send_wr[0].local_ds[j].vaddr = p_sgl->Elements[i].Address.QuadPart;\r
- p_desc->send_wr[0].local_ds[j].length = p_sgl->Elements[i].Length;\r
- p_desc->send_wr[0].local_ds[j].lkey = p_port->ib_mgr.lkey;\r
- i++;\r
- j++;\r
- }\r
-\r
- /* Set the number of data segments. */\r
- p_desc->send_wr[0].wr.num_ds = j;\r
-\r
- IPOIB_EXIT( IPOIB_DBG_SEND );\r
- return NDIS_STATUS_SUCCESS;\r
-}\r
-#endif\r
-\r
-\r
-static NDIS_STATUS\r
-__send_mgr_filter_ip(\r
- IN ipoib_port_t* const p_port,\r
- IN const eth_hdr_t* const p_eth_hdr,\r
- IN MDL* p_mdl,\r
- IN size_t buf_len,\r
- IN SCATTER_GATHER_LIST *p_sgl,\r
- IN OUT ipoib_send_desc_t* const p_desc )\r
-{\r
- NDIS_STATUS status;\r
- ip_hdr_t *p_ip_hdr;\r
- uint32_t ip_packet_len;\r
- size_t iph_size_in_bytes;\r
- size_t iph_options_size;\r
- \r
- PERF_DECLARE( QueryIp );\r
- PERF_DECLARE( SendTcp );\r
- PERF_DECLARE( FilterUdp );\r
-\r
- IPOIB_ENTER( IPOIB_DBG_SEND );\r
-\r
- if( !buf_len )\r
- {\r
- cl_perf_start( QueryIp );\r
- NdisGetNextMdl ( p_mdl, &p_mdl );\r
- if( !p_mdl )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Failed to get IP header buffer.\n") );\r
- return NDIS_STATUS_FAILURE;\r
- }\r
-\r
- NdisQueryMdl(p_mdl, &p_ip_hdr, &buf_len, NormalPagePriority);\r
- if( !p_ip_hdr )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Failed to query IP header buffer.\n") );\r
- return NDIS_STATUS_FAILURE;\r
- }\r
- cl_perf_stop( &p_port->p_adapter->perf, QueryIp );\r
- }\r
- else\r
- {\r
- p_ip_hdr = (ip_hdr_t*)(p_eth_hdr + 1);\r
- }\r
- if( buf_len < sizeof(ip_hdr_t) )\r
- {\r
- /* This buffer is done for. Get the next buffer. */\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Buffer too small for IP packet.\n") );\r
- return NDIS_STATUS_BUFFER_TOO_SHORT;\r
- }\r
-\r
- switch( p_ip_hdr->prot )\r
- {\r
- case IP_PROT_UDP:\r
-\r
- cl_perf_start( FilterUdp );\r
- status = __send_mgr_filter_udp(\r
- p_port, p_ip_hdr, p_mdl, (buf_len - sizeof(ip_hdr_t)), p_sgl, p_desc );\r
- cl_perf_stop( &p_port->p_adapter->perf, FilterUdp );\r
- if( status == NDIS_STATUS_PENDING )\r
- { /* not DHCP packet, keep going */\r
- if( ETH_IS_MULTICAST( p_eth_hdr->dst.addr ) )\r
- p_desc->send_dir = SEND_UD_QP;\r
- else\r
- p_desc->send_dir = SEND_RC_QP;\r
- break;\r
- }\r
- return status;\r
- \r
- case IP_PROT_TCP:\r
- p_desc->send_dir = SEND_RC_QP;\r
- break;\r
- case IP_PROT_IGMP:\r
- /*\r
- In igmp packet I saw that iph arrive in 2 NDIS_BUFFERs:\r
- 1. iph\r
- 2. ip options\r
- So to get the IGMP packet we need to skip the ip options NDIS_BUFFER\r
- */\r
- iph_size_in_bytes = (p_ip_hdr->ver_hl & 0xf) * 4;\r
- iph_options_size = iph_size_in_bytes - buf_len;\r
- buf_len -= sizeof(ip_hdr_t);//without ipheader\r
-\r
- /*\r
- Could be a case that arrived igmp packet not from type IGMPv2 ,\r
- but IGMPv1 or IGMPv3.\r
- We anyway pass it to __send_mgr_filter_igmp_v2().\r
- */\r
- status =\r
- __send_mgr_filter_igmp_v2( p_port, p_ip_hdr, iph_options_size, p_mdl, buf_len );\r
- if( status != NDIS_STATUS_SUCCESS )\r
- return status;\r
-\r
- case IP_PROT_ICMP:\r
- p_desc->send_dir = SEND_UD_QP;\r
- default:\r
- break;\r
- }\r
- \r
- if( !p_port->p_adapter->params.cm_enabled )\r
- {\r
- p_desc->send_dir = SEND_UD_QP;\r
- goto send_gen;\r
- }\r
- else if( endpt_cm_get_state( p_desc->p_endpt ) != IPOIB_CM_CONNECTED )\r
- {\r
- p_desc->send_dir = SEND_UD_QP;\r
- }\r
- if( p_desc->send_dir == SEND_UD_QP )\r
- {\r
- ip_packet_len = cl_ntoh16( p_ip_hdr->length );\r
- if( ip_packet_len > p_port->p_adapter->params.payload_mtu )\r
- {\r
- //TODO: NDIS60\r
- #if 0\r
- status = __send_fragments( p_port, p_desc, (eth_hdr_t* const)p_eth_hdr,\r
- (ip_hdr_t* const)p_ip_hdr, (uint32_t)buf_len, p_mdl );\r
- return status;\r
- #endif\r
- ASSERT(FALSE);\r
- }\r
- }\r
-\r
-send_gen:\r
- cl_perf_start( SendTcp );\r
- status = __send_gen( p_port, p_desc, p_sgl, 0 );\r
- cl_perf_stop( &p_port->p_adapter->perf, SendTcp );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_SEND );\r
- return status;\r
-}\r
-\r
-static NDIS_STATUS\r
-__send_mgr_filter_igmp_v2(\r
- IN ipoib_port_t* const p_port,\r
- IN const ip_hdr_t* const p_ip_hdr,\r
- IN size_t iph_options_size,\r
- IN MDL* p_mdl,\r
- IN size_t buf_len )\r
-{\r
- igmp_v2_hdr_t *p_igmp_v2_hdr = NULL;\r
- NDIS_STATUS endpt_status;\r
- ipoib_endpt_t* p_endpt = NULL;\r
- mac_addr_t fake_mcast_mac;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_SEND );\r
-\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_MCAST,\r
- ("buf_len = %d,iph_options_size = %d\n",(int)buf_len,(int)iph_options_size ) );\r
-\r
- if( !buf_len )\r
- {\r
- // To get the IGMP packet we need to skip the ip options NDIS_BUFFER (if exists)\r
- while ( iph_options_size )\r
- {\r
- NdisGetNextMdl( p_mdl, &p_mdl );\r
- if( !p_mdl )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Failed to get IGMPv2 header buffer.\n") );\r
- return NDIS_STATUS_FAILURE;\r
- }\r
- NdisQueryMdl( p_mdl, &p_igmp_v2_hdr, &buf_len, NormalPagePriority );\r
- if( !p_igmp_v2_hdr )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Failed to query IGMPv2 header buffer.\n") );\r
- return NDIS_STATUS_FAILURE;\r
- }\r
- iph_options_size-=buf_len;\r
- }\r
- \r
- NdisGetNextMdl( p_mdl, &p_mdl );\r
- if( !p_mdl )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Failed to get IGMPv2 header buffer.\n") );\r
- return NDIS_STATUS_FAILURE;\r
- }\r
- NdisQueryMdl( p_mdl, &p_igmp_v2_hdr, &buf_len, NormalPagePriority );\r
- if( !p_igmp_v2_hdr )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Failed to query IGMPv2 header buffer.\n") );\r
- return NDIS_STATUS_FAILURE;\r
- }\r
- }\r
- else\r
- {\r
- /* assuming ip header and options are in the same packet */\r
- p_igmp_v2_hdr = GetIpPayloadPtr(p_ip_hdr);\r
- }\r
- /* Get the IGMP header length. */\r
- if( buf_len < sizeof(igmp_v2_hdr_t) )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Buffer not large enough for IGMPv2 packet.\n") );\r
- return NDIS_STATUS_BUFFER_TOO_SHORT;\r
- }\r
-\r
- // build fake mac from igmp packet group address\r
- fake_mcast_mac.addr[0] = 1;\r
- fake_mcast_mac.addr[1] = ((unsigned char*)&p_igmp_v2_hdr->group_address)[0] & 0x0f;\r
- fake_mcast_mac.addr[2] = 0x5E;\r
- fake_mcast_mac.addr[3] = ((unsigned char*)&p_igmp_v2_hdr->group_address)[1];\r
- fake_mcast_mac.addr[4] = ((unsigned char*)&p_igmp_v2_hdr->group_address)[2];\r
- fake_mcast_mac.addr[5] = ((unsigned char*)&p_igmp_v2_hdr->group_address)[3];\r
-\r
- switch ( p_igmp_v2_hdr->type )\r
- {\r
- case IGMP_V2_MEMBERSHIP_REPORT:\r
- /* \r
- This mean that some body open listener on this group \r
- Change type of mcast endpt to SEND_RECV endpt. So mcast garbage collector \r
- will not delete this mcast endpt.\r
- */\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_MCAST,\r
- ("Catched IGMP_V2_MEMBERSHIP_REPORT message\n") );\r
- endpt_status = __endpt_mgr_ref( p_port, fake_mcast_mac, &p_endpt );\r
- if ( p_endpt )\r
- {\r
- cl_obj_lock( &p_port->obj );\r
- p_endpt->is_mcast_listener = TRUE;\r
- cl_obj_unlock( &p_port->obj );\r
- ipoib_endpt_deref( p_endpt );\r
- }\r
- break;\r
-\r
- case IGMP_V2_LEAVE_GROUP:\r
- /* \r
- This mean that somebody CLOSE listener on this group .\r
- Change type of mcast endpt to SEND_ONLY endpt. So mcast \r
- garbage collector will delete this mcast endpt next time.\r
- */\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_MCAST,\r
- ("Catched IGMP_V2_LEAVE_GROUP message\n") );\r
- endpt_status = __endpt_mgr_ref( p_port, fake_mcast_mac, &p_endpt );\r
- if ( p_endpt )\r
- {\r
- cl_obj_lock( &p_port->obj );\r
- p_endpt->is_mcast_listener = FALSE;\r
- p_endpt->is_in_use = FALSE;\r
- cl_obj_unlock( &p_port->obj );\r
- ipoib_endpt_deref( p_endpt );\r
- }\r
-\r
- __port_do_mcast_garbage(p_port);\r
-\r
- break;\r
-\r
- default:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_MCAST,\r
- ("Send Unknown IGMP message: 0x%x \n", p_igmp_v2_hdr->type ) );\r
- break;\r
- }\r
-\r
- IPOIB_EXIT( IPOIB_DBG_SEND );\r
- return NDIS_STATUS_SUCCESS;\r
-}\r
-\r
-static NDIS_STATUS\r
-__send_mgr_filter_udp(\r
- IN ipoib_port_t* const p_port,\r
- IN const ip_hdr_t* const p_ip_hdr,\r
- IN MDL* p_mdl,\r
- IN size_t buf_len,\r
- IN SCATTER_GATHER_LIST *p_sgl,\r
- IN OUT ipoib_send_desc_t* const p_desc )\r
-{\r
- ib_api_status_t status;\r
- udp_hdr_t *p_udp_hdr;\r
- PERF_DECLARE( QueryUdp );\r
- PERF_DECLARE( SendUdp );\r
- PERF_DECLARE( FilterDhcp );\r
- //TODO NDIS60 remove this param\r
- UNUSED_PARAM(p_sgl);\r
- IPOIB_ENTER( IPOIB_DBG_SEND );\r
-\r
- if( !buf_len )\r
- {\r
- cl_perf_start( QueryUdp );\r
- NdisGetNextMdl( p_mdl, &p_mdl );\r
- if( !p_mdl )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Failed to get UDP header buffer.\n") );\r
- return NDIS_STATUS_FAILURE;\r
- }\r
- NdisQueryMdl( p_mdl, &p_udp_hdr, &buf_len, NormalPagePriority );\r
- if( !p_udp_hdr )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Failed to query UDP header buffer.\n") );\r
- return NDIS_STATUS_FAILURE;\r
- }\r
- cl_perf_stop( &p_port->p_adapter->perf, QueryUdp );\r
- }\r
- else\r
- {\r
- p_udp_hdr = (udp_hdr_t*)GetIpPayloadPtr(p_ip_hdr);\r
- }\r
- /* Get the UDP header and check the destination port numbers. */\r
- \r
- if (p_ip_hdr->offset > 0) {\r
- /* This is a fragmented part of UDP packet\r
- * Only first packet will contain UDP header in such case\r
- * So, return if offset > 0\r
- */\r
- return NDIS_STATUS_PENDING;\r
- }\r
- \r
- if( buf_len < sizeof(udp_hdr_t) )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Buffer not large enough for UDP packet.\n") );\r
- return NDIS_STATUS_BUFFER_TOO_SHORT;\r
- }\r
-\r
- if( (p_udp_hdr->src_port != DHCP_PORT_CLIENT ||\r
- p_udp_hdr->dst_port != DHCP_PORT_SERVER) &&\r
- (p_udp_hdr->src_port != DHCP_PORT_SERVER ||\r
- p_udp_hdr->dst_port != DHCP_PORT_CLIENT) )\r
- {\r
- /* Not a DHCP packet. */\r
- return NDIS_STATUS_PENDING;\r
- }\r
-\r
- buf_len -= sizeof(udp_hdr_t);\r
-\r
- /* Allocate our scratch buffer. */\r
- p_desc->p_buf = (send_buf_t*)\r
- ExAllocateFromNPagedLookasideList( &p_port->buf_mgr.send_buf_list );\r
- if( !p_desc->p_buf )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Failed to query DHCP packet buffer.\n") );\r
- return NDIS_STATUS_RESOURCES;\r
- }\r
- /* Copy the IP and UDP headers. */\r
- cl_memcpy( &p_desc->p_buf->ip.hdr, p_ip_hdr , sizeof(ip_hdr_t) );\r
- cl_memcpy(\r
- &p_desc->p_buf->ip.prot.udp.hdr, p_udp_hdr, sizeof(udp_hdr_t) );\r
-\r
- cl_perf_start( FilterDhcp );\r
- status = __send_mgr_filter_dhcp(\r
- p_port, p_udp_hdr, p_mdl, buf_len, p_desc );\r
- cl_perf_stop( &p_port->p_adapter->perf, FilterDhcp );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_SEND );\r
- return status;\r
-}\r
-\r
-unsigned short ipchksum(unsigned short *ip, int len)\r
-{\r
- unsigned long sum = 0;\r
-\r
- len >>= 1;\r
- while (len--) {\r
- sum += *(ip++);\r
- if (sum > 0xFFFF)\r
- sum -= 0xFFFF;\r
- }\r
- return (unsigned short)((~sum) & 0x0000FFFF);\r
-}\r
-\r
-static NDIS_STATUS\r
-__send_mgr_filter_dhcp(\r
- IN ipoib_port_t* const p_port,\r
- IN const udp_hdr_t* const p_udp_hdr,\r
- IN NDIS_BUFFER* p_mdl,\r
- IN size_t buf_len,\r
- IN OUT ipoib_send_desc_t* const p_desc )\r
-{\r
- dhcp_pkt_t *p_dhcp;\r
- dhcp_pkt_t *p_ib_dhcp;\r
- uint8_t *p_option, *p_cid = NULL;\r
- uint8_t msg = 0;\r
- size_t len;\r
- ib_gid_t gid;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_SEND );\r
-\r
- if( !buf_len )\r
- {\r
- NdisGetNextMdl( p_mdl, &p_mdl );\r
- if( !p_mdl )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Failed to get DHCP buffer.\n") );\r
- return NDIS_STATUS_FAILURE;\r
- }\r
- NdisQueryMdl( p_mdl, &p_dhcp, &buf_len, NormalPagePriority );\r
- if( !p_dhcp )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Failed to query DHCP buffer.\n") );\r
- return NDIS_STATUS_FAILURE;\r
- }\r
- }\r
- else\r
- {\r
- p_dhcp = (dhcp_pkt_t*)(p_udp_hdr + 1);\r
- }\r
-\r
- if( buf_len < DHCP_MIN_SIZE )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Buffer not large enough for DHCP packet.\n") );\r
- return NDIS_STATUS_BUFFER_TOO_SHORT;\r
- }\r
-\r
- p_ib_dhcp = &p_desc->p_buf->ip.prot.udp.dhcp;\r
- cl_memcpy( p_ib_dhcp, p_dhcp, buf_len );\r
-\r
- /* Now scan through the options looking for the client identifier. */\r
- p_option = &p_ib_dhcp->options[4];\r
- while( *p_option != DHCP_OPT_END && p_option < &p_ib_dhcp->options[312] )\r
- {\r
- switch( *p_option )\r
- {\r
- case DHCP_OPT_PAD:\r
- p_option++;\r
- break;\r
-\r
- case DHCP_OPT_MSG:\r
- msg = p_option[2];\r
- p_option += 3;\r
- break;\r
-\r
- case DHCP_OPT_CLIENT_ID:\r
- p_cid = p_option;\r
- /* Fall through. */\r
-\r
- default:\r
- /*\r
- * All other options have a length byte following the option code.\r
- * Offset by the length to get to the next option.\r
- */\r
- p_option += (p_option[1] + 2);\r
- }\r
- }\r
-\r
- switch( msg )\r
- {\r
- /* Client messages */\r
- case DHCPDISCOVER:\r
- case DHCPREQUEST:\r
- p_ib_dhcp->flags |= DHCP_FLAGS_BROADCAST;\r
- /* Fall through */\r
- case DHCPDECLINE:\r
- case DHCPRELEASE:\r
- case DHCPINFORM:\r
- /* Fix up the client identifier option */\r
- if( p_cid )\r
- {\r
- /* do we need to replace it ? len eq ETH MAC sz 'and' MAC is mine */\r
- if( p_cid[1] == HW_ADDR_LEN+1 && !cl_memcmp( &p_cid[3],\r
- &p_port->p_adapter->params.conf_mac.addr, HW_ADDR_LEN ) )\r
- {\r
- /* Make sure there's room to extend it. 23 is the size of\r
- * the CID option for IPoIB.\r
- */\r
- if( buf_len + 23 - p_cid[1] > sizeof(dhcp_pkt_t) )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Can't convert CID to IPoIB format.\n") );\r
- return NDIS_STATUS_RESOURCES;\r
- }\r
- /* Move the existing options down, and add a new CID option */\r
- len = p_option - ( p_cid + p_cid[1] + 2 );\r
- p_option = p_cid + p_cid[1] + 2;\r
- RtlMoveMemory( p_cid, p_option, len );\r
- \r
- p_cid += len;\r
- p_cid[0] = DHCP_OPT_CLIENT_ID;\r
- p_cid[1] = 21;\r
- p_cid[2] = DHCP_HW_TYPE_IB;\r
- }\r
- else\r
- {\r
- p_cid[2] = DHCP_HW_TYPE_IB;\r
- }\r
- }\r
- else\r
- {\r
- /*\r
- * Make sure there's room to extend it. 23 is the size of\r
- * the CID option for IPoIB.\r
- */\r
- if( buf_len + 23 > sizeof(dhcp_pkt_t) )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Can't convert CID to IPoIB format.\n") );\r
- return NDIS_STATUS_RESOURCES;\r
- }\r
-\r
- p_cid = p_option;\r
- p_option = p_cid + 23;\r
- p_option[0] = DHCP_OPT_END;\r
- p_cid[0] = DHCP_OPT_CLIENT_ID;\r
- p_cid[1] = 21;\r
- p_cid[2] = DHCP_HW_TYPE_IB;\r
- }\r
-\r
- CL_ASSERT( p_cid[1] == 21 );\r
- p_cid[23]= DHCP_OPT_END;\r
- ib_gid_set_default( &gid, p_port->p_adapter->guids.port_guid.guid );\r
- cl_memcpy( &p_cid[7], &gid, sizeof(ib_gid_t) );\r
- cl_memcpy( &p_cid[3], &p_port->ib_mgr.qpn, sizeof(p_port->ib_mgr.qpn) ); \r
- p_ib_dhcp->htype = DHCP_HW_TYPE_IB;\r
-\r
- /* update lengths to include any change we made */\r
- p_desc->p_buf->ip.hdr.length = cl_ntoh16( sizeof(ip_hdr_t) + sizeof(udp_hdr_t) + sizeof(dhcp_pkt_t) );\r
- p_desc->p_buf->ip.prot.udp.hdr.length = cl_ntoh16( sizeof(udp_hdr_t) + sizeof(dhcp_pkt_t) );\r
-\r
- /* update crc in ip header */\r
- //if( !p_port->p_adapter->params.send_chksum_offload )\r
- //{ //TODO ?\r
- p_desc->p_buf->ip.hdr.chksum = 0;\r
- p_desc->p_buf->ip.hdr.chksum = ipchksum((unsigned short*) &p_desc->p_buf->ip.hdr, sizeof(ip_hdr_t));\r
- //} TODO ??\r
- break;\r
-\r
- /* Server messages. */\r
- case DHCPOFFER:\r
- case DHCPACK:\r
- case DHCPNAK:\r
- /* don't touch server messages */\r
- break;\r
-\r
- default:\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Invalide message type.\n") );\r
- return NDIS_STATUS_INVALID_DATA;\r
- }\r
- /* no chksum for udp */\r
- p_desc->p_buf->ip.prot.udp.hdr.chksum = 0;\r
- p_desc->send_wr[0].local_ds[1].vaddr = cl_get_physaddr( p_desc->p_buf );\r
- p_desc->send_wr[0].local_ds[1].length = sizeof(ip_hdr_t) + sizeof(udp_hdr_t) + sizeof(dhcp_pkt_t);\r
- p_desc->send_wr[0].local_ds[1].lkey = p_port->ib_mgr.lkey;\r
- p_desc->send_wr[0].wr.num_ds = 2;\r
- p_desc->send_dir = SEND_UD_QP;\r
- IPOIB_EXIT( IPOIB_DBG_SEND );\r
- return NDIS_STATUS_SUCCESS;\r
-}\r
-\r
-\r
-static NDIS_STATUS\r
-__send_mgr_filter_arp(\r
- IN ipoib_port_t* const p_port,\r
- IN const eth_hdr_t* const p_eth_hdr,\r
- IN MDL* p_mdl,\r
- IN size_t buf_len,\r
- IN OUT ipoib_send_desc_t* const p_desc )\r
-{\r
- arp_pkt_t *p_arp;\r
- ipoib_arp_pkt_t *p_ib_arp;\r
- NDIS_STATUS status;\r
- mac_addr_t null_hw = {0};\r
-\r
- IPOIB_ENTER( IPOIB_DBG_SEND );\r
- \r
- if( !buf_len )\r
- {\r
- NdisGetNextMdl( p_mdl, &p_mdl );\r
- if( !p_mdl )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Failed to get ARP buffer.\n") );\r
- return NDIS_STATUS_FAILURE;\r
- }\r
- NdisQueryMdl( p_mdl, &p_arp, &buf_len, NormalPagePriority );\r
- if( !p_arp )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Failed to get query ARP buffer.\n") );\r
- return NDIS_STATUS_FAILURE;\r
- }\r
- }\r
- else\r
- {\r
- p_arp = (arp_pkt_t*)(p_eth_hdr + 1);\r
- }\r
-\r
- /* Single buffer ARP packet. */\r
- if( buf_len < sizeof(arp_pkt_t) )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Buffer too short for ARP.\n") );\r
- return NDIS_STATUS_BUFFER_TOO_SHORT;\r
- }\r
-\r
- if( p_arp->prot_type != ETH_PROT_TYPE_IP )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Unsupported protocol type.\n") );\r
- return NDIS_STATUS_INVALID_DATA;\r
- }\r
-\r
- /* Allocate our scratch buffer. */\r
- p_desc->p_buf = (send_buf_t*)\r
- NdisAllocateFromNPagedLookasideList( &p_port->buf_mgr.send_buf_list );\r
- if( !p_desc->p_buf )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Failed to query ARP packet buffer.\n") );\r
- return NDIS_STATUS_RESOURCES;\r
- }\r
- p_ib_arp = (ipoib_arp_pkt_t*)p_desc->p_buf;\r
-\r
- /* Convert the ARP payload. */\r
- p_ib_arp->hw_type = ARP_HW_TYPE_IB;\r
- p_ib_arp->prot_type = p_arp->prot_type;\r
- p_ib_arp->hw_size = sizeof(ipoib_hw_addr_t);\r
- p_ib_arp->prot_size = p_arp->prot_size;\r
- p_ib_arp->op = p_arp->op;\r
- \r
- ipoib_addr_set_qpn( &p_ib_arp->src_hw, p_port->ib_mgr.qpn );\r
-#if 0\r
-\r
- if( p_port->p_adapter->params.cm_enabled )\r
- {\r
- ipoib_addr_set_flags( &p_ib_arp->src_hw, IPOIB_CM_FLAG_RC );\r
- }\r
-#endif\r
-\r
- ib_gid_set_default( &p_ib_arp->src_hw.gid,\r
- p_port->p_adapter->guids.port_guid.guid );\r
- p_ib_arp->src_ip = p_arp->src_ip;\r
- if( cl_memcmp( &p_arp->dst_hw, &null_hw, sizeof(mac_addr_t) ) )\r
- {\r
- /* Get the endpoint referenced by the dst_hw address. */\r
- net32_t qpn = 0;\r
- status = __endpt_mgr_get_gid_qpn( p_port, p_arp->dst_hw,\r
- &p_ib_arp->dst_hw.gid, &qpn );\r
- if( status != NDIS_STATUS_SUCCESS )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Failed lookup of destination HW address\n") );\r
- return status;\r
- }\r
- ipoib_addr_set_qpn( &p_ib_arp->dst_hw, qpn );\r
-#if 0\r
- if( p_arp->op == ARP_OP_REP && \r
- p_port->p_adapter->params.cm_enabled && \r
- p_desc->p_endpt->cm_flag == IPOIB_CM_FLAG_RC )\r
- {\r
- cm_state_t cm_state;\r
- cm_state = \r
- ( cm_state_t )InterlockedCompareExchange( (volatile LONG *)&p_desc->p_endpt->conn.state,\r
- IPOIB_CM_CONNECT, IPOIB_CM_DISCONNECTED );\r
- switch( cm_state )\r
- {\r
- case IPOIB_CM_DISCONNECTED:\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
- ("ARP REPLY pending Endpt[%p] QPN %#x MAC %02x:%02x:%02x:%02x:%02x:%02x\n",\r
- p_desc->p_endpt, \r
- cl_ntoh32( ipoib_addr_get_qpn( &p_ib_arp->dst_hw )),\r
- p_desc->p_endpt->mac.addr[0], p_desc->p_endpt->mac.addr[1],\r
- p_desc->p_endpt->mac.addr[2], p_desc->p_endpt->mac.addr[3],\r
- p_desc->p_endpt->mac.addr[4], p_desc->p_endpt->mac.addr[5] ) );\r
- ipoib_addr_set_sid( &p_desc->p_endpt->conn.service_id,\r
- ipoib_addr_get_qpn( &p_ib_arp->dst_hw ) );\r
-\r
- NdisFreeToNPagedLookasideList(\r
- &p_port->buf_mgr.send_buf_list, p_desc->p_buf );\r
- cl_qlist_insert_tail( &p_port->send_mgr.pending_list,\r
- IPOIB_LIST_ITEM_FROM_PACKET( p_desc->p_buf ) );\r
- NdisInterlockedInsertTailList( &p_port->endpt_mgr.pending_conns, \r
- &p_desc->p_endpt->list_item, \r
- &p_port->endpt_mgr.conn_lock );\r
- cl_event_signal( &p_port->endpt_mgr.event );\r
- return NDIS_STATUS_PENDING;\r
- \r
- case IPOIB_CM_CONNECT:\r
- /* queue ARP REP packet until connected */\r
- NdisFreeToNPagedLookasideList(\r
- &p_port->buf_mgr.send_buf_list, p_desc->p_buf );\r
- cl_qlist_insert_tail( &p_port->send_mgr.pending_list,\r
- IPOIB_LIST_ITEM_FROM_PACKET( p_desc->p_pkt ) );\r
- return NDIS_STATUS_PENDING;\r
- default:\r
- break;\r
- }\r
- }\r
-#endif\r
- }\r
- else\r
- {\r
- cl_memclr( &p_ib_arp->dst_hw, sizeof(ipoib_hw_addr_t) );\r
- }\r
- \r
-#if 0 //DBG\r
- if( p_port->p_adapter->params.cm_enabled )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
- (" ARP %s SEND to ENDPT[%p] State: %d flag: %#x, QPN: %#x MAC %02x:%02x:%02x:%02x:%02x:%02x\n",\r
- ( p_ib_arp->op == ARP_OP_REP ? "REP": "REQ"), p_desc->p_endpt, \r
- endpt_cm_get_state( p_desc->p_endpt ),\r
- p_desc->p_endpt->cm_flag, \r
- cl_ntoh32( ipoib_addr_get_qpn( &p_ib_arp->dst_hw )),\r
- p_desc->p_endpt->mac.addr[0], p_desc->p_endpt->mac.addr[1],\r
- p_desc->p_endpt->mac.addr[2], p_desc->p_endpt->mac.addr[3],\r
- p_desc->p_endpt->mac.addr[4], p_desc->p_endpt->mac.addr[5] ));\r
- }\r
-#endif\r
-\r
- p_ib_arp->dst_ip = p_arp->dst_ip;\r
-\r
- p_desc->send_wr[0].local_ds[1].vaddr = cl_get_physaddr( p_ib_arp );\r
- p_desc->send_wr[0].local_ds[1].length = sizeof(ipoib_arp_pkt_t);\r
- p_desc->send_wr[0].local_ds[1].lkey = p_port->ib_mgr.lkey;\r
- p_desc->send_wr[0].wr.num_ds = 2;\r
- p_desc->send_wr[0].wr.p_next = NULL;\r
-\r
- IPOIB_EXIT( IPOIB_DBG_SEND );\r
- return NDIS_STATUS_SUCCESS;\r
-}\r
-\r
-static inline NDIS_STATUS\r
-__send_mgr_queue(\r
- IN ipoib_port_t* const p_port,\r
- IN eth_hdr_t* const p_eth_hdr,\r
- OUT ipoib_endpt_t** const pp_endpt )\r
-{\r
- NDIS_STATUS status;\r
-\r
- PERF_DECLARE( GetEndpt );\r
-\r
- IPOIB_ENTER( IPOIB_DBG_SEND );\r
-\r
- /* Check the send queue and pend the request if not empty. */\r
- if( cl_qlist_count( &p_port->send_mgr.pending_list ) )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_WARNING, IPOIB_DBG_SEND,\r
- ("Pending list not empty.\n") );\r
- return NDIS_STATUS_PENDING;\r
- }\r
-\r
- /* Check the send queue and pend the request if not empty. */\r
- if( p_port->send_mgr.depth == p_port->p_adapter->params.sq_depth )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_WARNING, IPOIB_DBG_SEND,\r
- ("No available WQEs.\n") );\r
- return NDIS_STATUS_PENDING;\r
- }\r
-\r
- cl_perf_start( GetEndpt );\r
- status = __endpt_mgr_ref( p_port, p_eth_hdr->dst, pp_endpt );\r
- cl_perf_stop( &p_port->p_adapter->perf, GetEndpt );\r
-\r
- if( status == NDIS_STATUS_NO_ROUTE_TO_DESTINATION &&\r
- ETH_IS_MULTICAST( p_eth_hdr->dst.addr ) )\r
- {\r
- if( ipoib_port_join_mcast( p_port, p_eth_hdr->dst, \r
- IB_MC_REC_STATE_FULL_MEMBER) == IB_SUCCESS )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_SEND,\r
- ("Multicast Mac - trying to join.\n") );\r
- return NDIS_STATUS_PENDING;\r
- }\r
- }\r
- else if ( status == NDIS_STATUS_SUCCESS && \r
- ETH_IS_MULTICAST( p_eth_hdr->dst.addr ) && \r
- !ETH_IS_BROADCAST( p_eth_hdr->dst.addr ) )\r
- {\r
- CL_ASSERT( (*pp_endpt) );\r
- CL_ASSERT((*pp_endpt)->h_mcast != NULL);\r
- (*pp_endpt)->is_in_use = TRUE;\r
- }\r
-\r
- IPOIB_EXIT( IPOIB_DBG_SEND );\r
- return status;\r
-}\r
-\r
-\r
-static NDIS_STATUS\r
-__build_send_desc(\r
- IN ipoib_port_t* const p_port,\r
- IN eth_hdr_t* const p_eth_hdr,\r
- IN MDL* const p_mdl,\r
- IN const size_t mdl_len,\r
- IN SCATTER_GATHER_LIST *p_sgl,\r
- IN OUT ipoib_send_desc_t* const p_desc )\r
-{\r
- NDIS_STATUS status;\r
- int32_t hdr_idx;\r
- uint32_t mss;\r
- //PVOID* pp_tmp;\r
- PNDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO p_checksum_list_info;\r
- PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO p_lso_info;\r
- PERF_DECLARE( SendMgrFilter );\r
- \r
- IPOIB_ENTER( IPOIB_DBG_SEND );\r
-\r
- /* Format the send descriptor. */\r
- p_checksum_list_info = NET_BUFFER_LIST_INFO( p_desc->p_netbuf_list,TcpIpChecksumNetBufferListInfo);\r
- //pp_tmp = &NET_BUFFER_LIST_INFO(p_desc->p_netbuf_list, TcpIpChecksumNetBufferListInfo);\r
- //p_checksum_list_info = ( ) ((PULONG)pp_tmp);\r
- p_lso_info = NET_BUFFER_LIST_INFO( p_desc->p_netbuf_list, TcpLargeSendNetBufferListInfo );\r
- \r
- /* Format the send descriptor. */\r
- hdr_idx = cl_atomic_inc( &p_port->hdr_idx );\r
- hdr_idx &= (p_port->p_adapter->params.sq_depth - 1);\r
- ASSERT( hdr_idx < p_port->p_adapter->params.sq_depth );\r
- p_port->hdr[hdr_idx].type = p_eth_hdr->type;\r
- p_port->hdr[hdr_idx].resv = 0;\r
-\r
- p_desc->send_wr[0].local_ds[0].vaddr = cl_get_physaddr( &p_port->hdr[hdr_idx] );\r
- p_desc->send_wr[0].local_ds[0].length = sizeof(ipoib_hdr_t);\r
- p_desc->send_wr[0].local_ds[0].lkey = p_port->ib_mgr.lkey;\r
- p_desc->send_wr[0].wr.send_opt = 0;\r
-\r
- mss = (p_lso_info->LsoV1Transmit.MSS | p_lso_info->LsoV2Transmit.MSS);\r
- //TODO: first check params.lso, and thereafter calculate LSO\r
- if( p_port->p_adapter->params.lso && mss )\r
-\r
-\r
- {\r
- ASSERT( mss == (p_lso_info->LsoV1Transmit.MSS & p_lso_info->LsoV2Transmit.MSS));\r
- ASSERT ( (mss & (1<<20)) == mss);\r
- status = __build_lso_desc( p_port, p_desc, mss, p_sgl, hdr_idx, p_lso_info );\r
- if( status != NDIS_STATUS_SUCCESS )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("__build_lso_desc returned 0x%08X.\n", status) );\r
- return status;\r
- }\r
- }\r
- else\r
- {\r
- uint32_t i;\r
- cl_perf_start( SendMgrFilter );\r
- status = __send_mgr_filter(\r
- p_port, p_eth_hdr, p_mdl, mdl_len,p_sgl, p_desc );\r
- cl_perf_stop( &p_port->p_adapter->perf, SendMgrFilter );\r
- if( status != NDIS_STATUS_SUCCESS )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("__send_mgr_filter returned 0x%08X.\n", status) );\r
- return status;\r
- }\r
-\r
- if( p_desc->send_dir == SEND_UD_QP )\r
- {\r
- p_desc->send_qp = p_port->ib_mgr.h_qp; // UD QP\r
- for( i = 0; i < p_desc->num_wrs; i++ )\r
- {\r
- p_desc->send_wr[i].wr.dgrm.ud.remote_qp = p_desc->p_endpt->qpn;\r
- p_desc->send_wr[i].wr.dgrm.ud.remote_qkey = p_port->ib_mgr.bcast_rec.qkey;\r
- p_desc->send_wr[i].wr.dgrm.ud.h_av = p_desc->p_endpt->h_av;\r
- p_desc->send_wr[i].wr.dgrm.ud.pkey_index = p_port->pkey_index;\r
- p_desc->send_wr[i].wr.dgrm.ud.rsvd = NULL;\r
- p_desc->send_wr[i].wr.send_opt = 0;\r
-\r
- if( p_port->p_adapter->params.send_chksum_offload && \r
- ( p_checksum_list_info->Transmit.IsIPv4 || \r
- p_checksum_list_info->Transmit.IsIPv6 ))\r
- {\r
- // Set transimition checksum offloading \r
- if( p_checksum_list_info->Transmit.IpHeaderChecksum )\r
- {\r
- p_desc->send_wr[i].wr.send_opt |= IB_SEND_OPT_TX_IP_CSUM;\r
- }\r
- if( p_checksum_list_info->Transmit.TcpChecksum )\r
- {\r
- p_desc->send_wr[i].wr.send_opt |= IB_SEND_OPT_TX_TCP_UDP_CSUM;\r
- }\r
- }\r
- }\r
- }\r
- else // RC QP\r
- {\r
- CL_ASSERT( p_desc->send_dir == SEND_RC_QP );\r
- p_desc->send_qp = p_desc->p_endpt->conn.h_work_qp;\r
- }\r
- for( i = 0; i < p_desc->num_wrs; i++ )\r
- {\r
- p_desc->send_wr[i].wr.wr_type = WR_SEND;\r
- p_desc->send_wr[i].wr.wr_id = 0;\r
- p_desc->send_wr[i].wr.ds_array = &p_desc->send_wr[i].local_ds[0];\r
- if( i )\r
- {\r
- p_desc->send_wr[i-1].wr.p_next = &p_desc->send_wr[i].wr;\r
- }\r
- }\r
- //TODO p_net_buf or p_buf\r
-// p_desc->send_wr[p_desc->num_wrs - 1].wr.wr_id = (uintn_t)NET_BUFFER_LIST_FIRST_NB(p_desc->p_netbuf_list );\r
-//???? IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, ("WR_ID was set to NBL 0x%x \n",p_desc->p_netbuf_list ));\r
- p_desc->send_wr[p_desc->num_wrs - 1].wr.wr_id = (uintn_t)p_desc->p_netbuf_list ;\r
-\r
- p_desc->send_wr[p_desc->num_wrs - 1].wr.send_opt |= IB_SEND_OPT_SIGNALED;\r
- p_desc->send_wr[p_desc->num_wrs - 1].wr.p_next = NULL;\r
- }\r
-\r
- /* Store context in our reserved area of the packet. */\r
- IPOIB_PORT_FROM_PACKET( p_desc->p_netbuf_list ) = p_port;\r
- IPOIB_ENDPT_FROM_PACKET( p_desc->p_netbuf_list ) = p_desc->p_endpt;\r
- IPOIB_SEND_FROM_NETBUFFER( NET_BUFFER_LIST_FIRST_NB(p_desc->p_netbuf_list ))= p_desc->p_buf;\r
-\r
- IPOIB_EXIT( IPOIB_DBG_SEND );\r
- return NDIS_STATUS_SUCCESS;\r
-}\r
-\r
-static NDIS_STATUS\r
-__build_lso_desc(\r
- IN ipoib_port_t* const p_port,\r
- IN OUT ipoib_send_desc_t* const p_desc,\r
- IN ULONG mss,\r
- IN SCATTER_GATHER_LIST *p_sgl,\r
- IN int32_t hdr_idx, \r
- IN PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO p_lso_info)\r
-{\r
- NDIS_STATUS status;\r
- LsoData TheLsoData;\r
- UINT IndexOfData = 0;\r
- \r
- PNET_BUFFER FirstBuffer = NET_BUFFER_LIST_FIRST_NB (p_desc->p_netbuf_list);\r
- ULONG PacketLength = NET_BUFFER_DATA_LENGTH(FirstBuffer);\r
-\r
- IPOIB_ENTER( IPOIB_DBG_SEND );\r
-\r
-\r
-\r
- memset(&TheLsoData, 0, sizeof TheLsoData );\r
- status = GetLsoHeaderSize(\r
- FirstBuffer, \r
- &TheLsoData, \r
- &IndexOfData,\r
- &p_port->hdr[hdr_idx] );\r
-\r
- if ((status != NDIS_STATUS_SUCCESS ) || \r
- (TheLsoData.FullBuffers != TheLsoData.UsedBuffers)) \r
- {\r
- ASSERT(FALSE);\r
-\r
- IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, ("<-- Throwing this packet\n"));\r
-\r
- if( status == NDIS_STATUS_SUCCESS )\r
- {\r
- status = NDIS_STATUS_INVALID_PACKET;\r
- }\r
- return status;\r
- }\r
- ASSERT(TheLsoData.LsoHeaderSize> 0);\r
- // Tell NDIS how much we will send.\r
- //PktExt->NdisPacketInfo[TcpLargeSendPacketInfo] = UlongToPtr(PacketLength);\r
- p_lso_info->LsoV1TransmitComplete.TcpPayload = PacketLength;\r
-\r
- p_desc->send_wr[0].wr.dgrm.ud.mss = mss;\r
- p_desc->send_wr[0].wr.dgrm.ud.header = TheLsoData.LsoBuffers[0].pData;\r
- p_desc->send_wr[0].wr.dgrm.ud.hlen = TheLsoData.LsoHeaderSize ;//lso_header_size; \r
- p_desc->send_wr[0].wr.dgrm.ud.remote_qp = p_desc->p_endpt->qpn;\r
- p_desc->send_wr[0].wr.dgrm.ud.remote_qkey = p_port->ib_mgr.bcast_rec.qkey;\r
- p_desc->send_wr[0].wr.dgrm.ud.h_av = p_desc->p_endpt->h_av;\r
- p_desc->send_wr[0].wr.dgrm.ud.pkey_index = p_port->pkey_index;\r
- p_desc->send_wr[0].wr.dgrm.ud.rsvd = NULL;\r
-\r
- //TODO: Should be NBL or p_desc\r
- p_desc->send_wr[0].wr.wr_id = (uintn_t)p_desc->p_netbuf_list;\r
- p_desc->send_wr[0].wr.ds_array = p_desc->send_wr[0].local_ds;\r
- p_desc->send_wr[0].wr.wr_type = WR_LSO;\r
- p_desc->send_wr[0].wr.send_opt = \r
- (IB_SEND_OPT_TX_IP_CSUM | IB_SEND_OPT_TX_TCP_UDP_CSUM) | IB_SEND_OPT_SIGNALED;\r
- \r
- p_desc->send_wr[0].wr.p_next = NULL;\r
- p_desc->send_qp = p_port->ib_mgr.h_qp;\r
- p_desc->send_dir = SEND_UD_QP;\r
- status = __send_gen(p_port, p_desc, p_sgl, IndexOfData );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_SEND );\r
- return status;\r
-}\r
-\r
-static inline void\r
-__process_failed_send(\r
- IN ipoib_port_t* const p_port,\r
- IN ipoib_send_desc_t* const p_desc,\r
- IN const NDIS_STATUS status,\r
- IN ULONG compl_flags)\r
-{\r
- IPOIB_ENTER( IPOIB_DBG_SEND );\r
-\r
- /* Complete the packet. */\r
- NET_BUFFER_LIST_NEXT_NBL(p_desc->p_netbuf_list) = NULL;\r
- NET_BUFFER_LIST_STATUS(p_desc->p_netbuf_list) = status;\r
- NdisMSendNetBufferListsComplete( p_port->p_adapter->h_adapter,\r
- p_desc->p_netbuf_list, compl_flags );\r
- ipoib_inc_send_stat( p_port->p_adapter, IP_STAT_ERROR, 0 );\r
- /* Deref the endpoint. */\r
- if( p_desc->p_endpt )\r
- ipoib_endpt_deref( p_desc->p_endpt );\r
-\r
- if( p_desc->p_buf )\r
- {\r
- NdisFreeToNPagedLookasideList(\r
- &p_port->buf_mgr.send_buf_list, p_desc->p_buf );\r
- }\r
-\r
- IPOIB_EXIT( IPOIB_DBG_SEND );\r
-}\r
-\r
-// max number of physical fragmented buffers \r
-#define MAX_PHYS_BUF_FRAG_ELEMENTS 0x29\r
-#define MP_FRAG_ELEMENT SCATTER_GATHER_ELEMENT \r
-#define PMP_FRAG_ELEMENT PSCATTER_GATHER_ELEMENT \r
-\r
-\r
-typedef struct _MP_FRAG_LIST {\r
- ULONG NumberOfElements;\r
- ULONG_PTR Reserved;\r
- SCATTER_GATHER_ELEMENT Elements[MAX_PHYS_BUF_FRAG_ELEMENTS];\r
-} MP_FRAG_LIST, *PMP_FRAG_LIST;\r
-\r
-\r
-void \r
-CreateFragList(\r
- ULONG PhysBufCount,\r
- PNET_BUFFER NetBuff,\r
- ULONG PacketLength,\r
- PMP_FRAG_LIST pFragList\r
- )\r
-{\r
-// ETH_ENTER(ETH_SND);\r
-\r
- ULONG i = 0;\r
- int j=0;\r
-\r
- UINT buf_len = NET_BUFFER_DATA_LENGTH(NetBuff);\r
- PMDL pMdl = NET_BUFFER_CURRENT_MDL(NetBuff);\r
-\r
- ULONG CurrentMdlDataOffset = NET_BUFFER_CURRENT_MDL_OFFSET(NetBuff);\r
- ASSERT(MmGetMdlByteCount(pMdl) >= CurrentMdlDataOffset);\r
-\r
- \r
- ASSERT(NetBuff != NULL);\r
-#ifdef DBG\r
- ASSERT(PhysBufCount <= MAX_PHYS_BUF_FRAG_ELEMENTS);\r
-#else\r
- UNREFERENCED_PARAMETER(PhysBufCount);\r
-#endif\r
- \r
- ASSERT(buf_len > 0);\r
- UNREFERENCED_PARAMETER(PacketLength);\r
-\r
-\r
-// ETH_PRINT(TRACE_LEVEL_VERBOSE, ETH_SND, "CreateFragList: NetBuff %p, Length =0x%x\n", NetBuff, buf_len);\r
-\r
- while ( (pMdl != NULL) && (buf_len != 0) )\r
- {\r
- PPFN_NUMBER page_array = MmGetMdlPfnArray(pMdl);\r
- int MdlBufCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(pMdl), MmGetMdlByteCount(pMdl));\r
- \r
- ULONG offset = MmGetMdlByteOffset(pMdl) + CurrentMdlDataOffset ; \r
- ULONG MdlBytesCount = MmGetMdlByteCount(pMdl) - CurrentMdlDataOffset;\r
- CurrentMdlDataOffset = 0;\r
- \r
- if( MdlBytesCount == 0 )\r
- {\r
- pMdl = pMdl->Next;\r
- continue;\r
- }\r
-\r
- ASSERT( (buf_len > 0) && (MdlBytesCount > 0) );\r
- \r
-// ETH_PRINT(TRACE_LEVEL_VERBOSE, ETH_SND, "CreateFragList: pMdl=%p, MdlBytesCount=x%x, MdlBufCount=0x%x\n", pMdl, MdlBytesCount, MdlBufCount);\r
-\r
- if (MdlBytesCount > 0)\r
- {\r
- if( buf_len > MdlBytesCount)\r
- {\r
- buf_len -= MdlBytesCount; \r
- }\r
- else\r
- {\r
- MdlBytesCount = buf_len;\r
- buf_len = 0; \r
- } \r
- //\r
- // In some cases the mdlcount is greater than needed and in the last page\r
- // there is 0 bytes\r
- //\r
- for (j=0; ((j< MdlBufCount) && (MdlBytesCount > 0)); j++) \r
- {\r
- ASSERT(MdlBytesCount > 0);\r
- if (j ==0 ) \r
- {\r
- //\r
- // First page\r
- //\r
- ULONG64 ul64PageNum = page_array[j];\r
- pFragList->Elements[i].Address.QuadPart = (ul64PageNum << PAGE_SHIFT)+ offset;\r
- if( offset + MdlBytesCount > PAGE_SIZE )\r
- {\r
- //\r
- // the data slides behind the page boundry\r
- //\r
- ASSERT(PAGE_SIZE > offset);\r
- pFragList->Elements[i].Length = PAGE_SIZE - offset;\r
- MdlBytesCount -= pFragList->Elements[i].Length;\r
- }\r
- else\r
- {\r
- //\r
- // All the data is hold in one page\r
- // \r
- pFragList->Elements[i].Length = MdlBytesCount;\r
- MdlBytesCount = 0;\r
- }\r
-\r
-// 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); \r
- } \r
- else \r
- {\r
- if (page_array[j] == (page_array[j-1] + 1))\r
- {\r
- \r
- ULONG size = min(PAGE_SIZE, MdlBytesCount);\r
- i -= 1;\r
- pFragList->Elements[i].Length += size;\r
- MdlBytesCount -= size;\r
- }\r
- else \r
- {\r
- //\r
- // Not first page. so the data always start at the begining of the page\r
- //\r
- ULONG64 ul64PageNum = page_array[j];\r
- pFragList->Elements[i].Address.QuadPart = (ul64PageNum << PAGE_SHIFT);\r
- pFragList->Elements[i].Length = min(PAGE_SIZE, MdlBytesCount);\r
- MdlBytesCount -= pFragList->Elements[i].Length;\r
- }\r
-\r
-// 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); \r
- } \r
- i++;\r
- ASSERT(i <= MAX_PHYS_BUF_FRAG_ELEMENTS);\r
- }\r
- }\r
-\r
- pMdl = pMdl->Next;\r
- }\r
- \r
- if (buf_len != 0)\r
- {\r
- //\r
- // In some cases the size in MDL isn't equal to the buffer size. In such \r
- // a case we need to add the rest of packet to last chunk\r
- //\r
- ASSERT(i > 0); // To prevent array underflow\r
- pFragList->Elements[i-1].Length += buf_len;\r
-// 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); \r
- }\r
-\r
- ASSERT(i <= PhysBufCount);\r
- pFragList->NumberOfElements = i;\r
-\r
-#ifdef DBG\r
-{\r
- ULONG size = 0;\r
- for (i = 0; i < pFragList->NumberOfElements; ++i)\r
- {\r
- size += pFragList->Elements[i].Length;\r
- }\r
- ASSERT(size == PacketLength);\r
-}\r
-#endif\r
-\r
-// ETH_EXIT(ETH_SND);\r
-}\r
-\r
-\r
-\r
-\r
-void\r
-ipoib_port_send(\r
- IN ipoib_port_t* const p_port,\r
- IN NET_BUFFER_LIST *p_net_buffer_list,\r
- IN ULONG send_flags)\r
-{\r
- NDIS_STATUS status;\r
- PNET_BUFFER p_netbuf;\r
- UINT buf_cnt = 0;\r
- //ipoib_send_desc_t *p_desc;\r
- ULONG send_complete_flags = 0;\r
- KIRQL old_irql;\r
- PVOID p_sgl;\r
- \r
- PERF_DECLARE( GetEthHdr );\r
- PERF_DECLARE( BuildSendDesc );\r
- PERF_DECLARE( QueuePacket );\r
- PERF_DECLARE( SendMgrQueue );\r
- PERF_DECLARE( PostSend );\r
- PERF_DECLARE( ProcessFailedSends );\r
-\r
- IPOIB_ENTER( IPOIB_DBG_SEND );\r
- \r
- if (NDIS_TEST_SEND_AT_DISPATCH_LEVEL(send_flags))\r
- {\r
- //TODO Tzachid: make an assert here to validate your IRQL\r
- //ASSERT (KeGetCurrentIRQL() == DISPATCH_LEVEL);\r
- NDIS_SET_SEND_COMPLETE_FLAG(send_complete_flags, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL);\r
- } else {\r
- //ASSERT (KeGetCurrentIRQL() == PASSIVE_LEVEL);\r
- }\r
- \r
- cl_obj_lock( &p_port->obj );\r
- if( p_port->state != IB_QPS_RTS )\r
- {\r
- \r
- \r
- cl_obj_unlock( &p_port->obj );\r
- \r
- \r
- NET_BUFFER_LIST_STATUS(p_net_buffer_list) = NDIS_STATUS_FAILURE;\r
- NET_BUFFER_LIST_NEXT_NBL(p_net_buffer_list) = NULL;\r
- ipoib_inc_send_stat( p_port->p_adapter, IP_STAT_DROPPED, 0 );\r
- \r
- NdisMSendNetBufferListsComplete(\r
- p_port->p_adapter->h_adapter,\r
- p_net_buffer_list,\r
- send_complete_flags); \r
- \r
- return;\r
- }\r
- cl_obj_unlock( &p_port->obj );\r
- \r
- //IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- // ("Processing netbuffer list: %x\n", p_net_buffer_list));\r
- for (p_netbuf = NET_BUFFER_LIST_FIRST_NB(p_net_buffer_list);\r
- p_netbuf != NULL; \r
- p_netbuf = NET_BUFFER_NEXT_NB(p_netbuf))\r
- {\r
- IPOIB_PORT_FROM_PACKET(p_net_buffer_list) = p_port;\r
- IPOIB_NET_BUFFER_LIST_FROM_NETBUFFER(p_netbuf) = p_net_buffer_list;\r
- IPOIB_FROM_QUEUE(p_netbuf) = NULL;\r
- /*p_desc = &p_port->send_mgr.desc;\r
- p_desc->p_buf = p_netbuf;\r
- p_desc->p_endpt = NULL;\r
- p_desc->p_buf = NULL;\r
- p_desc->send_qp = NULL;\r
- p_desc->num_wrs = 1;\r
- p_desc->send_dir = 0;*/\r
- \r
- old_irql = KeGetCurrentIrql();\r
- if (old_irql < DISPATCH_LEVEL) \r
- {\r
- KeRaiseIrqlToDpcLevel();\r
- }\r
- ++buf_cnt;\r
- //IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- // ("[%d] Netbuf = %x\n",buf_cnt, p_netbuf) );\r
- if (cl_is_item_in_qlist( &p_port->send_mgr.pending_list,\r
- IPOIB_LIST_ITEM_FROM_PACKET( p_net_buffer_list ))) {\r
- p_sgl = IPOIB_FROM_QUEUE(p_netbuf); \r
- //IPOIB_FROM_QUEUE(p_net_buffer) = (void*)1;\r
- ASSERT (p_sgl); \r
- //IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- // ("[%d] FROM_QUEUE Netbuf = %x, found SGL = %x\n",buf_cnt, p_netbuf, p_sgl) );\r
- status = NDIS_STATUS_SUCCESS;\r
- } else {\r
-\r
-//#if 0\r
- CHAR *pTemp = ExAllocatePoolWithTag(NonPagedPool , p_port->p_adapter->sg_list_size, 'abcd');\r
- CL_ASSERT(pTemp != NULL);\r
- status = NDIS_STATUS_SUCCESS;\r
- p_sgl = pTemp;\r
- CreateFragList(NdisQueryNetBufferPhysicalCount(p_netbuf), p_netbuf, NET_BUFFER_DATA_LENGTH(p_netbuf), p_sgl);\r
- IPOIB_FROM_QUEUE(p_netbuf) = NULL;\r
- /*IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("[%d] Allocation from scratch: Netbuf = %x, found SGL = %x, PhysBufCnt=%ld, NB LEN = %ld, sg_list_size=%ld\n",\r
- buf_cnt, p_netbuf, p_sgl,NdisQueryNetBufferPhysicalCount(p_netbuf) ,\r
- NET_BUFFER_DATA_LENGTH(p_netbuf),p_port->p_adapter->sg_list_size) );\r
- */\r
- ipoib_process_sg_list(NULL, NULL, p_sgl, p_netbuf);\r
- status = NDIS_STATUS_SUCCESS;\r
-//#endif\r
-#if 0 \r
- status = NdisMAllocateNetBufferSGList(\r
- p_port->p_adapter->NdisMiniportDmaHandle,\r
- p_netbuf,\r
- p_netbuf,\r
- NDIS_SG_LIST_WRITE_TO_DEVICE,\r
- NULL,\r
- 0);\r
-#endif\r
- }\r
- KeLowerIrql (old_irql);\r
- \r
- if( status != NDIS_STATUS_SUCCESS )\r
- {\r
- /* fail net buffer list */\r
- NET_BUFFER_LIST_NEXT_NBL(p_net_buffer_list) = NULL;\r
- NET_BUFFER_LIST_STATUS(p_net_buffer_list) = NDIS_STATUS_RESOURCES;\r
- NdisMSendNetBufferListsComplete(\r
- p_port->p_adapter->h_adapter,\r
- p_net_buffer_list,\r
- send_complete_flags); \r
- break;\r
- }\r
- ASSERT(buf_cnt);\r
- IPOIB_GET_NET_BUFFER_LIST_REF_COUNT(p_net_buffer_list) = (PVOID)(ULONG_PTR)buf_cnt;\r
- }\r
- \r
- /* Post the WR. *\r
- cl_perf_start( PostSend );\r
- ib_status = p_port->p_adapter->p_ifc->post_send( p_desc->send_qp, &p_desc->send_wr[0].wr, &p_wr_failed );\r
- cl_perf_stop( &p_port->p_adapter->perf, PostSend );\r
- if( ib_status != IB_SUCCESS )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ib_post_send returned %s\n", \r
- p_port->p_adapter->p_ifc->get_err_str( ib_status )) );\r
- cl_perf_start( ProcessFailedSends );\r
- __process_failed_send( p_port, p_desc, NDIS_STATUS_FAILURE );\r
- cl_perf_stop( &p_port->p_adapter->perf, ProcessFailedSends );\r
- * Flag the adapter as hung since posting is busted. *\r
- p_port->p_adapter->hung = TRUE;\r
- continue;\r
- }\r
-\r
- cl_atomic_inc( &p_port->send_mgr.depth );\r
- }\r
- cl_spinlock_release( &p_port->send_lock );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_SEND );*/\r
-}\r
-\r
-\r
-void\r
-ipoib_port_resume(\r
- IN ipoib_port_t* const p_port,\r
- IN boolean_t b_pending )\r
-{\r
- NDIS_STATUS status;\r
- cl_list_item_t *p_item;\r
- NET_BUFFER *p_net_buffer;\r
- NET_BUFFER_LIST *p_net_buffer_list;\r
- //ipoib_send_desc_t *p_desc;\r
- KIRQL old_irql;\r
- UINT buf_cnt = 0;\r
- NET_BUFFER_LIST *p_prev_nbl = NULL;\r
- PVOID p_sgl;\r
- static PVOID p_prev_sgl = NULL;\r
- \r
- PERF_DECLARE( GetEndpt );\r
- PERF_DECLARE( BuildSendDesc );\r
- PERF_DECLARE( ProcessFailedSends );\r
- PERF_DECLARE( PostSend );\r
-\r
- IPOIB_ENTER( IPOIB_DBG_SEND );\r
-\r
- UNUSED_PARAM(b_pending);\r
- \r
- cl_obj_lock( &p_port->obj );\r
- if( p_port->state != IB_QPS_RTS )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_WARNING, IPOIB_DBG_SEND,\r
- ("Invalid state - Aborting.\n") );\r
- cl_obj_unlock( &p_port->obj );\r
- return;\r
- }\r
- cl_obj_unlock( &p_port->obj );\r
-\r
-//TODO NDIS60\r
-////?????????????? cl_spinlock_acquire( &p_port->send_lock );\r
-\r
- for( p_item = cl_qlist_head( &p_port->send_mgr.pending_list );\r
- p_item != cl_qlist_end( &p_port->send_mgr.pending_list );\r
- p_item = cl_qlist_head( &p_port->send_mgr.pending_list ) )\r
- {\r
- \r
- \r
- /* Check the send queue and pend the request if not empty. */\r
- if( p_port->send_mgr.depth == p_port->p_adapter->params.sq_depth )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_SEND,\r
- ("No available WQEs.\n") );\r
- break;\r
- }\r
- \r
- p_net_buffer_list = IPOIB_PACKET_FROM_LIST_ITEM(\r
- cl_qlist_remove_head( &p_port->send_mgr.pending_list ) );\r
- if (p_prev_nbl == p_net_buffer_list) {\r
-// IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- // ("TRYING TO PROCESS ONCE AGAIN, EXITING: %x\n", p_net_buffer_list));\r
- break; //TODO more sophisticated mechanism to avoid starvation\r
- }\r
- old_irql = KeGetCurrentIrql();\r
- if (old_irql < DISPATCH_LEVEL) \r
- {\r
- KeRaiseIrqlToDpcLevel();\r
- }\r
-// IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- // ("Processing netbuffer list from queue: %x\n", (UINT) (PVOID) p_net_buffer_list));\r
- \r
- for( p_net_buffer = NET_BUFFER_LIST_FIRST_NB(p_net_buffer_list);\r
- p_net_buffer != NULL;\r
- p_net_buffer = NET_BUFFER_NEXT_NB(p_net_buffer), buf_cnt++)\r
- {\r
-\r
- \r
- p_sgl = IPOIB_FROM_QUEUE(p_net_buffer); \r
- //IPOIB_FROM_QUEUE(p_net_buffer) = (void*)1;\r
- ASSERT (p_sgl);\r
- IPOIB_PORT_FROM_PACKET(p_net_buffer_list) = p_port;\r
- IPOIB_NET_BUFFER_LIST_FROM_NETBUFFER(p_net_buffer) = p_net_buffer_list;\r
- /*p_desc = &p_port->send_mgr.desc;\r
- p_desc->p_buf = p_net_buffer;\r
- p_desc->p_endpt = NULL;\r
- p_desc->p_buf = NULL;\r
- p_desc->send_qp = NULL;\r
- p_desc->num_wrs = 1;\r
- p_desc->send_dir = 0;*/\r
-\r
-// IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- // ("[%d] Netbuf = %x, p_sgl = %x\n",buf_cnt, p_net_buffer, p_sgl) );\r
- ASSERT(p_sgl);\r
- if (p_sgl != (void*) 1) {\r
- ipoib_process_sg_list(NULL, NULL, p_sgl, p_net_buffer);\r
- status = NDIS_STATUS_SUCCESS;\r
- }\r
- else {\r
- ASSERT(FALSE);\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Getting strange flow\n") );\r
- NdisMFreeNetBufferSGList(\r
- p_port->p_adapter->NdisMiniportDmaHandle,\r
- p_sgl,\r
- p_net_buffer );\r
- status = NdisMAllocateNetBufferSGList(\r
- p_port->p_adapter->NdisMiniportDmaHandle,\r
- p_net_buffer,\r
- p_net_buffer,\r
- NDIS_SG_LIST_WRITE_TO_DEVICE,\r
- NULL,\r
- 0 /*p_port->p_adapter->sg_list_size*/ );\r
- }\r
- p_prev_sgl = p_sgl; \r
- if( status != NDIS_STATUS_SUCCESS )\r
- {\r
- /* fail net buffer list */\r
- NET_BUFFER_LIST_NEXT_NBL(p_net_buffer_list) = NULL;\r
- NET_BUFFER_LIST_STATUS(p_net_buffer_list) = NDIS_STATUS_RESOURCES;\r
- NdisMSendNetBufferListsComplete(\r
- p_port->p_adapter->h_adapter,\r
- p_net_buffer_list,\r
- 0); \r
- break;\r
- }\r
- }\r
- \r
- KeLowerIrql (old_irql);\r
- \r
- \r
- p_prev_nbl = p_net_buffer_list;\r
- \r
- }\r
- IPOIB_EXIT( IPOIB_DBG_SEND );\r
-}\r
-\r
-\r
-\r
-static void\r
-__send_cb(\r
- IN const ib_cq_handle_t h_cq,\r
- IN void *cq_context )\r
-{\r
- ipoib_port_t *p_port;\r
- ib_api_status_t status;\r
- ib_wc_t wc[MAX_SEND_WC], *p_wc, *p_free;\r
- cl_qlist_t done_list;\r
- NET_BUFFER_LIST *p_nbl;\r
- uint32_t length;\r
- ipoib_endpt_t *p_endpt;\r
- send_buf_t *p_send_buf;\r
- ip_stat_sel_t type;\r
- size_t i;\r
- NET_BUFFER *p_netbuffer = NULL;\r
-\r
- PERF_DECLARE( SendCompBundle );\r
- PERF_DECLARE( SendCb );\r
- PERF_DECLARE( PollSend );\r
- PERF_DECLARE( SendComp );\r
- PERF_DECLARE( FreeSendBuf );\r
- PERF_DECLARE( RearmSend );\r
- PERF_DECLARE( PortResume );\r
-//return;//???????????\r
- IPOIB_ENTER( IPOIB_DBG_SEND );\r
-\r
- cl_perf_clr( SendCompBundle );\r
-\r
- cl_perf_start( SendCb );\r
-\r
- UNUSED_PARAM( h_cq );\r
-\r
- cl_qlist_init( &done_list );\r
-\r
- p_port = (ipoib_port_t*)cq_context;\r
-\r
- ipoib_port_ref( p_port, ref_send_cb );\r
-\r
- for( i = 0; i < MAX_SEND_WC; i++ )\r
- wc[i].p_next = &wc[i + 1];\r
- wc[MAX_SEND_WC - 1].p_next = NULL;\r
-\r
- do\r
- {\r
- p_free = wc;\r
- cl_perf_start( PollSend );\r
- status = p_port->p_adapter->p_ifc->poll_cq( p_port->ib_mgr.h_send_cq, &p_free, &p_wc );\r
- cl_perf_stop( &p_port->p_adapter->perf, PollSend );\r
- CL_ASSERT( status == IB_SUCCESS || status == IB_NOT_FOUND );\r
-\r
- while( p_wc )\r
- {\r
- cl_perf_start( SendComp );\r
- CL_ASSERT( p_wc->status != IB_WCS_SUCCESS || p_wc->wc_type == IB_WC_SEND );\r
- p_nbl = (NET_BUFFER_LIST*)(uintn_t)p_wc->wr_id;\r
- //IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_SEND,\r
- //("[1]Successfull send completion for NBL=0x%x .\n", (UINT) (PVOID) p_nbl ));\r
- CL_ASSERT( p_nbl );\r
- CL_ASSERT( IPOIB_PORT_FROM_PACKET( p_nbl ) == p_port );\r
- length = 0;\r
- p_endpt = IPOIB_ENDPT_FROM_PACKET( p_nbl );\r
- p_send_buf = IPOIB_SEND_FROM_NETBUFFER( NET_BUFFER_LIST_FIRST_NB (p_nbl ));\r
- \r
- switch( p_wc->status )\r
- {\r
- case IB_WCS_SUCCESS:\r
- if( p_endpt->h_mcast )\r
- {\r
- if( p_endpt->dgid.multicast.raw_group_id[11] == 0xFF &&\r
- p_endpt->dgid.multicast.raw_group_id[10] == 0xFF &&\r
- p_endpt->dgid.multicast.raw_group_id[12] == 0xFF &&\r
- p_endpt->dgid.multicast.raw_group_id[13] == 0xFF )\r
- {\r
- type = IP_STAT_BCAST_BYTES;\r
- }\r
- else\r
- {\r
- type = IP_STAT_MCAST_BYTES;\r
- }\r
- }\r
- else\r
- {\r
- type = IP_STAT_UCAST_BYTES;\r
- }\r
- for (p_netbuffer = NET_BUFFER_LIST_FIRST_NB(p_nbl);\r
- p_netbuffer != NULL;\r
- p_netbuffer = NET_BUFFER_NEXT_NB(p_netbuffer))\r
- {\r
- length += NET_BUFFER_DATA_LENGTH(p_netbuffer);\r
- } \r
- ipoib_inc_send_stat( p_port->p_adapter, type, length );\r
- // IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_SEND,\r
- //("Successfull send completion for NBL=0x%x .\n", (UINT) (PVOID) p_nbl) );\r
- NET_BUFFER_LIST_STATUS(p_nbl) = NDIS_STATUS_SUCCESS;\r
- IPOIB_DEC_NET_BUFFER_LIST_REF_COUNT(p_nbl);\r
- if (IPOIB_GET_NET_BUFFER_LIST_REF_COUNT(p_nbl) == 0)\r
- NdisMSendNetBufferListsComplete(p_port->p_adapter->h_adapter,\r
- p_nbl,\r
- 0);\r
- break;\r
-\r
- case IB_WCS_WR_FLUSHED_ERR:\r
- IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_SEND,\r
- ("Flushed send completion.\n") );\r
- ipoib_inc_send_stat( p_port->p_adapter, IP_STAT_DROPPED, 0 );\r
- NET_BUFFER_LIST_STATUS(p_nbl) = NDIS_STATUS_RESET_IN_PROGRESS;\r
- NdisMSendNetBufferListsComplete(p_port->p_adapter->h_adapter,\r
- p_nbl,\r
- 0); \r
- break;\r
-\r
- default:\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Send failed with %s (vendor specific %#x)\n",\r
- p_port->p_adapter->p_ifc->get_wc_status_str( p_wc->status ),\r
- (int)p_wc->vendor_specific) );\r
- ipoib_inc_send_stat( p_port->p_adapter, IP_STAT_ERROR, 0 );\r
- NET_BUFFER_LIST_STATUS(p_nbl) = NDIS_STATUS_FAILURE;\r
- NdisMSendNetBufferListsComplete(p_port->p_adapter->h_adapter,\r
- p_nbl,\r
- 0); \r
- break;\r
- }\r
- cl_perf_stop( &p_port->p_adapter->perf, SendComp );\r
- /* Dereference the enpoint used for the transfer. */\r
- ipoib_endpt_deref( p_endpt );\r
-\r
- if( p_send_buf )\r
- {\r
- cl_perf_start( FreeSendBuf );\r
- NdisFreeToNPagedLookasideList( &p_port->buf_mgr.send_buf_list,\r
- p_send_buf );\r
- cl_perf_stop( &p_port->p_adapter->perf, FreeSendBuf );\r
- }\r
-\r
- cl_atomic_dec( &p_port->send_mgr.depth );\r
-\r
- p_wc = p_wc->p_next;\r
- cl_perf_inc( SendCompBundle );\r
- }\r
- /* If we didn't use up every WC, break out. */\r
- } while( !p_free );\r
-\r
- /* Rearm the CQ. */\r
- cl_perf_start( RearmSend );\r
- status = p_port->p_adapter->p_ifc->rearm_cq( p_port->ib_mgr.h_send_cq, FALSE );\r
- cl_perf_stop( &p_port->p_adapter->perf, RearmSend );\r
- CL_ASSERT( status == IB_SUCCESS );\r
-\r
- /* Resume any sends awaiting resources. */\r
- cl_perf_start( PortResume );\r
- ipoib_port_resume( p_port, TRUE );\r
- cl_perf_stop( &p_port->p_adapter->perf, PortResume );\r
- \r
- ipoib_port_deref( p_port, ref_send_cb );\r
-\r
- cl_perf_stop( &p_port->p_adapter->perf, SendCb );\r
- cl_perf_update_ctr( &p_port->p_adapter->perf, SendCompBundle );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_SEND );\r
-}\r
-\r
-\r
-/******************************************************************************\r
-*\r
-* Endpoint manager implementation\r
-*\r
-******************************************************************************/\r
-static void\r
-__endpt_mgr_construct(\r
- IN ipoib_port_t* const p_port )\r
-{\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
- cl_qmap_init( &p_port->endpt_mgr.mac_endpts );\r
- cl_qmap_init( &p_port->endpt_mgr.lid_endpts );\r
- cl_fmap_init( &p_port->endpt_mgr.gid_endpts, __gid_cmp );\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
-}\r
-\r
-static void\r
-__endpt_cm_mgr_thread(\r
-IN void* p_context );\r
-\r
-static ib_api_status_t\r
-__endpt_mgr_init(\r
- IN ipoib_port_t* const p_port )\r
-{\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-#if 0\r
- if( p_port->p_adapter->params.cm_enabled )\r
- {\r
- cl_fmap_init( &p_port->endpt_mgr.conn_endpts, __gid_cmp );\r
- \r
- NdisInitializeListHead( &p_port->endpt_mgr.pending_conns );\r
- NdisAllocateSpinLock( &p_port->endpt_mgr.conn_lock );\r
- cl_event_init( &p_port->endpt_mgr.event, FALSE );\r
- \r
- NdisInitializeListHead( &p_port->endpt_mgr.remove_conns );\r
- NdisAllocateSpinLock( &p_port->endpt_mgr.remove_lock );\r
-\r
- cl_thread_init( &p_port->endpt_mgr.h_thread, \r
- __endpt_cm_mgr_thread,\r
- ( const void *)p_port, \r
- "CmEndPtMgr" );\r
- }\r
-#endif\r
- UNUSED_PARAM(p_port);\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
- return IB_SUCCESS;\r
-}\r
-\r
-static void\r
-__endpt_cm_mgr_thread(\r
-IN void* p_context )\r
-{\r
- ib_api_status_t ib_status;\r
- LIST_ENTRY *p_item;\r
- ipoib_endpt_t *p_endpt;\r
- ipoib_port_t *p_port =( ipoib_port_t *)p_context;\r
- \r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, \r
- ("Starting Port [%d] Endpt CM thread \n", p_port->port_num ) );\r
-\r
- while( !p_port->endpt_mgr.thread_is_done )\r
- {\r
- cl_event_wait_on( &p_port->endpt_mgr.event, EVENT_NO_TIMEOUT, FALSE );\r
- \r
- while( ( p_item = NdisInterlockedRemoveHeadList( \r
- &p_port->endpt_mgr.pending_conns,\r
- &p_port->endpt_mgr.conn_lock) ) != NULL )\r
- {\r
-\r
- p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, list_item );\r
- if( p_port->endpt_mgr.thread_is_done )\r
- {\r
- endpt_cm_set_state( p_endpt, IPOIB_CM_DISCONNECTED );\r
- continue;\r
- }\r
-\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
- ("Endpt[%p] CONNECT REQ to MAC %02x:%02x:%02x:%02x:%02x:%02x\n",\r
- p_endpt,\r
- p_endpt->mac.addr[0], p_endpt->mac.addr[1],\r
- p_endpt->mac.addr[2], p_endpt->mac.addr[3],\r
- p_endpt->mac.addr[4], p_endpt->mac.addr[5] ) );\r
- \r
- if( !p_endpt->conn.h_send_qp )\r
- {\r
- ib_status = endpt_cm_create_qp( p_endpt, &p_endpt->conn.h_send_qp );\r
- if( ib_status != IB_SUCCESS )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Endpt [%p ] CM create QP failed status %#x\n", p_endpt, ib_status ) );\r
- }\r
- else\r
- {\r
- ib_status = ipoib_endpt_connect( p_endpt );\r
- if( ib_status != IB_SUCCESS && ib_status != IB_PENDING )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Endpt [ %p ] conn REQ failed status %#x\n", p_endpt, ib_status ) );\r
- }\r
- }\r
- if( ib_status != IB_SUCCESS && ib_status != IB_PENDING )\r
- {\r
- endpt_cm_set_state( p_endpt, IPOIB_CM_DESTROY );\r
- endpt_cm_flush_recv( p_port, p_endpt );\r
- endpt_cm_set_state( p_endpt, IPOIB_CM_DISCONNECTED );\r
- }\r
- }\r
-\r
- }//while( p_item != NULL )\r
-\r
- while( ( p_item = NdisInterlockedRemoveHeadList(\r
- &p_port->endpt_mgr.remove_conns,\r
- &p_port->endpt_mgr.remove_lock ) ) != NULL )\r
- {\r
- p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, list_item );\r
-\r
- endpt_cm_set_state( p_endpt, IPOIB_CM_DESTROY );\r
-\r
- IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_INIT,\r
- ("\nDESTROYING Endpt[%p] MAC %02x:%02x:%02x:%02x:%02x:%02x\n",\r
- p_endpt,\r
- p_endpt->mac.addr[0], p_endpt->mac.addr[1],\r
- p_endpt->mac.addr[2], p_endpt->mac.addr[3],\r
- p_endpt->mac.addr[4], p_endpt->mac.addr[5] ) );\r
- endpt_cm_flush_recv( p_port, p_endpt );\r
- endpt_cm_set_state( p_endpt, IPOIB_CM_DISCONNECTED );\r
- cl_obj_destroy( &p_endpt->obj );\r
- }\r
- }\r
-\r
- p_port->endpt_mgr.thread_is_done++;\r
- NdisFreeSpinLock( &p_port->endpt_mgr.conn_lock );\r
- \r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, \r
- (" Port [%d] Endpt thread is done\n", p_port->port_num ) );\r
-}\r
-\r
-static void\r
-__endpt_mgr_destroy(\r
- IN ipoib_port_t* const p_port )\r
-{\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
- CL_ASSERT( cl_is_qmap_empty( &p_port->endpt_mgr.mac_endpts ) );\r
- CL_ASSERT( cl_is_qmap_empty( &p_port->endpt_mgr.lid_endpts ) );\r
- CL_ASSERT( cl_is_fmap_empty( &p_port->endpt_mgr.gid_endpts ) );\r
- UNUSED_PARAM(p_port);\r
-#if 0\r
- if( p_port->p_adapter->params.cm_enabled )\r
- {\r
- CL_ASSERT( cl_is_fmap_empty( &p_port->endpt_mgr.conn_endpts ) );\r
- }\r
-#endif\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
-}\r
-\r
-\r
-static void\r
-__endpt_mgr_remove_all(\r
- IN ipoib_port_t* const p_port )\r
-{\r
- IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
- \r
- cl_obj_lock( &p_port->obj );\r
- /* Wait for all readers to complete. */\r
- while( p_port->endpt_rdr )\r
- ;\r
- /*\r
- * We don't need to initiate destruction - this is called only\r
- * from the __port_destroying function, and destruction cascades\r
- * to all child objects. Just clear all the maps.\r
- */\r
- cl_qmap_remove_all( &p_port->endpt_mgr.mac_endpts );\r
- cl_qmap_remove_all( &p_port->endpt_mgr.lid_endpts );\r
- cl_fmap_remove_all( &p_port->endpt_mgr.gid_endpts );\r
- cl_obj_unlock( &p_port->obj );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
-}\r
-\r
-\r
-static void\r
-__endpt_mgr_reset_all(\r
- IN ipoib_port_t* const p_port )\r
-{\r
- cl_map_item_t *p_item;\r
- cl_fmap_item_t *p_fmap_item;\r
- ipoib_endpt_t *p_endpt;\r
- cl_qlist_t mc_list;\r
- cl_qlist_t conn_list;\r
- uint32_t local_exist = 0;\r
- NDIS_LINK_STATE link_state;\r
- NDIS_STATUS_INDICATION status_indication;\r
-\r
-\r
- IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
-\r
- cl_qlist_init( &mc_list );\r
- cl_qlist_init( &conn_list );\r
-//??? cl_obj_lock( &p_port->obj );\r
- /* Wait for all readers to complete. */\r
- while( p_port->endpt_rdr )\r
- ;\r
-\r
-#if 0\r
- __endpt_mgr_remove_all(p_port);\r
-#else\r
- link_state.Header.Revision = NDIS_LINK_STATE_REVISION_1;\r
- link_state.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;\r
- link_state.Header.Size = sizeof(NDIS_LINK_STATE);\r
- link_state.MediaConnectState = MediaConnectStateDisconnected;\r
- link_state.MediaDuplexState = MediaDuplexStateFull;\r
- link_state.XmitLinkSpeed = link_state.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED;\r
-\r
- IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication,\r
- p_port->p_adapter->h_adapter,\r
- NDIS_STATUS_LINK_STATE,\r
- (PVOID)&link_state,\r
- sizeof(link_state));\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, ("Indicate DISCONNECT!\n") );\r
- NdisMIndicateStatusEx(p_port->p_adapter->h_adapter,&status_indication);\r
- \r
- link_state.MediaConnectState = MediaConnectStateConnected;\r
- IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication,\r
- p_port->p_adapter->h_adapter,\r
- NDIS_STATUS_LINK_STATE,\r
- (PVOID)&link_state,\r
- sizeof(link_state));\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, ("Indicate Connect\n") );\r
- NdisMIndicateStatusEx(p_port->p_adapter->h_adapter,&status_indication);\r
-\r
- \r
- // IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
- // ("Link DOWN!\n") );\r
-\r
- if( p_port->p_local_endpt )\r
- {\r
- //TODO: CM RESTORE\r
- //ipoib_port_cancel_listen( p_port, p_port->p_local_endpt );\r
-\r
- cl_fmap_remove_item( &p_port->endpt_mgr.gid_endpts,\r
- &p_port->p_local_endpt->gid_item );\r
- cl_qmap_remove_item( &p_port->endpt_mgr.mac_endpts,\r
- &p_port->p_local_endpt->mac_item );\r
- cl_qmap_remove_item( &p_port->endpt_mgr.lid_endpts,\r
- &p_port->p_local_endpt->lid_item );\r
- \r
- cl_qlist_insert_head(\r
- &mc_list, &p_port->p_local_endpt->mac_item.pool_item.list_item );\r
- local_exist = 1;\r
-\r
- p_port->p_local_endpt = NULL;\r
- }\r
-\r
- p_item = cl_qmap_head( &p_port->endpt_mgr.mac_endpts );\r
- while( p_item != cl_qmap_end( &p_port->endpt_mgr.mac_endpts ) )\r
- {\r
- p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item );\r
- p_item = cl_qmap_next( p_item );\r
- if( p_endpt->h_mcast )\r
- {\r
- /*\r
- * We destroy MC endpoints since they will get recreated\r
- * when the port comes back up and we rejoin the MC groups.\r
- */\r
- cl_qmap_remove_item( &p_port->endpt_mgr.mac_endpts,\r
- &p_endpt->mac_item );\r
- cl_fmap_remove_item( &p_port->endpt_mgr.gid_endpts,\r
- &p_endpt->gid_item );\r
-\r
- cl_qlist_insert_tail(\r
- &mc_list, &p_endpt->mac_item.pool_item.list_item );\r
- }\r
- /* destroy connected endpoints if any */\r
- else if( p_port->p_adapter->params.cm_enabled &&\r
- endpt_cm_get_state( p_endpt ) != IPOIB_CM_DISCONNECTED )\r
- {\r
- p_fmap_item = cl_fmap_get( &p_port->endpt_mgr.conn_endpts, &p_endpt->dgid );\r
- if( p_fmap_item != cl_fmap_end( &p_port->endpt_mgr.conn_endpts ) )\r
- {\r
- cl_fmap_remove_item( &p_port->endpt_mgr.conn_endpts, \r
- &p_endpt->conn_item );\r
- }\r
- cl_qmap_remove_item( &p_port->endpt_mgr.mac_endpts,\r
- &p_endpt->mac_item );\r
- cl_fmap_remove_item( &p_port->endpt_mgr.gid_endpts,\r
- &p_endpt->gid_item );\r
-\r
- cl_qlist_insert_tail(\r
- &conn_list, &p_endpt->mac_item.pool_item.list_item );\r
- }\r
- if( p_endpt->h_av )\r
- {\r
- /* Destroy the AV for all other endpoints. */\r
- p_port->p_adapter->p_ifc->destroy_av( p_endpt->h_av );\r
- p_endpt->h_av = NULL;\r
- }\r
- \r
- if( p_endpt->dlid )\r
- {\r
- cl_qmap_remove_item( &p_port->endpt_mgr.lid_endpts,\r
- &p_endpt->lid_item );\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
- ("<__endptr_mgr_reset_all: setting p_endpt->dlid to 0\n"));\r
- p_endpt->dlid = 0;\r
- }\r
- \r
- }\r
-#endif\r
-//??? cl_obj_unlock( &p_port->obj );\r
-\r
- //TODO CM\r
- /*while( cl_qlist_count( &conn_list ) )\r
- {\r
- endpt_cm_destroy_conn( p_port,\r
- PARENT_STRUCT( cl_qlist_remove_head( &conn_list ),\r
- ipoib_endpt_t, mac_item.pool_item.list_item ) );\r
- }*/\r
-\r
- if(cl_qlist_count( &mc_list ) - local_exist)\r
- {\r
- p_port->mcast_cnt = (uint32_t)cl_qlist_count( &mc_list ) - local_exist;\r
- }\r
- else\r
- {\r
- p_port->mcast_cnt = 0;\r
- KeSetEvent( &p_port->leave_mcast_event, EVENT_INCREMENT, FALSE );\r
- } \r
-\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,("p_port->mcast_cnt = %d\n", p_port->mcast_cnt - local_exist));\r
-\r
- /* Destroy all multicast endpoints now that we have released the lock. */\r
- while( cl_qlist_count( &mc_list ) )\r
- {\r
- cl_list_item_t *p_item;\r
- p_item = cl_qlist_remove_head( &mc_list );\r
- p_endpt = PARENT_STRUCT(p_item, ipoib_endpt_t, mac_item.pool_item.list_item);\r
- cl_obj_destroy( &p_endpt->obj);\r
- }\r
-\r
- IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
-}\r
-\r
-\r
-/*\r
- * Called when updating an endpoint entry in response to an ARP.\r
- * Because receive processing is serialized, and holds a reference\r
- * on the endpoint reader, we wait for all *other* readers to exit before\r
- * removing the item.\r
- */\r
-static void\r
-__endpt_mgr_remove(\r
- IN ipoib_port_t* const p_port,\r
- IN ipoib_endpt_t* const p_endpt )\r
-{\r
-#if 0 //CM\r
- cl_fmap_item_t* p_fmap_item;\r
-#endif \r
- IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
-\r
- /* This function must be called from the receive path */\r
- CL_ASSERT(p_port->endpt_rdr > 0);\r
-\r
- cl_obj_lock( &p_port->obj );\r
- /* Wait for all readers to complete. */ \r
- while( p_port->endpt_rdr > 1 )\r
- ;\r
-\r
- /* Remove the endpoint from the maps so further requests don't find it. */\r
- cl_qmap_remove_item( &p_port->endpt_mgr.mac_endpts, &p_endpt->mac_item );\r
- /*\r
- * The enpoints are *ALWAYS* in both the MAC and GID maps. They are only\r
- * in the LID map if the GID has the same subnet prefix as us.\r
- */\r
- cl_fmap_remove_item( &p_port->endpt_mgr.gid_endpts, &p_endpt->gid_item );\r
-#if 0\r
-\r
- if( p_port->p_adapter->params.cm_enabled )\r
- {\r
- p_fmap_item = cl_fmap_get( &p_port->endpt_mgr.conn_endpts, &p_endpt->dgid );\r
- \r
- if( p_fmap_item != cl_fmap_end( &p_port->endpt_mgr.conn_endpts ) )\r
- {\r
- cl_fmap_remove_item( &p_port->endpt_mgr.conn_endpts, \r
- &p_endpt->conn_item );\r
- }\r
- }\r
-#endif \r
- if( p_endpt->dlid )\r
- {\r
- cl_qmap_remove_item( &p_port->endpt_mgr.lid_endpts,\r
- &p_endpt->lid_item );\r
- }\r
-\r
- cl_obj_unlock( &p_port->obj );\r
-\r
- //TODO CM\r
- //endpt_cm_destroy_conn( p_port, p_endpt );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
-}\r
-\r
-\r
-NTSTATUS\r
-ipoib_mac_to_gid(\r
- IN ipoib_port_t* const p_port,\r
- IN const mac_addr_t mac,\r
- OUT ib_gid_t* p_gid )\r
-{\r
- ipoib_endpt_t* p_endpt;\r
- cl_map_item_t *p_item;\r
- uint64_t key = 0;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
-\r
- cl_memcpy( &key, &mac, sizeof(mac_addr_t) );\r
-\r
- cl_obj_lock( &p_port->obj );\r
-\r
- p_item = cl_qmap_get( &p_port->endpt_mgr.mac_endpts, key );\r
- if( p_item == cl_qmap_end( &p_port->endpt_mgr.mac_endpts ) )\r
- {\r
- cl_obj_unlock( &p_port->obj );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Failed endpoint lookup.\n") );\r
- return STATUS_INVALID_PARAMETER;\r
- }\r
-\r
- p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item );\r
- *p_gid = p_endpt->dgid;\r
-\r
- cl_obj_unlock( &p_port->obj );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
- return STATUS_SUCCESS;\r
-}\r
-\r
-\r
-NTSTATUS\r
-ipoib_mac_to_path(\r
- IN ipoib_port_t* const p_port,\r
- IN const mac_addr_t mac,\r
- OUT ib_path_rec_t* p_path )\r
-{\r
- ipoib_endpt_t* p_endpt;\r
- cl_map_item_t *p_item;\r
- uint64_t key = 0;\r
- uint8_t sl;\r
- net32_t flow_lbl;\r
- uint8_t hop_limit;\r
- uint8_t pkt_life;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
-\r
- cl_memcpy( &key, &mac, sizeof(mac_addr_t) );\r
-\r
- cl_obj_lock( &p_port->obj );\r
-\r
- if( p_port->p_local_endpt == NULL )\r
- {\r
- cl_obj_unlock( &p_port->obj );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("No local endpoint.\n") );\r
- return STATUS_INVALID_PARAMETER;\r
- }\r
-\r
- if( mac.addr[0] == 0 && mac.addr[1] == 0 && mac.addr[2] == 0 &&\r
- mac.addr[3] == 0 && mac.addr[4] == 0 && mac.addr[5] == 0 )\r
- {\r
- p_endpt = p_port->p_local_endpt;\r
- }\r
- else\r
- {\r
- p_item = cl_qmap_get( &p_port->endpt_mgr.mac_endpts, key );\r
- if( p_item == cl_qmap_end( &p_port->endpt_mgr.mac_endpts ) )\r
- {\r
- cl_obj_unlock( &p_port->obj );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Failed endpoint lookup.\n") );\r
- return STATUS_INVALID_PARAMETER;\r
- }\r
-\r
- p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item );\r
- }\r
-\r
- p_path->service_id = 0;\r
- p_path->dgid = p_endpt->dgid;\r
- p_path->sgid = p_port->p_local_endpt->dgid;\r
- p_path->dlid = p_endpt->dlid;\r
- p_path->slid = p_port->p_local_endpt->dlid;\r
-\r
- ib_member_get_sl_flow_hop(\r
- p_port->ib_mgr.bcast_rec.sl_flow_hop,\r
- &sl,\r
- &flow_lbl,\r
- &hop_limit\r
- );\r
- \r
- if( p_path->slid == p_path->dlid )\r
- pkt_life = 0;\r
- else\r
- pkt_life = p_port->ib_mgr.bcast_rec.pkt_life;\r
-\r
- ib_path_rec_init_local(\r
- p_path,\r
- &p_endpt->dgid,\r
- &p_port->p_local_endpt->dgid,\r
- p_endpt->dlid,\r
- p_port->p_local_endpt->dlid,\r
- 1,\r
- p_port->ib_mgr.bcast_rec.pkey,\r
- sl, 0,\r
- IB_PATH_SELECTOR_EXACTLY, p_port->ib_mgr.bcast_rec.mtu,\r
- IB_PATH_SELECTOR_EXACTLY, p_port->ib_mgr.bcast_rec.rate,\r
- IB_PATH_SELECTOR_EXACTLY, pkt_life,\r
- 0 );\r
-\r
- /* Set global routing information. */\r
- ib_path_rec_set_hop_flow_raw( p_path, hop_limit, flow_lbl, FALSE );\r
- p_path->tclass = p_port->ib_mgr.bcast_rec.tclass;\r
- \r
- cl_obj_unlock( &p_port->obj );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
- return STATUS_SUCCESS;\r
-}\r
-\r
-\r
-static inline NDIS_STATUS\r
-__endpt_mgr_ref(\r
- IN ipoib_port_t* const p_port,\r
- IN const mac_addr_t mac,\r
- OUT ipoib_endpt_t** const pp_endpt )\r
-{\r
- NDIS_STATUS status;\r
- cl_map_item_t *p_item;\r
- uint64_t key;\r
-\r
- PERF_DECLARE( EndptQueue );\r
-\r
- IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
-\r
- if( !cl_memcmp( &mac, &p_port->p_adapter->params.conf_mac, sizeof(mac) ) )\r
- {\r
- /* Discard loopback traffic. */\r
- IPOIB_PRINT(TRACE_LEVEL_WARNING, IPOIB_DBG_ENDPT,\r
- ("Discarding loopback traffic\n") );\r
- IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
- return NDIS_STATUS_NO_ROUTE_TO_DESTINATION;\r
- }\r
-\r
- key = 0;\r
- cl_memcpy( &key, &mac, sizeof(mac_addr_t) );\r
-\r
- cl_obj_lock( &p_port->obj );\r
-\r
- IPOIB_PRINT( TRACE_LEVEL_VERBOSE, IPOIB_DBG_ENDPT,\r
- ("Look for :\t MAC: %02X-%02X-%02X-%02X-%02X-%02X\n",\r
- mac.addr[0], mac.addr[1], mac.addr[2],\r
- mac.addr[3], mac.addr[4], mac.addr[5]) );\r
-\r
- p_item = cl_qmap_get( &p_port->endpt_mgr.mac_endpts, key );\r
- if( p_item == cl_qmap_end( &p_port->endpt_mgr.mac_endpts ) )\r
- {\r
- cl_obj_unlock( &p_port->obj );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
- ("Failed endpoint lookup.\n") );\r
- return NDIS_STATUS_NO_ROUTE_TO_DESTINATION;\r
- }\r
-\r
- *pp_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item );\r
- ipoib_endpt_ref( *pp_endpt );\r
-\r
- cl_obj_unlock( &p_port->obj );\r
-\r
- cl_perf_start( EndptQueue );\r
- status = ipoib_endpt_queue( *pp_endpt );\r
- cl_perf_stop( &p_port->p_adapter->perf, EndptQueue );\r
- if( status != NDIS_STATUS_SUCCESS )\r
- *pp_endpt = NULL;\r
-\r
- IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
- return status;\r
-}\r
-\r
-\r
-static inline NDIS_STATUS\r
-__endpt_mgr_get_gid_qpn(\r
- IN ipoib_port_t* const p_port,\r
- IN const mac_addr_t mac,\r
- OUT ib_gid_t* const p_gid,\r
- OUT UNALIGNED net32_t* const p_qpn )\r
-{\r
- UNALIGNED\r
- cl_map_item_t *p_item;\r
- ipoib_endpt_t *p_endpt;\r
- uint64_t key;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
-\r
- cl_obj_lock( &p_port->obj );\r
-\r
- key = 0;\r
- cl_memcpy( &key, &mac, sizeof(mac_addr_t) );\r
- p_item = cl_qmap_get( &p_port->endpt_mgr.mac_endpts, key );\r
- if( p_item == cl_qmap_end( &p_port->endpt_mgr.mac_endpts ) )\r
- {\r
- cl_obj_unlock( &p_port->obj );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
- ("Failed endpoint lookup.\n") );\r
- return NDIS_STATUS_FAILURE;\r
- }\r
-\r
- p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item );\r
-\r
- *p_gid = p_endpt->dgid;\r
- *p_qpn = p_endpt->qpn;\r
-\r
- cl_obj_unlock( &p_port->obj );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
- return NDIS_STATUS_SUCCESS;\r
-}\r
-\r
-\r
-static inline ipoib_endpt_t*\r
-__endpt_mgr_get_by_gid(\r
- IN ipoib_port_t* const p_port,\r
- IN const ib_gid_t* const p_gid )\r
-{\r
- cl_fmap_item_t *p_item;\r
- ipoib_endpt_t *p_endpt;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
-\r
- p_item = cl_fmap_get( &p_port->endpt_mgr.gid_endpts, p_gid );\r
- if( p_item == cl_fmap_end( &p_port->endpt_mgr.gid_endpts ) )\r
- p_endpt = NULL;\r
- else\r
- p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, gid_item );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
- return p_endpt;\r
-}\r
-\r
-\r
-static ipoib_endpt_t*\r
-__endpt_mgr_get_by_lid(\r
- IN ipoib_port_t* const p_port,\r
- IN const net16_t lid )\r
-{\r
- cl_map_item_t *p_item;\r
- ipoib_endpt_t *p_endpt;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
-\r
- p_item = cl_qmap_get( &p_port->endpt_mgr.lid_endpts, lid );\r
- if( p_item == cl_qmap_end( &p_port->endpt_mgr.lid_endpts ) )\r
- p_endpt = NULL;\r
- else\r
- p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, lid_item );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
- return p_endpt;\r
-}\r
-\r
-\r
-inline ib_api_status_t\r
-__endpt_mgr_insert_locked(\r
- IN ipoib_port_t* const p_port,\r
- IN const mac_addr_t mac,\r
- IN ipoib_endpt_t* const p_endpt )\r
-{\r
- ib_api_status_t status;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
-\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
- ("insert :\t MAC: %02X-%02X-%02X-%02X-%02X-%02X\n",\r
- mac.addr[0], mac.addr[1], mac.addr[2],\r
- mac.addr[3], mac.addr[4], mac.addr[5]) );\r
-\r
- cl_obj_lock( &p_port->obj );\r
- while( p_port->endpt_rdr )\r
- {\r
- cl_obj_unlock( &p_port->obj );\r
- cl_obj_lock( &p_port->obj );\r
- }\r
- /* __endpt_mgr_insert expects *one* reference to be held when being called. */\r
- cl_atomic_inc( &p_port->endpt_rdr );\r
- status= __endpt_mgr_insert( p_port, mac, p_endpt );\r
- cl_atomic_dec( &p_port->endpt_rdr );\r
- cl_obj_unlock( &p_port->obj );\r
-\r
- return status;\r
-}\r
-\r
-\r
-inline ib_api_status_t\r
-__endpt_mgr_insert(\r
- IN ipoib_port_t* const p_port,\r
- IN const mac_addr_t mac,\r
- IN ipoib_endpt_t* const p_endpt )\r
-{\r
- uint64_t key;\r
- cl_status_t cl_status;\r
- cl_map_item_t *p_qitem;\r
- cl_fmap_item_t *p_fitem;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
-\r
- /* Wait for all accesses to the map to complete. */\r
- while( p_port->endpt_rdr > 1 )\r
- ;\r
-\r
- /* Link the endpoint to the port. */\r
- cl_status = cl_obj_insert_rel_parent_locked(\r
- &p_endpt->rel, &p_port->obj, &p_endpt->obj );\r
-\r
- if( cl_status != CL_SUCCESS )\r
- {\r
- cl_obj_destroy( &p_endpt->obj );\r
- return IB_INVALID_STATE;\r
- }\r
-\r
-#if DBG\r
- cl_atomic_inc( &p_port->ref[ref_endpt_track] );\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OBJ,\r
- ("ref type %d ref_cnt %d\n", ref_endpt_track, p_port->obj.ref_cnt) );\r
-#endif\r
-\r
- p_endpt->mac = mac;\r
- key = 0;\r
- cl_memcpy( &key, &mac, sizeof(mac_addr_t) );\r
- p_qitem = cl_qmap_insert(\r
- &p_port->endpt_mgr.mac_endpts, key, &p_endpt->mac_item );\r
- CL_ASSERT( p_qitem == &p_endpt->mac_item );\r
- p_fitem = cl_fmap_insert(\r
- &p_port->endpt_mgr.gid_endpts, &p_endpt->dgid, &p_endpt->gid_item );\r
- CL_ASSERT( p_fitem == &p_endpt->gid_item );\r
- if( p_endpt->dlid )\r
- {\r
- p_qitem = cl_qmap_insert(\r
- &p_port->endpt_mgr.lid_endpts, p_endpt->dlid, &p_endpt->lid_item );\r
- CL_ASSERT( p_qitem == &p_endpt->lid_item );\r
- if (p_qitem != &p_endpt->lid_item) {\r
- // Since we failed to insert into the list, make sure it is not removed\r
- p_endpt->dlid =0;\r
- }\r
- }\r
-\r
- IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
- return IB_SUCCESS;\r
-}\r
-\r
-\r
-static ib_api_status_t\r
-__endpt_mgr_add_bcast(\r
- IN ipoib_port_t* const p_port,\r
- IN ib_mcast_rec_t *p_mcast_rec )\r
-{\r
- ib_api_status_t status;\r
- ipoib_endpt_t *p_endpt;\r
- mac_addr_t bcast_mac;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-\r
- /*\r
- * Cache the broadcast group properties for creating future mcast groups.\r
- */\r
- p_port->ib_mgr.bcast_rec = *p_mcast_rec->p_member_rec;\r
-\r
- /* Allocate the broadcast endpoint. */\r
- p_endpt = ipoib_endpt_create( &p_mcast_rec->p_member_rec->mgid,\r
- 0 , CL_HTON32(0x00FFFFFF) );\r
- if( !p_endpt )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ipoib_endpt_create failed.\n") );\r
- return IB_INSUFFICIENT_RESOURCES;\r
- }\r
- /* set reference to transport to be used while is not attached to the port */\r
- p_endpt->is_mcast_listener = TRUE;\r
- p_endpt->p_ifc = p_port->p_adapter->p_ifc;\r
- status = ipoib_endpt_set_mcast( p_endpt, p_port->ib_mgr.h_pd,\r
- p_port->port_num, p_mcast_rec );\r
- if( status != IB_SUCCESS )\r
- {\r
- cl_obj_destroy( &p_endpt->obj );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ipoib_create_mcast_endpt returned %s\n",\r
- p_port->p_adapter->p_ifc->get_err_str( status )) );\r
- return status;\r
- }\r
-\r
- /* Add the broadcast endpoint to the endpoint map. */\r
- cl_memset( &bcast_mac, 0xFF, sizeof(bcast_mac) );\r
- status = __endpt_mgr_insert_locked( p_port, bcast_mac, p_endpt );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
- return status;\r
-}\r
-\r
-\r
-void\r
-ipoib_port_remove_endpt(\r
- IN ipoib_port_t* const p_port,\r
- IN const mac_addr_t mac )\r
-{\r
- cl_map_item_t *p_item;\r
- //TODO CM\r
-// cl_fmap_item_t *p_fmap_item;\r
- ipoib_endpt_t *p_endpt;\r
- uint64_t key;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
-\r
- key = 0;\r
- cl_memcpy( &key, &mac, sizeof(mac_addr_t) );\r
-\r
- /* Remove the endpoint from the maps so further requests don't find it. */\r
- cl_obj_lock( &p_port->obj );\r
- /* Wait for all readers to finish */\r
- while( p_port->endpt_rdr )\r
- ;\r
- p_item = cl_qmap_remove( &p_port->endpt_mgr.mac_endpts, key );\r
- /*\r
- * Dereference the endpoint. If the ref count goes to zero, it\r
- * will get freed.\r
- */\r
- if( p_item != cl_qmap_end( &p_port->endpt_mgr.mac_endpts ) )\r
- {\r
- p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item );\r
- /*\r
- * The enpoints are *ALWAYS* in both the MAC and GID maps. They are only\r
- * in the LID map if the GID has the same subnet prefix as us.\r
- */\r
- cl_fmap_remove_item(\r
- &p_port->endpt_mgr.gid_endpts, &p_endpt->gid_item );\r
-#if 0\r
- if( p_port->p_adapter->params.cm_enabled )\r
- {\r
- p_fmap_item = cl_fmap_get( &p_port->endpt_mgr.conn_endpts, &p_endpt->dgid );\r
- \r
- if( p_fmap_item != cl_fmap_end( &p_port->endpt_mgr.conn_endpts ) )\r
- {\r
- cl_fmap_remove_item( &p_port->endpt_mgr.conn_endpts, \r
- &p_endpt->conn_item );\r
- }\r
- }\r
-#endif\r
-\r
- if( p_endpt->dlid )\r
- {\r
- cl_qmap_remove_item(\r
- &p_port->endpt_mgr.lid_endpts, &p_endpt->lid_item );\r
- }\r
-\r
- cl_obj_unlock( &p_port->obj );\r
- //TODO CM\r
- //endpt_cm_destroy_conn( p_port, p_endpt );\r
-\r
-#if DBG\r
- cl_atomic_dec( &p_port->ref[ref_endpt_track] );\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
- ("ref type %d ref_cnt %d\n", ref_endpt_track, p_port->obj.ref_cnt) );\r
-#endif\r
-\r
- }\r
- else\r
- {\r
- cl_obj_unlock( &p_port->obj );\r
- }\r
-\r
- IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
-}\r
-\r
-/*\r
- * The sequence for port up is as follows:\r
- * 1. The port goes active. This allows the adapter to send SA queries\r
- * and join the broadcast group (and other groups).\r
- *\r
- * 2. The adapter sends an SA query for the broadcast group.\r
- *\r
- * 3. Upon completion of the query, the adapter joins the broadcast group.\r
- */\r
-\r
-\r
-/*\r
- * Query the SA for the broadcast group.\r
- */\r
-void\r
-ipoib_port_up(\r
- IN ipoib_port_t* const p_port,\r
- IN const ib_pnp_port_rec_t* const p_pnp_rec )\r
-{\r
- ib_port_info_t *p_port_info;\r
- ib_mad_t *mad_in = NULL;\r
- ib_mad_t *mad_out = NULL;\r
- ib_api_status_t status = IB_INSUFFICIENT_MEMORY;\r
- static int cnt = 0;\r
- \r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_INIT,\r
- ("[%d] Entering port_up.\n", ++cnt) ); \r
- \r
- cl_obj_lock( &p_port->obj );\r
- if ( p_port->state == IB_QPS_INIT ) \r
- {\r
- cl_obj_unlock( &p_port->obj );\r
- status = IB_SUCCESS;\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
- ("p_port->state = %d - Aborting.\n", p_port->state) ); \r
- goto up_done;\r
- }\r
- else if ( p_port->state == IB_QPS_RTS )\r
- {\r
- cl_obj_unlock( &p_port->obj );\r
- cl_obj_lock( &p_port->p_adapter->obj );\r
- if( p_port->p_adapter->state == IB_PNP_PORT_INIT )\r
- {\r
- p_port->p_adapter->state = IB_PNP_PORT_ACTIVE;\r
- }\r
- cl_obj_unlock( &p_port->p_adapter->obj );\r
- status = IB_SUCCESS;\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
- ("Port init is done. p_port->state = %d.\n", p_port->state ) );\r
- goto up_done;\r
- }\r
- p_port->state = IB_QPS_INIT;\r
- cl_obj_unlock( &p_port->obj ); \r
-\r
-\r
- /* Wait for all work requests to get flushed. */\r
- while( p_port->recv_mgr.depth || p_port->send_mgr.depth )\r
- cl_thread_suspend( 0 );\r
-\r
- KeResetEvent( &p_port->sa_event );\r
-\r
- mad_out = (ib_mad_t*)cl_zalloc(256);\r
- if(! mad_out)\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("failed to allocate mad mad_out\n")); \r
- goto up_done;\r
- }\r
- mad_in = (ib_mad_t*)cl_zalloc(256);\r
- if(! mad_in)\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("failed to allocate mad mad_in\n")); \r
- goto up_done;\r
- }\r
-\r
- mad_in->attr_id = IB_MAD_ATTR_PORT_INFO;\r
- mad_in->method = IB_MAD_METHOD_GET;\r
- mad_in->base_ver = 1;\r
- mad_in->class_ver =1;\r
- mad_in->mgmt_class = IB_MCLASS_SUBN_LID;\r
- \r
- status = p_port->p_adapter->p_ifc->local_mad(\r
- p_port->ib_mgr.h_ca ,p_port->port_num ,mad_in ,mad_out);\r
-\r
- if( status != IB_SUCCESS )\r
- {\r
- ipoib_set_inactive( p_port->p_adapter );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ib_local_mad returned %s\n", \r
- p_port->p_adapter->p_ifc->get_err_str( status )) );\r
- goto up_done;\r
- }\r
-\r
- p_port_info = (ib_port_info_t*)(((ib_smp_t*)mad_out)->data);\r
- p_port->base_lid = p_pnp_rec->p_port_attr->lid;\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
- ("Received port info: link width = %d.\n",\r
- p_port_info->link_width_active) );\r
- p_port->ib_mgr.rate =\r
- ib_port_info_compute_rate( p_port_info );\r
- \r
- ipoib_set_rate( p_port->p_adapter,\r
- p_port_info->link_width_active,\r
- ib_port_info_get_link_speed_active( p_port_info ) );\r
-\r
- status = __port_get_bcast( p_port );\r
- if (status != IB_SUCCESS)\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- (" __port_get_bcast returned %s\n",p_port->p_adapter->p_ifc->get_err_str( status )));\r
-\r
-up_done:\r
- if( status != IB_SUCCESS )\r
- {\r
- if( status != IB_CANCELED )\r
- {\r
- ipoib_set_inactive( p_port->p_adapter );\r
- __endpt_mgr_reset_all( p_port );\r
- }\r
- ASSERT(p_port->state == IB_QPS_INIT || p_port->state == IB_QPS_ERROR);\r
- p_port->state = IB_QPS_ERROR;\r
- KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE );\r
- }\r
-\r
- if(mad_out)\r
- cl_free(mad_out);\r
- if(mad_in)\r
- cl_free(mad_in);\r
-\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
-}\r
-\r
-\r
-static ib_api_status_t\r
-__endpt_mgr_add_local(\r
- IN ipoib_port_t* const p_port,\r
- IN ib_port_info_t* const p_port_info )\r
-{\r
- ib_api_status_t status;\r
- ib_gid_t gid;\r
- ipoib_endpt_t *p_endpt;\r
- ib_av_attr_t av_attr;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-\r
- ib_gid_set_default( &gid, p_port->p_adapter->guids.port_guid.guid );\r
- p_endpt = ipoib_endpt_create(\r
- &gid, p_port_info->base_lid, p_port->ib_mgr.qpn );\r
- if( !p_endpt )\r
- {\r
- p_port->p_adapter->hung = TRUE;\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Failed to create local endpt\n") );\r
- return IB_INSUFFICIENT_MEMORY;\r
- }\r
-\r
- cl_memclr( &av_attr, sizeof(ib_av_attr_t) );\r
- av_attr.port_num = p_port->port_num;\r
- av_attr.sl = 0;\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
- (" av_attr.dlid = p_port_info->base_lid = %d\n", cl_ntoh16( p_port_info->base_lid ) ));\r
- av_attr.dlid = p_port_info->base_lid;\r
- av_attr.static_rate = p_port->ib_mgr.rate;\r
- av_attr.path_bits = 0;\r
- status = p_port->p_adapter->p_ifc->create_av(\r
- p_port->ib_mgr.h_pd, &av_attr, &p_endpt->h_av );\r
- if( status != IB_SUCCESS )\r
- {\r
- cl_obj_destroy( &p_endpt->obj );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ib_create_av for local endpoint returned %s\n",\r
- p_port->p_adapter->p_ifc->get_err_str( status )) );\r
- return status;\r
- }\r
-\r
- /* __endpt_mgr_insert expects *one* reference to be held. */\r
- cl_atomic_inc( &p_port->endpt_rdr );\r
- status = __endpt_mgr_insert( p_port, p_port->p_adapter->params.conf_mac, p_endpt );\r
- cl_atomic_dec( &p_port->endpt_rdr );\r
- if( status != IB_SUCCESS )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("__endpt_mgr_insert for local endpoint returned %s\n",\r
- p_port->p_adapter->p_ifc->get_err_str( status )) );\r
- return status;\r
- }\r
-\r
- p_port->p_local_endpt = p_endpt;\r
-\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
- return status;\r
-}\r
-\r
-\r
-\r
-\r
-static ib_api_status_t\r
-__port_get_bcast(\r
- IN ipoib_port_t* const p_port )\r
-{\r
- ib_api_status_t status;\r
- ib_query_req_t query;\r
- ib_user_query_t info;\r
- ib_member_rec_t member_rec;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-\r
- info.method = IB_MAD_METHOD_GETTABLE;\r
- info.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD;\r
- info.attr_size = sizeof(ib_member_rec_t);\r
- info.comp_mask = IB_MCR_COMPMASK_MGID;\r
- info.p_attr = &member_rec;\r
-\r
- /* Query requires only the MGID. */\r
- cl_memclr( &member_rec, sizeof(ib_member_rec_t) );\r
- member_rec.mgid = bcast_mgid_template;\r
-\r
- member_rec.mgid.raw[4] = (uint8_t) (p_port->p_adapter->guids.port_guid.pkey >> 8) ;\r
- member_rec.mgid.raw[5] = (uint8_t) p_port->p_adapter->guids.port_guid.pkey;\r
- member_rec.pkey = cl_hton16(p_port->p_adapter->guids.port_guid.pkey);\r
- cl_memclr( &query, sizeof(ib_query_req_t) );\r
- query.query_type = IB_QUERY_USER_DEFINED;\r
- query.p_query_input = &info;\r
- query.port_guid = p_port->p_adapter->guids.port_guid.guid;\r
- query.timeout_ms = p_port->p_adapter->params.sa_timeout;\r
- query.retry_cnt = p_port->p_adapter->params.sa_retry_cnt;\r
- query.query_context = p_port;\r
- query.pfn_query_cb = __bcast_get_cb;\r
-\r
- /* reference the object for the multicast query. */\r
- ipoib_port_ref( p_port, ref_get_bcast );\r
-\r
- status = p_port->p_adapter->p_ifc->query(\r
- p_port->p_adapter->h_al, &query, &p_port->ib_mgr.h_query );\r
- if( status != IB_SUCCESS )\r
- {\r
- ipoib_port_deref( p_port, ref_get_bcast );\r
- ASSERT(FALSE);\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ib_query returned %s\n", \r
- p_port->p_adapter->p_ifc->get_err_str( status )) );\r
- }\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ib_query returned SUCCESS\n"));\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
- return status;\r
-}\r
-\r
-\r
-/* Callback for the MCMemberRecord Get query for the IPv4 broadcast group. */\r
-static void\r
-__bcast_get_cb(\r
- IN ib_query_rec_t *p_query_rec )\r
-{\r
- ipoib_port_t *p_port;\r
- ib_member_rec_t *p_mc_req;\r
- ib_api_status_t status;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-\r
- p_port = (ipoib_port_t*)p_query_rec->query_context;\r
-\r
- cl_obj_lock( &p_port->obj );\r
- p_port->ib_mgr.h_query = NULL;\r
-\r
- CL_ASSERT(p_port->state == IB_QPS_INIT || p_port->state == IB_QPS_ERROR);\r
- if( p_port->state != IB_QPS_INIT )\r
- {\r
- status = IB_CANCELED;\r
- goto done;\r
- }\r
- \r
- status = p_query_rec->status;\r
-\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
- ("status of request %s\n", \r
- p_port->p_adapter->p_ifc->get_err_str( status )) );\r
-\r
- switch( status )\r
- {\r
- case IB_SUCCESS:\r
- if( p_query_rec->result_cnt )\r
- {\r
- p_mc_req = (ib_member_rec_t*)\r
- ib_get_query_result( p_query_rec->p_result_mad, 0 );\r
-\r
- /* Join the broadcast group. */\r
- status = __port_join_bcast( p_port, p_mc_req );\r
- break;\r
- }\r
- /* Fall through. */\r
-\r
- case IB_REMOTE_ERROR:\r
- /* SA failed the query. Broadcast group doesn't exist, create it. */\r
- status = __port_create_bcast( p_port );\r
- break;\r
-\r
- case IB_CANCELED:\r
- IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
- ("Instance destroying - Aborting.\n") );\r
- break;\r
-\r
- default:\r
- NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
- EVENT_IPOIB_BCAST_GET, 1, p_query_rec->status );\r
- }\r
-done:\r
- cl_obj_unlock( &p_port->obj );\r
-\r
- if( status != IB_SUCCESS )\r
- {\r
- if( status != IB_CANCELED )\r
- {\r
- ipoib_set_inactive( p_port->p_adapter );\r
- __endpt_mgr_reset_all( p_port );\r
- }\r
- p_port->state = IB_QPS_ERROR;\r
- KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE );\r
- }\r
-\r
- /* Return the response MAD to AL. */\r
- if( p_query_rec->p_result_mad )\r
- p_port->p_adapter->p_ifc->put_mad( p_query_rec->p_result_mad );\r
-\r
- /* Release the reference taken when issuing the member record query. */\r
- ipoib_port_deref( p_port, ref_bcast_get_cb );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
-}\r
-\r
-\r
-static ib_api_status_t\r
-__port_join_bcast(\r
- IN ipoib_port_t* const p_port,\r
- IN ib_member_rec_t* const p_member_rec )\r
-{\r
- ib_api_status_t status;\r
- ib_mcast_req_t mcast_req;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-\r
- /* Check that the rate is realizable for our port. */\r
- if( p_port->ib_mgr.rate < (p_member_rec->rate & 0x3F) &&\r
- (g_ipoib.bypass_check_bcast_rate == 0))\r
- {\r
- /*\r
- * The MC group rate is higher than our port's rate. Log an error\r
- * and stop. A port transition will drive the retry.\r
- */\r
- IPOIB_PRINT(TRACE_LEVEL_WARNING, IPOIB_DBG_INIT,\r
- ("Unrealizable join due to rate mismatch.\n") );\r
- NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
- EVENT_IPOIB_BCAST_RATE, 2,\r
- (uint32_t)(p_member_rec->rate & 0x3F),\r
- (uint32_t)p_port->ib_mgr.rate );\r
- return IB_ERROR;\r
- }\r
-\r
- /* Join the broadcast group. */\r
- cl_memclr( &mcast_req, sizeof(mcast_req) );\r
- /* Copy the results of the Get to use as parameters. */\r
- mcast_req.member_rec = *p_member_rec;\r
- /* We specify our port GID for the join operation. */\r
- mcast_req.member_rec.port_gid.unicast.prefix = IB_DEFAULT_SUBNET_PREFIX;\r
- mcast_req.member_rec.port_gid.unicast.interface_id =\r
- p_port->p_adapter->guids.port_guid.guid;\r
-\r
- mcast_req.mcast_context = p_port;\r
- mcast_req.pfn_mcast_cb = __bcast_cb;\r
- mcast_req.timeout_ms = p_port->p_adapter->params.sa_timeout;\r
- mcast_req.retry_cnt = p_port->p_adapter->params.sa_retry_cnt;\r
- mcast_req.port_guid = p_port->p_adapter->guids.port_guid.guid;\r
- mcast_req.pkey_index = p_port->pkey_index;\r
-\r
- if( ib_member_get_state( mcast_req.member_rec.scope_state ) !=\r
- IB_MC_REC_STATE_FULL_MEMBER )\r
- {\r
- IPOIB_PRINT(TRACE_LEVEL_WARNING, IPOIB_DBG_INIT,\r
- ("Incorrect MC member rec join state in query response.\n") );\r
- ib_member_set_state( &mcast_req.member_rec.scope_state,\r
- IB_MC_REC_STATE_FULL_MEMBER );\r
- }\r
-\r
- /* reference the object for the multicast join request. */\r
- ipoib_port_ref( p_port, ref_join_bcast );\r
-\r
- status = p_port->p_adapter->p_ifc->join_mcast(\r
- p_port->ib_mgr.h_qp, &mcast_req );\r
- if( status != IB_SUCCESS )\r
- {\r
- ipoib_port_deref( p_port, ref_bcast_join_failed );\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ib_join_mcast returned %s\n", \r
- p_port->p_adapter->p_ifc->get_err_str( status )) );\r
- }\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
- return status;\r
-}\r
-\r
-\r
-static ib_api_status_t\r
-__port_create_bcast(\r
- IN ipoib_port_t* const p_port )\r
-{\r
- ib_api_status_t status;\r
- ib_mcast_req_t mcast_req;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-\r
- /* Join the broadcast group. */\r
- cl_memclr( &mcast_req, sizeof(mcast_req) );\r
- mcast_req.create = TRUE;\r
- /*\r
- * Create requires pkey, qkey, SL, flow label, traffic class, joing state\r
- * and port GID.\r
- *\r
- * We specify the MGID since we don't want the SA to generate it for us.\r
- */\r
- mcast_req.member_rec.mgid = bcast_mgid_template;\r
- mcast_req.member_rec.mgid.raw[4] = (uint8_t) (p_port->p_adapter->guids.port_guid.pkey >> 8); \r
- mcast_req.member_rec.mgid.raw[5] = (uint8_t) p_port->p_adapter->guids.port_guid.pkey;\r
- ib_gid_set_default( &mcast_req.member_rec.port_gid,\r
- p_port->p_adapter->guids.port_guid.guid );\r
- /*\r
- * IPOIB spec requires that the QKEY have the MSb set so that the QKEY\r
- * from the QP is used rather than the QKEY in the send WR.\r
- */\r
- mcast_req.member_rec.qkey =\r
- (uint32_t)(uintn_t)p_port | IB_QP_PRIVILEGED_Q_KEY;\r
- mcast_req.member_rec.mtu =\r
- (IB_PATH_SELECTOR_EXACTLY << 6) | IB_MTU_LEN_2048;\r
-\r
- mcast_req.member_rec.pkey = cl_hton16(p_port->p_adapter->guids.port_guid.pkey);\r
-\r
- mcast_req.member_rec.sl_flow_hop = ib_member_set_sl_flow_hop( 0, 0, 0 );\r
- mcast_req.member_rec.scope_state =\r
- ib_member_set_scope_state( 2, IB_MC_REC_STATE_FULL_MEMBER );\r
-\r
- mcast_req.mcast_context = p_port;\r
- mcast_req.pfn_mcast_cb = __bcast_cb;\r
- mcast_req.timeout_ms = p_port->p_adapter->params.sa_timeout;\r
- mcast_req.retry_cnt = p_port->p_adapter->params.sa_retry_cnt;\r
- mcast_req.port_guid = p_port->p_adapter->guids.port_guid.guid;\r
- mcast_req.pkey_index = p_port->pkey_index;\r
-\r
- /* reference the object for the multicast join request. */\r
- ipoib_port_ref( p_port, ref_join_bcast );\r
-\r
- status = p_port->p_adapter->p_ifc->join_mcast( p_port->ib_mgr.h_qp, &mcast_req );\r
- if( status != IB_SUCCESS )\r
- {\r
- ipoib_port_deref( p_port, ref_bcast_create_failed );\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ib_join_mcast returned %s\n", \r
- p_port->p_adapter->p_ifc->get_err_str( status )) );\r
- }\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
- return status;\r
-}\r
-\r
-\r
-void\r
-ipoib_port_down(\r
- IN ipoib_port_t* const p_port )\r
-{\r
- ib_api_status_t status;\r
- ib_qp_mod_t qp_mod;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-\r
- /*\r
- * Mark our state. This causes all callbacks to abort.\r
- * Note that we hold the receive lock so that we synchronize\r
- * with reposting. We must take the receive lock before the\r
- * object lock since that is the order taken when reposting.\r
- */\r
- cl_spinlock_acquire( &p_port->recv_lock );\r
- cl_obj_lock( &p_port->obj );\r
- p_port->state = IB_QPS_ERROR;\r
-\r
- NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
- EVENT_IPOIB_PORT_DOWN, 0 );\r
-\r
- if( p_port->ib_mgr.h_query )\r
- {\r
- p_port->p_adapter->p_ifc->cancel_query(\r
- p_port->p_adapter->h_al, p_port->ib_mgr.h_query );\r
- p_port->ib_mgr.h_query = NULL;\r
- }\r
- cl_obj_unlock( &p_port->obj );\r
- cl_spinlock_release( &p_port->recv_lock );\r
-\r
- KeWaitForSingleObject(\r
- &p_port->sa_event, Executive, KernelMode, FALSE, NULL );\r
-\r
- /* garbage collector timer is not needed when link is down */\r
- KeCancelTimer(&p_port->gc_timer);\r
- KeFlushQueuedDpcs();\r
-\r
- /*\r
- * Put the QP in the error state. This removes the need to\r
- * synchronize with send/receive callbacks.\r
- */\r
- CL_ASSERT( p_port->ib_mgr.h_qp );\r
- cl_memclr( &qp_mod, sizeof(ib_qp_mod_t) );\r
- qp_mod.req_state = IB_QPS_ERROR;\r
- status = p_port->p_adapter->p_ifc->modify_qp( p_port->ib_mgr.h_qp, &qp_mod );\r
- if( status != IB_SUCCESS )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ib_modify_qp to error state returned %s.\n",\r
- p_port->p_adapter->p_ifc->get_err_str( status )) );\r
- p_port->p_adapter->hung = TRUE;\r
- return;\r
- }\r
-\r
- KeResetEvent(&p_port->leave_mcast_event);\r
-\r
- /* Reset all endpoints so we don't flush our ARP cache. */\r
- __endpt_mgr_reset_all( p_port );\r
-\r
- KeWaitForSingleObject(\r
- &p_port->leave_mcast_event, Executive, KernelMode, FALSE, NULL );\r
-\r
- __pending_list_destroy(p_port);\r
- \r
- cl_obj_lock( &p_port->p_adapter->obj );\r
- ipoib_dereg_addrs( p_port->p_adapter );\r
- cl_obj_unlock( &p_port->p_adapter->obj );\r
- \r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
-}\r
-\r
-\r
-static void\r
-__bcast_cb(\r
- IN ib_mcast_rec_t *p_mcast_rec )\r
-{\r
- ipoib_port_t *p_port;\r
- ib_api_status_t status;\r
- LARGE_INTEGER gc_due_time;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
-\r
- p_port = (ipoib_port_t*)p_mcast_rec->mcast_context;\r
-\r
- cl_obj_lock( &p_port->obj );\r
-\r
- ASSERT(p_port->state == IB_QPS_INIT || p_port->state == IB_QPS_ERROR);\r
- if( p_port->state != IB_QPS_INIT )\r
- {\r
- cl_obj_unlock( &p_port->obj );\r
- if( p_mcast_rec->status == IB_SUCCESS )\r
- {\r
- ipoib_port_ref(p_port, ref_leave_mcast);\r
- p_port->p_adapter->p_ifc->leave_mcast( p_mcast_rec->h_mcast, __leave_error_mcast_cb );\r
- }\r
- KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE );\r
- ipoib_port_deref( p_port, ref_bcast_inv_state );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
- ("Invalid state - Aborting.\n") );\r
- return;\r
- }\r
- status = p_mcast_rec->status;\r
- if( status != IB_SUCCESS )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Multicast join for broadcast group returned %s.\n",\r
- p_port->p_adapter->p_ifc->get_err_str( p_mcast_rec->status )) );\r
- if( status == IB_REMOTE_ERROR )\r
- {\r
- /*\r
- * Either:\r
- * - the join failed because the group no longer exists\r
- * - the create failed because the group already exists\r
- *\r
- * Kick off a new Get query to the SA to restart the join process\r
- * from the top. Note that as an optimization, it would be\r
- * possible to distinguish between the join and the create.\r
- * If the join fails, try the create. If the create fails, start\r
- * over with the Get.\r
- */\r
- /* TODO: Assert is a place holder. Can we ever get here if the\r
- state isn't IB_PNP_PORT_ADD or PORT_DOWN or PORT_INIT? */\r
- CL_ASSERT( p_port->p_adapter->state == IB_PNP_PORT_ADD ||\r
- p_port->p_adapter->state == IB_PNP_PORT_DOWN ||\r
- p_port->p_adapter->state == IB_PNP_PORT_INIT );\r
- if(++p_port->bc_join_retry_cnt < p_port->p_adapter->params.bc_join_retry)\r
- {\r
- status = __port_get_bcast( p_port );\r
- }\r
- else\r
- {\r
- NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
- EVENT_IPOIB_BCAST_JOIN, 1, p_mcast_rec->status );\r
- p_port->bc_join_retry_cnt = 0;\r
- }\r
- }\r
- else\r
- {\r
- NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
- EVENT_IPOIB_BCAST_JOIN, 1, p_mcast_rec->status );\r
- }\r
-\r
- cl_obj_unlock( &p_port->obj );\r
- if( status != IB_SUCCESS )\r
- {\r
- ipoib_set_inactive( p_port->p_adapter );\r
- __endpt_mgr_reset_all( p_port );\r
- ASSERT(p_port->state == IB_QPS_INIT || p_port->state == IB_QPS_ERROR);\r
- p_port->state = IB_QPS_ERROR;\r
- KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE );\r
- }\r
- ipoib_port_deref( p_port, ref_bcast_req_failed );\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
- return;\r
- }\r
- p_port->bc_join_retry_cnt = 0;\r
-\r
- while( p_port->endpt_rdr )\r
- {\r
- cl_obj_unlock( &p_port->obj );\r
- cl_obj_lock( &p_port->obj );\r
- }\r
-\r
- if( !p_port->p_local_endpt )\r
- {\r
- ib_port_info_t port_info;\r
- cl_memclr(&port_info, sizeof(port_info));\r
- port_info.base_lid = p_port->base_lid;\r
- status = __endpt_mgr_add_local( p_port, &port_info );\r
- if( status != IB_SUCCESS )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("__endpt_mgr_add_local returned %s\n",\r
- p_port->p_adapter->p_ifc->get_err_str( status )) );\r
- cl_obj_unlock( &p_port->obj );\r
- goto err;\r
- }\r
- }\r
-\r
- cl_obj_unlock( &p_port->obj );\r
-\r
- status = __endpt_mgr_add_bcast( p_port, p_mcast_rec );\r
- if( status != IB_SUCCESS )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("__endpt_mgr_add_bcast returned %s\n",\r
- p_port->p_adapter->p_ifc->get_err_str( status )) );\r
- ipoib_port_ref(p_port, ref_leave_mcast);\r
- status = p_port->p_adapter->p_ifc->leave_mcast( p_mcast_rec->h_mcast, __leave_error_mcast_cb );\r
- CL_ASSERT( status == IB_SUCCESS );\r
- goto err;\r
- }\r
-\r
- /* Get the QP ready for action. */\r
- status = __ib_mgr_activate( p_port );\r
- if( status != IB_SUCCESS )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("__ib_mgr_activate returned %s\n", \r
- p_port->p_adapter->p_ifc->get_err_str( status )) );\r
-\r
-err:\r
- /* Flag the adapter as hung. */\r
- p_port->p_adapter->hung = TRUE;\r
- ASSERT(p_port->state == IB_QPS_INIT || p_port->state == IB_QPS_ERROR);\r
- p_port->state = IB_QPS_ERROR; \r
- KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE );\r
- ipoib_port_deref( p_port, ref_bcast_error );\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
- return;\r
- }\r
-\r
- cl_obj_lock( &p_port->obj );\r
- /* Only change the state if we're still in INIT. */\r
- ASSERT( p_port->state == IB_QPS_INIT || p_port->state == IB_QPS_ERROR);\r
- if (p_port->state == IB_QPS_INIT) {\r
- p_port->state = IB_QPS_RTS;\r
- }\r
- cl_obj_unlock( &p_port->obj );\r
-\r
- /* Prepost receives. */\r
- cl_spinlock_acquire( &p_port->recv_lock );\r
- __recv_mgr_repost( p_port );\r
- cl_spinlock_release( &p_port->recv_lock );\r
-\r
- /* Notify the adapter that we now have an active connection. */\r
- status = ipoib_set_active( p_port->p_adapter );\r
- if( status != IB_SUCCESS )\r
- {\r
- ib_qp_mod_t qp_mod;\r
- ipoib_set_inactive( p_port->p_adapter );\r
- KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
- ("ipoib_set_active returned %s.\n",p_port->p_adapter->p_ifc->get_err_str( status )));\r
- cl_spinlock_acquire( &p_port->recv_lock );\r
- cl_obj_lock( &p_port->obj );\r
- p_port->state = IB_QPS_ERROR;\r
- if( p_port->ib_mgr.h_query )\r
- {\r
- p_port->p_adapter->p_ifc->cancel_query(\r
- p_port->p_adapter->h_al, p_port->ib_mgr.h_query );\r
- p_port->ib_mgr.h_query = NULL;\r
- }\r
- cl_obj_unlock( &p_port->obj );\r
- cl_spinlock_release( &p_port->recv_lock );\r
-\r
- CL_ASSERT( p_port->ib_mgr.h_qp );\r
- cl_memclr( &qp_mod, sizeof(ib_qp_mod_t) );\r
- qp_mod.req_state = IB_QPS_ERROR;\r
- status = p_port->p_adapter->p_ifc->modify_qp( p_port->ib_mgr.h_qp, &qp_mod );\r
- __endpt_mgr_reset_all( p_port );\r
-\r
- ipoib_port_deref( p_port, ref_join_bcast );\r
- return;\r
- }\r
-#if 0 //CM\r
- if( p_port->p_adapter->params.cm_enabled &&\r
- !p_port->p_local_endpt->conn.h_cm_listen )\r
- {\r
- if( ipoib_port_listen( p_port ) != IB_SUCCESS )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Port CM Listen failed\n" ) );\r
- /*keep going with UD only */\r
- p_port->p_adapter->params.cm_enabled = FALSE;\r
-\r
- NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
- EVENT_IPOIB_CONNECTED_MODE_ERR, 1, 0xbadc0de3 );\r
- }\r
- }\r
-#endif\r
- /* garbage collector timer is needed when link is active */\r
- gc_due_time.QuadPart = -(int64_t)(((uint64_t)p_port->p_adapter->params.mc_leave_rescan * 2000000) * 10);\r
- KeSetTimerEx(&p_port->gc_timer,gc_due_time,\r
- (LONG)p_port->p_adapter->params.mc_leave_rescan*1000,&p_port->gc_dpc);\r
-\r
- KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE );\r
- ipoib_port_deref( p_port, ref_join_bcast );\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
-}\r
-\r
-\r
-static void\r
-__qp_event(\r
- IN ib_async_event_rec_t *p_event_rec )\r
-{\r
- UNUSED_PARAM( p_event_rec );\r
- CL_ASSERT( p_event_rec->context );\r
- ((ipoib_port_t*)p_event_rec->context)->p_adapter->hung = TRUE;\r
-}\r
-\r
-\r
-static void\r
-__cq_event(\r
- IN ib_async_event_rec_t *p_event_rec )\r
-{\r
- UNUSED_PARAM( p_event_rec );\r
- CL_ASSERT( p_event_rec->context );\r
- ((ipoib_port_t*)p_event_rec->context)->p_adapter->hung = TRUE;\r
-}\r
-\r
-\r
-static ib_api_status_t\r
-__ib_mgr_activate(\r
- IN ipoib_port_t* const p_port )\r
-{\r
- ib_api_status_t status;\r
- ib_dgrm_info_t dgrm_info;\r
- ib_qp_mod_t qp_mod;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_INIT );\r
- /*\r
- * Move the QP to RESET. This allows us to reclaim any\r
- * unflushed receives.\r
- */\r
- cl_memclr( &qp_mod, sizeof(ib_qp_mod_t) );\r
- qp_mod.req_state = IB_QPS_RESET;\r
- status = p_port->p_adapter->p_ifc->modify_qp( p_port->ib_mgr.h_qp, &qp_mod );\r
- if( status != IB_SUCCESS )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ib_modify_qp returned %s\n", \r
- p_port->p_adapter->p_ifc->get_err_str( status )) );\r
- return status;\r
- }\r
-\r
- /* Move the QP to RTS. */\r
- dgrm_info.port_guid = p_port->p_adapter->guids.port_guid.guid;\r
- dgrm_info.qkey = p_port->ib_mgr.bcast_rec.qkey;\r
- dgrm_info.pkey_index = p_port->pkey_index;\r
- status = p_port->p_adapter->p_ifc->init_dgrm_svc( p_port->ib_mgr.h_qp, &dgrm_info );\r
- if( status != IB_SUCCESS )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ib_init_dgrm_svc returned %s\n", \r
- p_port->p_adapter->p_ifc->get_err_str( status )) );\r
- return status;\r
- }\r
-\r
- /* Rearm the CQs. */\r
- status = p_port->p_adapter->p_ifc->rearm_cq( p_port->ib_mgr.h_recv_cq, FALSE );\r
- if( status != IB_SUCCESS )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ib_rearm_cq for recv returned %s\n", \r
- p_port->p_adapter->p_ifc->get_err_str( status )) );\r
- return status;\r
- }\r
- status = p_port->p_adapter->p_ifc->rearm_cq( p_port->ib_mgr.h_send_cq, FALSE );\r
- if( status != IB_SUCCESS )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ib_rearm_cq for send returned %s\n", \r
- p_port->p_adapter->p_ifc->get_err_str( status )) );\r
- return status;\r
- }\r
-\r
- IPOIB_EXIT( IPOIB_DBG_INIT );\r
- return IB_SUCCESS;\r
-}\r
-\r
-\r
-/* Transition to a passive level thread. */\r
-ib_api_status_t\r
-ipoib_port_join_mcast(\r
- IN ipoib_port_t* const p_port,\r
- IN const mac_addr_t mac,\r
- IN const uint8_t state)\r
-{\r
- ib_api_status_t status;\r
- ib_mcast_req_t mcast_req;\r
- ipoib_endpt_t *p_endpt;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_MCAST );\r
-\r
- switch( __endpt_mgr_ref( p_port, mac, &p_endpt ) )\r
- {\r
- case NDIS_STATUS_NO_ROUTE_TO_DESTINATION:\r
- break;\r
-\r
- case NDIS_STATUS_SUCCESS:\r
- ipoib_endpt_deref( p_endpt );\r
- /* Fall through */\r
-\r
- case NDIS_STATUS_PENDING:\r
- return IB_SUCCESS;\r
- }\r
-\r
- /*\r
- * Issue the mcast request, using the parameters of the broadcast group.\r
- * This allows us to do a create request that should always succeed since\r
- * the required parameters are known.\r
- */\r
- cl_memclr( &mcast_req, sizeof(mcast_req) );\r
- mcast_req.create = TRUE;\r
-\r
- /* Copy the settings from the broadcast group. */\r
- mcast_req.member_rec = p_port->ib_mgr.bcast_rec;\r
- /* Clear fields that aren't specified in the join */\r
- mcast_req.member_rec.mlid = 0;\r
- ib_member_set_state( &mcast_req.member_rec.scope_state,state);\r
-\r
- if( (mac.addr[0] == 1) && (mac.addr[2] == 0x5E ))\r
- {\r
- /*\r
- * Update the address portion of the MGID with the 28 lower bits of the\r
- * IP address. Since we're given a MAC address, we are using \r
- * 24 lower bits of that network-byte-ordered value (assuming MSb\r
- * is zero) and 4 lsb bits of the first byte of IP address.\r
- */\r
- mcast_req.member_rec.mgid.raw[12] = mac.addr[1];\r
- mcast_req.member_rec.mgid.raw[13] = mac.addr[3];\r
- mcast_req.member_rec.mgid.raw[14] = mac.addr[4];\r
- mcast_req.member_rec.mgid.raw[15] = mac.addr[5];\r
- }\r
- else\r
- {\r
- /* Handle non IP mutlicast MAC addresses. */\r
- /* Update the signature to use the lower 2 bytes of the OpenIB OUI. */\r
- mcast_req.member_rec.mgid.raw[2] = 0x14;\r
- mcast_req.member_rec.mgid.raw[3] = 0x05;\r
- /* Now copy the MAC address into the last 6 bytes of the GID. */\r
- cl_memcpy( &mcast_req.member_rec.mgid.raw[10], mac.addr, 6 );\r
- }\r
-\r
- mcast_req.mcast_context = p_port;\r
- mcast_req.pfn_mcast_cb = __mcast_cb;\r
- mcast_req.timeout_ms = p_port->p_adapter->params.sa_timeout;\r
- mcast_req.retry_cnt = p_port->p_adapter->params.sa_retry_cnt;\r
- mcast_req.port_guid = p_port->p_adapter->guids.port_guid.guid;\r
- mcast_req.pkey_index = p_port->pkey_index;\r
- mcast_req.member_rec.pkey = cl_hton16(p_port->p_adapter->guids.port_guid.pkey);\r
- /*\r
- * Create the endpoint and insert it in the port. Since we don't wait for\r
- * the mcast SA operations to complete before returning from the multicast\r
- * list set OID asynchronously, it is possible for the mcast entry to be\r
- * cleared before the SA interaction completes. In this case, when the\r
- * mcast callback is invoked, it would not find the corresponding endpoint\r
- * and would be undone.\r
- */\r
- p_endpt = ipoib_endpt_create(\r
- &mcast_req.member_rec.mgid, 0, CL_HTON32(0x00FFFFFF) );\r
- if( !p_endpt )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ipoib_endpt_create failed.\n") );\r
- return IB_INSUFFICIENT_MEMORY;\r
- }\r
-\r
- status = __endpt_mgr_insert_locked( p_port, mac, p_endpt );\r
- if( status != IB_SUCCESS )\r
- {\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("__endpt_mgr_insert_locked returned %s\n", \r
- p_port->p_adapter->p_ifc->get_err_str( status )) );\r
- return status;\r
- }\r
-\r
- /* reference the object for the multicast join request. */\r
- ipoib_port_ref( p_port, ref_join_mcast );\r
-\r
- status = p_port->p_adapter->p_ifc->join_mcast( p_port->ib_mgr.h_qp, &mcast_req );\r
- if( status != IB_SUCCESS )\r
- {\r
- ipoib_port_deref( p_port, ref_mcast_join_failed );\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("ib_join_mcast returned %s\n", \r
- p_port->p_adapter->p_ifc->get_err_str( status )) );\r
- }\r
-\r
- IPOIB_EXIT( IPOIB_DBG_MCAST );\r
- return status;\r
-}\r
-\r
-\r
-static void\r
-__mcast_cb(\r
- IN ib_mcast_rec_t *p_mcast_rec )\r
-{\r
- ib_api_status_t status;\r
- ipoib_port_t *p_port;\r
- cl_fmap_item_t *p_item;\r
- ipoib_endpt_t *p_endpt;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_MCAST );\r
-\r
- p_port = (ipoib_port_t*)p_mcast_rec->mcast_context;\r
-\r
- cl_obj_lock( &p_port->obj );\r
- while( p_port->endpt_rdr )\r
- {\r
- cl_obj_unlock( &p_port->obj );\r
- cl_obj_lock( &p_port->obj );\r
- }\r
- if( p_port->state != IB_QPS_RTS )\r
- {\r
- cl_obj_unlock( &p_port->obj );\r
- if( p_mcast_rec->status == IB_SUCCESS )\r
-\r
- {\r
- ipoib_port_ref(p_port, ref_leave_mcast);\r
- p_port->p_adapter->p_ifc->leave_mcast( p_mcast_rec->h_mcast, __leave_error_mcast_cb );\r
- }\r
- ipoib_port_deref( p_port, ref_mcast_inv_state );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
- ("Invalid state - Aborting.\n") );\r
- return;\r
- }\r
-\r
- if( p_mcast_rec->status != IB_SUCCESS )\r
- {\r
- cl_obj_unlock( &p_port->obj );\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Multicast join request failed with status %s.\n",\r
- p_port->p_adapter->p_ifc->get_err_str( p_mcast_rec->status )) );\r
- /* Flag the adapter as hung. */\r
- p_port->p_adapter->hung =TRUE;\r
- ipoib_port_deref( p_port, ref_mcast_req_failed );\r
- IPOIB_EXIT( IPOIB_DBG_MCAST );\r
- return;\r
- }\r
-\r
- p_item = cl_fmap_get(\r
- &p_port->endpt_mgr.gid_endpts, &p_mcast_rec->p_member_rec->mgid );\r
- if( p_item == cl_fmap_end( &p_port->endpt_mgr.gid_endpts ) )\r
- {\r
- /*\r
- * The endpoint must have been flushed while the join request\r
- * was outstanding. Just leave the group and return. This\r
- * is not an error.\r
- */\r
- cl_obj_unlock( &p_port->obj );\r
- IPOIB_PRINT(TRACE_LEVEL_WARNING, IPOIB_DBG_ERROR,\r
- ("Failed to find endpoint for update.\n") );\r
-\r
- ipoib_port_ref(p_port, ref_leave_mcast);\r
- p_port->p_adapter->p_ifc->leave_mcast( p_mcast_rec->h_mcast, __leave_error_mcast_cb );\r
- ipoib_port_deref( p_port, ref_mcast_no_endpt );\r
- IPOIB_EXIT( IPOIB_DBG_MCAST );\r
- return;\r
- }\r
-\r
- p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, gid_item );\r
- p_endpt->p_ifc = p_port->p_adapter->p_ifc;\r
-\r
- /* Setup the endpoint for use. */\r
- status = ipoib_endpt_set_mcast(\r
- p_endpt, p_port->ib_mgr.h_pd, p_port->port_num, p_mcast_rec );\r
- if( status != IB_SUCCESS )\r
- {\r
- cl_obj_unlock( &p_port->obj );\r
- IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_MCAST,\r
- ("ipoib_endpt_set_mcast returned %s.\n",\r
- p_port->p_adapter->p_ifc->get_err_str( status )) );\r
- /* Flag the adapter as hung. */\r
- p_port->p_adapter->hung = TRUE;\r
- ipoib_port_deref( p_port, ref_mcast_av_failed );\r
- IPOIB_EXIT( IPOIB_DBG_MCAST );\r
- return;\r
- }\r
-\r
- /*\r
- * The endpoint is already in the GID and MAC maps.\r
- * mast endpoint are not used in the LID map.\r
- */\r
- CL_ASSERT(p_endpt->dlid == 0);\r
- /* set flag that endpoint is use */\r
- p_endpt->is_in_use = TRUE;\r
- cl_obj_unlock( &p_port->obj );\r
- \r
- /* Try to send all pending sends. */\r
- ipoib_port_resume( p_port , FALSE);\r
-\r
- ipoib_port_deref( p_port, ref_join_mcast );\r
-\r
- IPOIB_EXIT( IPOIB_DBG_MCAST );\r
-}\r
-\r
-\r
-void\r
-ipoib_leave_mcast_cb(\r
- IN void *context )\r
-{\r
- ipoib_port_t *p_port;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_MCAST );\r
-\r
- p_port = (ipoib_port_t*)context;\r
-\r
- IPOIB_PRINT( TRACE_LEVEL_VERBOSE, IPOIB_DBG_MCAST,("p_port->mcast_cnt = %d\n", p_port->mcast_cnt));\r
- \r
- ipoib_port_deref( p_port, ref_leave_mcast);\r
- cl_atomic_dec( &p_port->mcast_cnt);\r
- \r
- if(0 == p_port->mcast_cnt)\r
- {\r
- KeSetEvent( &p_port->leave_mcast_event, EVENT_INCREMENT, FALSE );\r
- }\r
- \r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_MCAST,\r
- ("Leave mcast callback deref ipoib_port \n") );\r
- \r
- IPOIB_EXIT( IPOIB_DBG_MCAST );\r
-}\r
-\r
-\r
-\r
-void\r
-__leave_error_mcast_cb(\r
- IN void *context )\r
-{\r
- ipoib_port_t *p_port;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_MCAST );\r
-\r
- p_port = (ipoib_port_t*)context;\r
-\r
- ipoib_port_deref( p_port, ref_leave_mcast);\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_MCAST,\r
- ("Leave mcast callback deref ipoib_port \n") );\r
- \r
- IPOIB_EXIT( IPOIB_DBG_MCAST );\r
-}\r
-\r
-/*++\r
-Routine Description:\r
- The routine process the packet and returns LSO information\r
- \r
-Arguments:\r
- pNetBuffer - a pointer to the first net buffer object of the packet\r
- TcpHeaderOffset - offset to the begining of the TCP header in the packet\r
- pLsoData - pointer to LsoData object in which the routine returns the LSO information\r
- pHeaderSize - pointer to ULONG object in which the header size is returned\r
- IndexOfData - \r
- \r
-Return Value:\r
- NDIS_STATUS \r
-\r
-NOTE:\r
- called at DISPATCH level\r
---*/\r
-\r
-NDIS_STATUS GetLsoHeaderSize(\r
- IN PNET_BUFFER pNetBuffer,\r
- IN LsoData *pLsoData,\r
- OUT UINT *IndexOfData,\r
- IN ipoib_hdr_t *ipoib_hdr\r
- )\r
-{\r
- UINT CurrLength;\r
- PUCHAR pSrc;\r
- PUCHAR pCopiedData = pLsoData->coppied_data;\r
- ip_hdr_t UNALIGNED *IpHdr;\r
- tcp_hdr_t UNALIGNED *TcpHdr;\r
- uint16_t TcpHeaderLen;\r
- uint16_t IpHeaderLen;\r
- uint16_t IpOffset;\r
- INT FullBuffers = 0;\r
- PMDL pMDL;\r
- NDIS_STATUS status = NDIS_STATUS_INVALID_PACKET;\r
- \r
- \r
-#define IP_OFFSET 14;\r
- //\r
- // This Flag indicates the way we gets the headers\r
- // RegularFlow = we get the headers (ETH+IP+TCP) in the same Buffer \r
- // in sequence.\r
- //\r
- boolean_t IsRegularFlow = TRUE;\r
-\r
- const uint16_t ETH_OFFSET = IP_OFFSET; \r
- \r
- pLsoData->LsoHeaderSize = 0;\r
- IpOffset = IP_OFFSET; //(uint16_t)pPort->EncapsulationFormat.EncapsulationHeaderSize;\r
- *IndexOfData = 0;\r
-\r
- pMDL = NET_BUFFER_CURRENT_MDL(pNetBuffer);\r
- NdisQueryMdl(pMDL, &pSrc, &CurrLength, NormalPagePriority);\r
- //NdisQueryBufferSafe( CurrBuffer, &pSrc, &CurrLength, NormalPagePriority );\r
- if (pSrc == NULL) {\r
- IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, ("Error processing packets\n"));\r
- return status;\r
- }\r
- // We start by looking for the ethernet and the IP\r
- if (CurrLength < ETH_OFFSET) {\r
- IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, ("Error porcessing packets\n"));\r
- return status;\r
- }\r
- //pLsoData->LsoHeaderSize = pLsoData->LsoHeaderSize + ETH_OFFSET;\r
- if (CurrLength == ETH_OFFSET) { \r
- ASSERT(FALSE);\r
- IsRegularFlow = FALSE; \r
- memcpy(pCopiedData, pSrc, ETH_OFFSET);\r
- pCopiedData += ETH_OFFSET; \r
- FullBuffers++;\r
- // First buffer was only ethernet\r
- pNetBuffer = NET_BUFFER_NEXT_NB(pNetBuffer);\r
- NdisQueryMdl(NET_BUFFER_CURRENT_MDL(pNetBuffer), &pSrc, &CurrLength, NormalPagePriority);\r
- if (pSrc == NULL) {\r
- IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, ("Error porcessing packets\n"));\r
- return status;\r
- }\r
- } else {\r
- // This is ETH + IP together (at least)\r
- pLsoData->LsoBuffers[0].pData = pSrc + (ETH_OFFSET - sizeof (ipoib_hdr_t));\r
- memcpy (pLsoData->LsoBuffers[0].pData, ipoib_hdr, sizeof (ipoib_hdr_t));\r
- CurrLength -= ETH_OFFSET;\r
- pSrc = pSrc + ETH_OFFSET;\r
- pLsoData->LsoHeaderSize = pLsoData->LsoHeaderSize + sizeof (ipoib_hdr_t);\r
- }\r
- // we should now be having at least the size of ethernet data\r
- if (CurrLength < sizeof (ip_hdr_t)) {\r
- IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, ("Error porcessing packets\n"));\r
- return status;\r
- }\r
- IpHdr = (ip_hdr_t UNALIGNED*)pSrc;\r
- IpHeaderLen = (uint16_t)IP_HEADER_LENGTH(IpHdr);\r
- ASSERT(IpHdr->prot == IP_PROT_TCP);\r
- if (CurrLength < IpHeaderLen) {\r
- IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, ("Error processing packets\n"));\r
- return status;\r
- }\r
- pLsoData->LsoHeaderSize = pLsoData->LsoHeaderSize + IpHeaderLen;\r
- // We now start to find where the TCP header starts\r
- if (CurrLength == IpHeaderLen) {\r
- ASSERT(FALSE);\r
- // two options : \r
- // if(IsRegularFlow = FALSE) ==> ETH and IP seperated in two buffers\r
- // if(IsRegularFlow = TRUE ) ==> ETH and IP in the same buffer \r
- // TCP will start at next buffer\r
- if(IsRegularFlow){\r
- memcpy(pCopiedData, pSrc-ETH_OFFSET ,ETH_OFFSET+IpHeaderLen);\r
- pCopiedData += (ETH_OFFSET + IpHeaderLen);\r
- } else {\r
- memcpy(pCopiedData, pSrc,IpHeaderLen);\r
- pCopiedData += IpHeaderLen;\r
- }\r
-\r
- FullBuffers++;\r
- IsRegularFlow = FALSE;\r
- //NdisGetNextBuffer( CurrBuffer, &CurrBuffer);\r
- //NdisQueryBufferSafe( CurrBuffer, &pSrc, &CurrLength, NormalPagePriority );\r
- pNetBuffer = NET_BUFFER_NEXT_NB(pNetBuffer);\r
- NdisQueryMdl(NET_BUFFER_CURRENT_MDL(pNetBuffer), &pSrc, &CurrLength, NormalPagePriority);\r
- if (pSrc == NULL) {\r
- IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, ("Error porcessing packets\n"));\r
- return status;\r
- }\r
- } else {\r
- // if(IsRegularFlow = TRUE ) ==> the ETH and IP and TCP in the same buffer \r
- // if(IsRegularFlow = FLASE ) ==> ETH in one buffer , IP+TCP together in the same buffer\r
- if (IsRegularFlow) { \r
- pLsoData->LsoBuffers[0].Len += IpHeaderLen;\r
- } else { \r
- memcpy(pCopiedData, pSrc, IpHeaderLen);\r
- pCopiedData += IpHeaderLen;\r
- }\r
-\r
- CurrLength -= IpHeaderLen;\r
- pSrc = pSrc + IpHeaderLen;\r
- }\r
- if (CurrLength < sizeof (tcp_hdr_t)) {\r
- IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, ("Error porcessing packets\n"));\r
- return status;\r
- }\r
- // We have finaly found the TCP header\r
- TcpHdr = (tcp_hdr_t UNALIGNED *)pSrc;\r
- TcpHeaderLen = TCP_HEADER_LENGTH(TcpHdr);\r
-\r
- //ASSERT(TcpHeaderLen == 20);\r
- \r
- if (CurrLength < TcpHeaderLen) {\r
- //IPOIB_PRINT(TRACE_LEVEL_VERBOSE, ETH, ("Error porcessing packets\n"));\r
- return status;\r
- }\r
- pLsoData->LsoHeaderSize = pLsoData->LsoHeaderSize + TcpHeaderLen;\r
- if(IsRegularFlow){\r
- pLsoData->LsoBuffers[0].Len += TcpHeaderLen;\r
- }\r
- else{\r
- memcpy(pCopiedData, pSrc, TcpHeaderLen);\r
- pCopiedData += TcpHeaderLen;\r
- }\r
- if (CurrLength == TcpHeaderLen) {\r
- FullBuffers++;\r
- pLsoData->UsedBuffers = FullBuffers;\r
- *IndexOfData = FullBuffers ;\r
- } else {\r
- pLsoData->UsedBuffers = FullBuffers + 1;\r
- *IndexOfData = FullBuffers - 1;\r
- }\r
- pLsoData->FullBuffers = FullBuffers; \r
- if (!IsRegularFlow){\r
- pLsoData->LsoBuffers[0].pData = pLsoData->coppied_data;\r
- pLsoData->LsoBuffers[0].Len = ETH_OFFSET + IpHeaderLen + TcpHeaderLen;\r
- ASSERT(pLsoData->LsoBuffers[0].Len <= LSO_MAX_HEADER);\r
- }\r
- return NDIS_STATUS_SUCCESS;\r
-}\r
-\r
-static void __port_do_mcast_garbage(ipoib_port_t* const p_port)\r
-{\r
- const mac_addr_t DEFAULT_MCAST_GROUP = {0x01, 0x00, 0x5E, 0x00, 0x00, 0x01};\r
- /* Do garbage collecting... */\r
-\r
- cl_map_item_t *p_item;\r
- ipoib_endpt_t *p_endpt;\r
- cl_qlist_t destroy_mc_list;\r
- uint8_t cnt;\r
- const static GC_MAX_LEAVE_NUM = 80;\r
-\r
- cl_qlist_init( &destroy_mc_list );\r
-\r
- cl_obj_lock( &p_port->obj );\r
- /* Wait for all readers to finish */\r
- while( p_port->endpt_rdr )\r
- {\r
- cl_obj_unlock( &p_port->obj );\r
- cl_obj_lock( &p_port->obj );\r
- }\r
- cnt = 0;\r
- p_item = cl_qmap_head( &p_port->endpt_mgr.mac_endpts );\r
- while( (p_item != cl_qmap_end( &p_port->endpt_mgr.mac_endpts )) && (cnt < GC_MAX_LEAVE_NUM))\r
- {\r
- p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item );\r
- p_item = cl_qmap_next( p_item );\r
-\r
- /* Check if the current endpoint is not a multicast listener */\r
-\r
- if( p_endpt->h_mcast && \r
- (!p_endpt->is_mcast_listener) &&\r
- ( cl_memcmp( &p_endpt->mac, &DEFAULT_MCAST_GROUP, sizeof(mac_addr_t) ) &&\r
- (!p_endpt->is_in_use) ))\r
- {\r
- cl_qmap_remove_item( &p_port->endpt_mgr.mac_endpts,\r
- &p_endpt->mac_item );\r
- cl_fmap_remove_item( &p_port->endpt_mgr.gid_endpts,\r
- &p_endpt->gid_item );\r
-\r
- if( p_endpt->dlid )\r
- {\r
- cl_qmap_remove_item( &p_port->endpt_mgr.lid_endpts,\r
- &p_endpt->lid_item );\r
- p_endpt->dlid = 0;\r
- }\r
-\r
- cl_qlist_insert_tail(\r
- &destroy_mc_list, &p_endpt->mac_item.pool_item.list_item );\r
- cnt++;\r
- }\r
- else\r
- p_endpt->is_in_use = FALSE;\r
- }\r
- cl_obj_unlock( &p_port->obj );\r
-\r
- /* Destroy all multicast endpoints now that we have released the lock. */\r
- while( cl_qlist_count( &destroy_mc_list ) )\r
- {\r
- p_endpt = PARENT_STRUCT( cl_qlist_remove_head( &destroy_mc_list ),\r
- ipoib_endpt_t, mac_item.pool_item.list_item );\r
- IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
- ("mcast garbage collector: destroying endpoint %02x:%02x:%02x:%02x:%02x:%02x \n", \r
- p_endpt->mac.addr[0],\r
- p_endpt->mac.addr[1],\r
- p_endpt->mac.addr[2],\r
- p_endpt->mac.addr[3],\r
- p_endpt->mac.addr[4],\r
- p_endpt->mac.addr[5]) );\r
- cl_obj_destroy( &p_endpt->obj );\r
- }\r
-}\r
-\r
-static void __port_mcast_garbage_dpc(KDPC *p_gc_dpc,void *context,void *s_arg1, void *s_arg2)\r
-{\r
- ipoib_port_t *p_port = context;\r
-\r
- UNREFERENCED_PARAMETER(p_gc_dpc);\r
- UNREFERENCED_PARAMETER(s_arg1);\r
- UNREFERENCED_PARAMETER(s_arg2);\r
-\r
- __port_do_mcast_garbage(p_port);\r
-}\r
-\r
-ipoib_endpt_t*\r
-ipoib_endpt_get_by_gid(\r
- IN ipoib_port_t* const p_port,\r
- IN const ib_gid_t* const p_gid )\r
-{\r
- return __endpt_mgr_get_by_gid( p_port, p_gid );\r
-}\r
-\r
-ipoib_endpt_t*\r
-ipoib_endpt_get_by_lid(\r
- IN ipoib_port_t* const p_port,\r
- IN const net16_t lid )\r
-{\r
- return __endpt_mgr_get_by_lid( p_port, lid );\r
-}\r
-\r
-ib_api_status_t\r
-ipoib_recv_dhcp(\r
- IN ipoib_port_t* const p_port,\r
- IN const ipoib_pkt_t* const p_ipoib,\r
- OUT eth_pkt_t* const p_eth,\r
- IN ipoib_endpt_t* const p_src,\r
- IN ipoib_endpt_t* const p_dst )\r
-{\r
- return __recv_dhcp(\r
- p_port, p_ipoib, p_eth, p_src,p_dst );\r
-}\r
-\r
-\r
-void\r
-ipoib_port_cancel_xmit(\r
- IN ipoib_port_t* const p_port,\r
- IN PVOID cancel_id )\r
-{\r
- cl_list_item_t *p_item;\r
- PNET_BUFFER_LIST p_nbl;\r
- PVOID nbl_id;\r
- cl_qlist_t cancel_list;\r
- ULONG send_complete_flags = 0;\r
- IPOIB_ENTER( IPOIB_DBG_SEND );\r
-\r
- cl_qlist_init( &cancel_list );\r
-\r
- cl_spinlock_acquire( &p_port->send_lock );\r
-\r
- for( p_item = cl_qlist_head( &p_port->send_mgr.pending_list );\r
- p_item != cl_qlist_end( &p_port->send_mgr.pending_list );\r
- p_item = cl_qlist_next( p_item ) )\r
- {\r
- p_nbl = IPOIB_PACKET_FROM_LIST_ITEM( p_item );\r
- nbl_id = NDIS_GET_NET_BUFFER_LIST_CANCEL_ID( p_nbl );\r
- if( nbl_id == cancel_id )\r
- {\r
- cl_qlist_remove_item( &p_port->send_mgr.pending_list, p_item );\r
- NET_BUFFER_LIST_STATUS( p_nbl) = NDIS_STATUS_REQUEST_ABORTED ;\r
- cl_qlist_insert_tail( &cancel_list, IPOIB_LIST_ITEM_FROM_PACKET( p_nbl ) );\r
- }\r
- }\r
- cl_spinlock_release( &p_port->send_lock );\r
-\r
- if( cl_qlist_count( &cancel_list ) )\r
- {\r
- while( ( p_item = cl_qlist_remove_head( &cancel_list )) \r
- != cl_qlist_end( &cancel_list ))\r
- {\r
- p_nbl = IPOIB_PACKET_FROM_LIST_ITEM( p_item );\r
- NET_BUFFER_LIST_STATUS( p_nbl) = NDIS_STATUS_SEND_ABORTED;\r
- send_complete_flags = 0;\r
- if (NDIS_CURRENT_IRQL() == DISPATCH_LEVEL)\r
- {\r
- NDIS_SET_SEND_COMPLETE_FLAG(send_complete_flags, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL);\r
- }\r
- NdisMSendNetBufferListsComplete( p_port->p_adapter->h_adapter,\r
- p_nbl, send_complete_flags );\r
- }\r
- }\r
- IPOIB_EXIT( IPOIB_DBG_SEND );\r
-}\r
-\r
-/* \r
-* Put all fragments into separate WR and chain together.\r
-* The last WR will be set to generate CQ Event.\r
-* lookaside buffer is used for ipoib and ip headers attached to each WR.\r
-* Buffer will be released on last WR send completion.\r
-*/\r
-#if 0\r
-static NDIS_STATUS\r
-__send_fragments(\r
-IN ipoib_port_t* const p_port,\r
-IN ipoib_send_desc_t* const p_desc,\r
-IN eth_hdr_t* const p_eth_hdr,\r
-IN ip_hdr_t* const p_ip_hdr,\r
-IN uint32_t buf_len,\r
-IN NDIS_BUFFER* p_ndis_buf )\r
-{\r
- uint32_t ds_idx = 1;\r
- uint32_t wr_idx = 0;\r
- uint32_t sgl_idx = 2; //skip eth hdr, ip hdr\r
- uint32_t options_len = 0;\r
- uint8_t* p_options = NULL;\r
- uint8_t* p_buf;\r
- uint32_t frag_offset = 0;\r
- uint32_t next_sge;\r
- uint32_t wr_size = 0;\r
- uint32_t ip_hdr_len = IP_HEADER_LENGTH( p_ip_hdr );\r
- uint32_t total_ip_len = cl_ntoh16( p_ip_hdr->length );\r
-\r
- SCATTER_GATHER_LIST *p_sgl;\r
-\r
- IPOIB_ENTER( IPOIB_DBG_SEND );\r
-\r
- if( IP_DONT_FRAGMENT(p_ip_hdr) )\r
- return NDIS_STATUS_INVALID_PACKET;\r
- \r
- p_sgl = NDIS_PER_PACKET_INFO_FROM_PACKET( p_desc->p_pkt, ScatterGatherListPacketInfo );\r
- if( !p_sgl )\r
- {\r
- ASSERT( p_sgl );\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Failed to get SGL from packet.\n") );\r
- return NDIS_STATUS_FAILURE;\r
- }\r
- if( ( p_sgl->NumberOfElements > MAX_SEND_SGE ||\r
- p_sgl->Elements[0].Length < sizeof(eth_hdr_t)) )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Too many SG Elements in packet.\n") );\r
- return NDIS_STATUS_FAILURE;\r
- }\r
- p_buf = (uint8_t *)\r
- ExAllocateFromNPagedLookasideList( &p_port->buf_mgr.send_buf_list );\r
- if( !p_buf )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Failed to allocate lookaside buffer.\n") );\r
- return NDIS_STATUS_RESOURCES;\r
- }\r
- p_desc->p_buf = (send_buf_t*)p_buf;\r
-\r
- if( buf_len < ip_hdr_len )\r
- { /* ip options in a separate buffer */\r
- CL_ASSERT( buf_len == sizeof( ip_hdr_t ) );\r
- NdisGetNextBuffer( p_ndis_buf, &p_ndis_buf );\r
- if( !p_ndis_buf )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Failed to get IP options buffer.\n") );\r
- return NDIS_STATUS_FAILURE;\r
- }\r
- NdisQueryBufferSafe( p_ndis_buf, &p_options, &options_len, NormalPagePriority );\r
- if( !p_options )\r
- {\r
- IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
- ("Failed to query IP options buffer address.\n") );\r
- return NDIS_STATUS_FAILURE;\r
- }\r
- cl_memcpy( p_buf, p_ip_hdr, sizeof( ip_hdr_t ) );\r
- if( p_options && options_len )\r
- { \r
- __copy_ip_options( &p_buf[sizeof(ip_hdr_t)], \r
- p_options, options_len, TRUE );\r
- }\r
- wr_size = buf_len + options_len;\r
- sgl_idx++;\r
- }\r
- else\r
- { /*options probably in the same buffer */\r
- cl_memcpy( p_buf, p_ip_hdr, buf_len );\r
- options_len = ip_hdr_len - sizeof( ip_hdr_t );\r
- if( options_len )\r
- {\r
- p_options = p_buf + sizeof( ip_hdr_t );\r
- }\r
- frag_offset += ( buf_len - ip_hdr_len );\r
- wr_size = buf_len;\r
- }\r
-\r
- p_desc->send_wr[wr_idx].local_ds[ds_idx].vaddr = cl_get_physaddr( p_buf );\r
- p_desc->send_wr[wr_idx].local_ds[ds_idx].lkey = p_port->ib_mgr.lkey;\r
- p_desc->send_wr[wr_idx].local_ds[ds_idx].length = wr_size;\r
- \r
- /* count how much data can be put into the first WR beside IP header.\r
- * other protocols headers possibly supplied in subsequent buffers.\r
- */\r
- for( sgl_idx; sgl_idx < p_sgl->NumberOfElements; sgl_idx++ )\r
- {\r
- next_sge = p_sgl->Elements[sgl_idx].Length;\r
-\r
- /* add sgl if it can fit into the same WR \r
- * Note: so far not going to split large SGE between WRs,\r
- * so first fragment could be a smaller size.\r
- */\r
- if( next_sge <= ( p_port->p_adapter->params.payload_mtu - wr_size ) )\r
- {\r
- ++ds_idx;\r
- wr_size += next_sge;\r
- frag_offset += next_sge;\r
- p_desc->send_wr[wr_idx].local_ds[ds_idx].vaddr = \r
- p_sgl->Elements[sgl_idx].Address.QuadPart;\r
- p_desc->send_wr[wr_idx].local_ds[ds_idx].length = next_sge;\r
- p_desc->send_wr[wr_idx].local_ds[ds_idx].lkey = p_port->ib_mgr.lkey;\r
- }\r
- else\r
- {\r
- /* fix ip hdr for the first fragment and move on */\r
- __update_fragment_ip_hdr( (ip_hdr_t* const)p_buf,\r
- (uint16_t)wr_size, IP_FRAGMENT_OFFSET(p_ip_hdr), TRUE );\r
-\r
- p_desc->send_wr[wr_idx].wr.num_ds = ds_idx + 1;\r
- p_buf += ip_hdr_len;\r
- p_buf += (( buf_len > ip_hdr_len ) ? ( buf_len - ip_hdr_len ): 0);\r
- frag_offset += ( (IP_FRAGMENT_OFFSET(p_ip_hdr)) << 3 );\r
- ++wr_idx;\r
- ds_idx = 0;\r
- break;\r
- }\r
- }\r
- total_ip_len -= wr_size;\r
- wr_size = 0;\r
-\r
- for( sgl_idx, wr_idx; sgl_idx < p_sgl->NumberOfElements; sgl_idx++ )\r
- {\r
- uint32_t seg_len;\r
- uint64_t next_sgl_addr;\r
- \r
- if( wr_idx >= ( MAX_WRS_PER_MSG - 1 ) )\r
- return NDIS_STATUS_RESOURCES;\r
- \r
- next_sge = p_sgl->Elements[sgl_idx].Length;\r
- next_sgl_addr = p_sgl->Elements[sgl_idx].Address.QuadPart;\r
-\r
- while( next_sge )\r
- {\r
- if( ds_idx == 0 )\r
- { /* new ipoib + ip header */\r
- ((ipoib_hdr_t*)p_buf)->type = p_eth_hdr->type;\r
- ((ipoib_hdr_t*)p_buf)->resv = 0;\r
- p_desc->send_wr[wr_idx].local_ds[ds_idx].vaddr = cl_get_physaddr( p_buf );\r
- p_desc->send_wr[wr_idx].local_ds[ds_idx].lkey = p_port->ib_mgr.lkey;\r
- p_desc->send_wr[wr_idx].local_ds[ds_idx].length = sizeof( ipoib_hdr_t );\r
- p_buf += sizeof( ipoib_hdr_t );\r
- ++ds_idx;\r
-\r
- cl_memcpy( p_buf, p_ip_hdr, sizeof( ip_hdr_t ) );\r
- if( p_options && options_len )\r
- {\r
- /* copy ip options if needed */\r
- __copy_ip_options( &p_buf[sizeof(ip_hdr_t)], \r
- p_options, options_len, FALSE );\r
- }\r
- wr_size = ip_hdr_len;\r
- }\r
- if( ds_idx == 1 )\r
- {\r
- p_desc->send_wr[wr_idx].local_ds[ds_idx].length = ip_hdr_len;\r
- p_desc->send_wr[wr_idx].local_ds[ds_idx].vaddr = cl_get_physaddr( p_buf );\r
- p_desc->send_wr[wr_idx].local_ds[ds_idx].lkey = p_port->ib_mgr.lkey;\r
- ++ds_idx;\r
- }\r
-\r
- seg_len = ( next_sge > ( p_port->p_adapter->params.payload_mtu - wr_size ) )?\r
- ( p_port->p_adapter->params.payload_mtu - wr_size ) : next_sge;\r
-\r
- p_desc->send_wr[wr_idx].local_ds[ds_idx].vaddr = next_sgl_addr;\r
- p_desc->send_wr[wr_idx].local_ds[ds_idx].length = seg_len;\r
- p_desc->send_wr[wr_idx].local_ds[ds_idx].lkey = p_port->ib_mgr.lkey;\r
- ++ds_idx;\r
- \r
- wr_size += seg_len;\r
- total_ip_len -= seg_len;\r
-\r
- if( wr_size >= p_port->p_adapter->params.payload_mtu || total_ip_len == 0 )\r
- { /* fix ip hdr for that fragment */\r
- __update_fragment_ip_hdr( (ip_hdr_t* const)p_buf, (uint16_t)wr_size,\r
- ((uint16_t)(frag_offset >> 3 )), \r
- (BOOLEAN)(( total_ip_len > 0 ) || IP_MORE_FRAGMENTS( p_ip_hdr)) );\r
- p_desc->send_wr[wr_idx].wr.num_ds = ds_idx;\r
- if( total_ip_len > 0 )\r
- {\r
- ++wr_idx;\r
- frag_offset += (wr_size - ip_hdr_len);\r
- wr_size = 0;\r
- ds_idx = 0;\r
- p_buf += ip_hdr_len;\r
- }\r
- }\r
- next_sge -= seg_len;\r
- if( next_sge > 0 )\r
- {\r
- next_sgl_addr += seg_len;\r
- }\r
- }\r
- }\r
- p_desc->num_wrs += wr_idx;\r
- \r
- IPOIB_EXIT( IPOIB_DBG_SEND );\r
- return NDIS_STATUS_SUCCESS;\r
-}\r
-#endif\r
-\r
-static void\r
-__update_fragment_ip_hdr(\r
-IN ip_hdr_t* const p_ip_hdr,\r
-IN uint16_t fragment_size, \r
-IN uint16_t fragment_offset, \r
-IN BOOLEAN more_fragments )\r
-{\r
- uint16_t* p_hdr = (uint16_t*)p_ip_hdr;\r
- p_ip_hdr->length = cl_hton16( fragment_size ); // bytes\r
- p_ip_hdr->offset = cl_hton16( fragment_offset ); // 8-byte units\r
- if( more_fragments )\r
- {\r
- IP_SET_MORE_FRAGMENTS( p_ip_hdr );\r
- }\r
- else\r
- {\r
- IP_SET_LAST_FRAGMENT( p_ip_hdr );\r
- }\r
- p_ip_hdr->chksum = 0;\r
- p_ip_hdr->chksum = ipchksum( p_hdr, IP_HEADER_LENGTH(p_ip_hdr) );\r
-}\r
-\r
-static void\r
-__copy_ip_options(\r
-IN uint8_t* p_buf,\r
-IN uint8_t* p_options,\r
-IN uint32_t options_len,\r
-IN BOOLEAN copy_all )\r
-{\r
- uint32_t option_length;\r
- uint32_t total_length = 0;\r
- uint32_t copied_length = 0;\r
- uint8_t* p_src = p_options;\r
- uint8_t* p_dst = p_buf;\r
-\r
- if( p_options == NULL || options_len == 0 )\r
- return;\r
- if( copy_all )\r
- {\r
- cl_memcpy( p_dst, p_src, options_len );\r
- return;\r
- }\r
- do\r
- {\r
- if( ( *p_src ) == 0 ) // end of options list\r
- {\r
- total_length++;\r
- break;\r
- }\r
- if( ( *p_src ) == 0x1 ) // no op\r
- {\r
- p_src++;\r
- total_length++;\r
- continue;\r
- }\r
- /*from RFC791: \r
- * This option may be used between options, for example, to align\r
- * the beginning of a subsequent option on a 32 bit boundary.\r
- */\r
- if( copied_length && (copied_length % 4) )\r
- {\r
- uint32_t align = 4 - (copied_length % 4);\r
- cl_memset( p_dst, 0x1, (size_t)align );\r
- p_dst += align;\r
- copied_length += align;\r
- }\r
- option_length = *(p_src + 1);\r
-\r
- if( *p_src & 0x80 )\r
- {\r
- cl_memcpy( p_dst, p_src, option_length );\r
- p_dst += option_length;\r
- copied_length += option_length;\r
- }\r
- total_length += option_length;\r
- p_src += option_length;\r
-\r
- }while( total_length < options_len );\r
-\r
- CL_ASSERT( total_length == options_len );\r
- CL_ASSERT( copied_length <= 40 );\r
-\r
- /* padding the rest */\r
- if( options_len > copied_length )\r
- {\r
- cl_memclr( p_dst, ( options_len - copied_length ) );\r
- }\r
- return;\r
-}\r
--- /dev/null
+/*\r
+ * Copyright (c) 2005 SilverStorm Technologies. All rights reserved.\r
+ * Copyright (c) 2006 Mellanox Technologies. All rights reserved.\r
+ * Portions Copyright (c) 2008 Microsoft Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ * - Redistributions of source code must retain the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer.\r
+ *\r
+ * - Redistributions in binary form must reproduce the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer in the documentation and/or other materials\r
+ * provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id: ipoib_port.c 4506 2009-06-23 14:40:54Z xalex $\r
+ */\r
+\r
+\r
+\r
+#include "ipoib_endpoint.h"\r
+#include "ipoib_port.h"\r
+#include "ipoib_adapter.h"\r
+#include "ipoib_debug.h"\r
+#if defined(EVENT_TRACING)\r
+#ifdef offsetof\r
+#undef offsetof\r
+#endif\r
+#include "ipoib_port.tmh"\r
+#endif\r
+#include <offload.h>\r
+\r
+#include "wdm.h"\r
+#include <ntddk.h>\r
+\r
+\r
+\r
+ib_gid_t bcast_mgid_template = {\r
+ 0xff, /* multicast field */\r
+ 0x12, /* scope (to be filled in) */\r
+ 0x40, 0x1b, /* IPv4 signature */\r
+ 0xff, 0xff, /* 16 bits of P_Key (to be filled in) */\r
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 48 bits of zeros */\r
+ 0xff, 0xff, 0xff, 0xff, /* 32 bit IPv4 broadcast address */\r
+};\r
+\r
+\r
+#ifdef _DEBUG_\r
+/* Handy pointer for debug use. */\r
+ipoib_port_t *gp_ipoib_port;\r
+#endif\r
+\r
+static void __port_mcast_garbage_dpc(KDPC *p_gc_dpc,void *context,void *s_arg1, void *s_arg2);\r
+static void __port_do_mcast_garbage(ipoib_port_t* const p_port );\r
+\r
+\r
+static void __recv_cb_dpc(KDPC *p_gc_dpc,void *context,void *s_arg1, void *s_arg2);\r
+\r
+\r
+/******************************************************************************\r
+*\r
+* Declarations\r
+*\r
+******************************************************************************/\r
+static void\r
+__port_construct(\r
+ IN ipoib_port_t* const p_port );\r
+\r
+static ib_api_status_t\r
+__port_init(\r
+ IN ipoib_port_t* const p_port,\r
+ IN ipoib_adapter_t* const p_adapter,\r
+ IN ib_pnp_port_rec_t* const p_pnp_rec );\r
+\r
+static void\r
+__port_destroying(\r
+ IN cl_obj_t* const p_obj );\r
+\r
+static void\r
+__port_cleanup(\r
+ IN cl_obj_t* const p_obj );\r
+\r
+static void\r
+__port_free(\r
+ IN cl_obj_t* const p_obj );\r
+\r
+static ib_api_status_t\r
+__port_query_ca_attrs( \r
+ IN ipoib_port_t* const p_port,\r
+ IN ib_ca_attr_t** pp_ca_attrs );\r
+\r
+static void\r
+__srq_async_event_cb(\r
+IN ib_async_event_rec_t *p_event_rec );\r
+\r
+/******************************************************************************\r
+*\r
+* IB resource manager operations\r
+*\r
+******************************************************************************/\r
+static void\r
+__ib_mgr_construct(\r
+ IN ipoib_port_t* const p_port );\r
+\r
+static ib_api_status_t\r
+__ib_mgr_init(\r
+ IN ipoib_port_t* const p_port );\r
+\r
+static void\r
+__ib_mgr_destroy(\r
+ IN ipoib_port_t* const p_port );\r
+\r
+static void\r
+__qp_event(\r
+ IN ib_async_event_rec_t *p_event_rec );\r
+\r
+static void\r
+__cq_event(\r
+ IN ib_async_event_rec_t *p_event_rec );\r
+\r
+static ib_api_status_t\r
+__ib_mgr_activate(\r
+ IN ipoib_port_t* const p_port );\r
+\r
+/******************************************************************************\r
+*\r
+* Buffer manager operations.\r
+*\r
+******************************************************************************/\r
+static void\r
+__buf_mgr_construct(\r
+ IN ipoib_port_t* const p_port );\r
+\r
+static ib_api_status_t\r
+__buf_mgr_init(\r
+ IN ipoib_port_t* const p_port );\r
+\r
+static void\r
+__buf_mgr_destroy(\r
+ IN ipoib_port_t* const p_port );\r
+\r
+static cl_status_t\r
+__recv_ctor(\r
+ IN void* const p_object,\r
+ IN void* context,\r
+ OUT cl_pool_item_t** const pp_pool_item );\r
+\r
+#if !IPOIB_INLINE_RECV\r
+static void\r
+__recv_dtor(\r
+ IN const cl_pool_item_t* const p_pool_item,\r
+ IN void *context );\r
+#endif /* IPOIB_INLINE_RECV */\r
+\r
+static inline ipoib_send_desc_t*\r
+__buf_mgr_get_send(\r
+ IN ipoib_port_t* const p_port );\r
+\r
+static inline void\r
+__buf_mgr_put_send(\r
+ IN ipoib_port_t* const p_port,\r
+ IN ipoib_send_desc_t* const p_desc );\r
+\r
+static inline ipoib_recv_desc_t*\r
+__buf_mgr_get_recv(\r
+ IN ipoib_port_t* const p_port );\r
+\r
+static inline void\r
+__buf_mgr_put_recv(\r
+ IN ipoib_port_t* const p_port,\r
+ IN ipoib_recv_desc_t* const p_desc,\r
+ IN NET_BUFFER_LIST* const p_net_buffer_list OPTIONAL );\r
+\r
+static inline void\r
+__buf_mgr_put_recv_list(\r
+ IN ipoib_port_t* const p_port,\r
+ IN cl_qlist_t* const p_list );\r
+\r
+//NDIS60\r
+static inline NET_BUFFER_LIST*\r
+__buf_mgr_get_ndis_pkt(\r
+ IN ipoib_port_t* const p_port,\r
+ IN ipoib_recv_desc_t* const p_desc );\r
+\r
+\r
+/******************************************************************************\r
+*\r
+* Receive manager operations.\r
+*\r
+******************************************************************************/\r
+static void\r
+__recv_mgr_construct(\r
+ IN ipoib_port_t* const p_port );\r
+\r
+static ib_api_status_t\r
+__recv_mgr_init(\r
+ IN ipoib_port_t* const p_port );\r
+\r
+static void\r
+__recv_mgr_destroy(\r
+ IN ipoib_port_t* const p_port );\r
+\r
+/* Posts receive buffers to the receive queue. */\r
+int32_t\r
+__recv_mgr_repost(\r
+ IN ipoib_port_t* const p_port );\r
+\r
+static void\r
+__recv_cb(\r
+ IN const ib_cq_handle_t h_cq,\r
+ IN void *cq_context );\r
+\r
+static void\r
+__recv_get_endpts(\r
+ IN ipoib_port_t* const p_port,\r
+ IN ipoib_recv_desc_t* const p_desc,\r
+ IN ib_wc_t* const p_wc,\r
+ OUT ipoib_endpt_t** const pp_src,\r
+ OUT ipoib_endpt_t** const pp_dst );\r
+\r
+static int32_t\r
+__recv_mgr_filter(\r
+ IN ipoib_port_t* const p_port,\r
+ IN ib_wc_t* const p_done_wc_list,\r
+ OUT cl_qlist_t* const p_done_list,\r
+ OUT cl_qlist_t* const p_bad_list );\r
+\r
+static ib_api_status_t\r
+__recv_gen(\r
+ IN const ipoib_pkt_t* const p_ipoib,\r
+ OUT eth_pkt_t* const p_eth,\r
+ IN ipoib_endpt_t* const p_src,\r
+ IN ipoib_endpt_t* const p_dst );\r
+\r
+static ib_api_status_t\r
+__recv_dhcp(\r
+ IN ipoib_port_t* const p_port,\r
+ IN const ipoib_pkt_t* const p_ipoib,\r
+ OUT eth_pkt_t* const p_eth,\r
+ IN ipoib_endpt_t* const p_src,\r
+ IN ipoib_endpt_t* const p_dst );\r
+\r
+static ib_api_status_t\r
+__recv_arp(\r
+ IN ipoib_port_t* const p_port,\r
+ IN ib_wc_t* const p_wc,\r
+ IN const ipoib_pkt_t* const p_ipoib,\r
+ OUT eth_pkt_t* const p_eth,\r
+ IN ipoib_endpt_t** const p_src,\r
+ IN ipoib_endpt_t* const p_dst );\r
+\r
+static ib_api_status_t\r
+__recv_mgr_prepare_pkt(\r
+ IN ipoib_port_t* const p_port,\r
+ IN ipoib_recv_desc_t* const p_desc,\r
+ OUT NET_BUFFER_LIST** const pp_net_buffer_list );\r
+\r
+static uint32_t\r
+__recv_mgr_build_pkt_array(\r
+ IN ipoib_port_t* const p_port,\r
+ IN int32_t shortage,\r
+ OUT cl_qlist_t* const p_done_list,\r
+ OUT int32_t* const p_discarded );\r
+\r
+/******************************************************************************\r
+*\r
+* Send manager operations.\r
+*\r
+******************************************************************************/\r
+static void\r
+__send_mgr_construct(\r
+ IN ipoib_port_t* const p_port );\r
+\r
+static void\r
+__send_mgr_destroy(\r
+ IN ipoib_port_t* const p_port );\r
+\r
+static NDIS_STATUS\r
+__send_gen(\r
+ IN ipoib_port_t* const p_port,\r
+ IN ipoib_send_desc_t* const p_desc,\r
+ IN SCATTER_GATHER_LIST *p_sgl,\r
+ IN INT lso_data_index);\r
+\r
+static NDIS_STATUS\r
+__send_mgr_filter_ip(\r
+ IN ipoib_port_t* const p_port,\r
+ IN const eth_hdr_t* const p_eth_hdr,\r
+ IN MDL* p_mdl,\r
+ IN size_t buf_len,\r
+ IN SCATTER_GATHER_LIST *p_sgl,\r
+ IN OUT ipoib_send_desc_t* const p_desc );\r
+\r
+static NDIS_STATUS\r
+__send_mgr_filter_igmp_v2(\r
+ IN ipoib_port_t* const p_port,\r
+ IN const ip_hdr_t* const p_ip_hdr,\r
+ IN size_t iph_options_size,\r
+ IN MDL* p_mdl,\r
+ IN size_t buf_len );\r
+\r
+static NDIS_STATUS\r
+__send_mgr_filter_udp(\r
+ IN ipoib_port_t* const p_port,\r
+ IN const ip_hdr_t* const p_ip_hdr,\r
+ IN MDL* p_mdl,\r
+ IN size_t buf_len,\r
+ IN SCATTER_GATHER_LIST *p_sgl,\r
+ IN OUT ipoib_send_desc_t* const p_desc );\r
+\r
+static NDIS_STATUS\r
+__send_mgr_filter_dhcp(\r
+ IN ipoib_port_t* const p_port,\r
+ IN const udp_hdr_t* const p_udp_hdr,\r
+ IN MDL* p_mdl,\r
+ IN size_t buf_len,\r
+ IN OUT ipoib_send_desc_t* const p_desc );\r
+\r
+static NDIS_STATUS\r
+__send_mgr_filter_arp(\r
+ IN ipoib_port_t* const p_port,\r
+ IN const eth_hdr_t* const p_eth_hdr,\r
+ IN MDL* p_mdl,\r
+ IN size_t buf_len,\r
+ IN OUT ipoib_send_desc_t* const p_desc );\r
+\r
+static void\r
+__process_failed_send(\r
+ IN ipoib_port_t* const p_port,\r
+ IN ipoib_send_desc_t* const p_desc,\r
+ IN const NDIS_STATUS status,\r
+ IN ULONG send_complete_flags );\r
+\r
+static inline NDIS_STATUS\r
+__send_mgr_queue(\r
+ IN ipoib_port_t* const p_port,\r
+ IN eth_hdr_t* const p_eth_hdr,\r
+ OUT ipoib_endpt_t** const pp_endpt );\r
+\r
+static NDIS_STATUS\r
+__build_send_desc(\r
+ IN ipoib_port_t* const p_port,\r
+ IN eth_hdr_t* const p_eth_hdr,\r
+ IN MDL* const p_mdl,\r
+ IN const size_t mdl_len,\r
+ IN SCATTER_GATHER_LIST *p_sgl,\r
+ IN OUT ipoib_send_desc_t* const p_desc );\r
+\r
+\r
+static void\r
+__send_cb(\r
+ IN const ib_cq_handle_t h_cq,\r
+ IN void *cq_context );\r
+\r
+static NDIS_STATUS \r
+GetLsoHeaderSize(\r
+ IN PNET_BUFFER pNetBuffer,\r
+ IN LsoData *pLsoData,\r
+ OUT UINT *IndexOfData,\r
+ IN ipoib_hdr_t *ipoib_hdr );\r
+\r
+\r
+static NDIS_STATUS\r
+__build_lso_desc(\r
+ IN ipoib_port_t* const p_port,\r
+ IN OUT ipoib_send_desc_t* const p_desc,\r
+ IN ULONG mss,\r
+ IN SCATTER_GATHER_LIST *p_sgl,\r
+ IN int32_t hdr_idx,\r
+ IN PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO p_lso_info );\r
+\r
+static NDIS_STATUS\r
+__send_fragments(\r
+ IN ipoib_port_t* const p_port,\r
+ IN ipoib_send_desc_t* const p_desc,\r
+ IN eth_hdr_t* const p_eth_hdr,\r
+ IN ip_hdr_t* const p_ip_hdr,\r
+ IN uint32_t buf_len,\r
+ IN NDIS_BUFFER* p_ndis_buf );\r
+\r
+//TODO CM Restore\r
+#if 0\r
+static void\r
+__update_fragment_ip_hdr(\r
+IN ip_hdr_t* const p_ip_hdr,\r
+IN uint16_t fragment_size, \r
+IN uint16_t fragment_offset, \r
+IN BOOLEAN more_fragments );\r
+\r
+static void\r
+__copy_ip_options(\r
+IN uint8_t* p_buf,\r
+IN uint8_t* p_options,\r
+IN uint32_t options_len,\r
+IN BOOLEAN copy_all );\r
+#endif\r
+/******************************************************************************\r
+*\r
+* Endpoint manager operations\r
+*\r
+******************************************************************************/\r
+static void\r
+__endpt_mgr_construct(\r
+ IN ipoib_port_t* const p_port );\r
+\r
+static ib_api_status_t\r
+__endpt_mgr_init(\r
+ IN ipoib_port_t* const p_port );\r
+\r
+static void\r
+__endpt_mgr_destroy(\r
+ IN ipoib_port_t* const p_port );\r
+\r
+/****f* IPoIB/__endpt_mgr_remove_all\r
+* NAME\r
+* __endpt_mgr_remove_all\r
+*\r
+* DESCRIPTION\r
+* Removes all enpoints from the port, dereferencing them to initiate\r
+* destruction.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static void\r
+__endpt_mgr_remove_all(\r
+ IN ipoib_port_t* const p_port );\r
+/*\r
+********/\r
+\r
+static void\r
+__endpt_mgr_remove(\r
+ IN ipoib_port_t* const p_port,\r
+ IN ipoib_endpt_t* const p_endpt );\r
+\r
+static void\r
+__endpt_mgr_reset_all(\r
+ IN ipoib_port_t* const p_port );\r
+\r
+static inline NDIS_STATUS\r
+__endpt_mgr_ref(\r
+ IN ipoib_port_t* const p_port,\r
+ IN const mac_addr_t mac,\r
+ OUT ipoib_endpt_t** const pp_endpt );\r
+\r
+static inline NDIS_STATUS\r
+__endpt_mgr_get_gid_qpn(\r
+ IN ipoib_port_t* const p_port,\r
+ IN const mac_addr_t mac,\r
+ OUT ib_gid_t* const p_gid,\r
+ OUT UNALIGNED net32_t* const p_qpn );\r
+\r
+static inline ipoib_endpt_t*\r
+__endpt_mgr_get_by_gid(\r
+ IN ipoib_port_t* const p_port,\r
+ IN const ib_gid_t* const p_gid );\r
+\r
+static inline ipoib_endpt_t*\r
+__endpt_mgr_get_by_lid(\r
+ IN ipoib_port_t* const p_port,\r
+ IN const net16_t lid );\r
+\r
+static inline ib_api_status_t\r
+__endpt_mgr_insert_locked(\r
+ IN ipoib_port_t* const p_port,\r
+ IN const mac_addr_t mac,\r
+ IN ipoib_endpt_t* const p_endpt );\r
+\r
+static inline ib_api_status_t\r
+__endpt_mgr_insert(\r
+ IN ipoib_port_t* const p_port,\r
+ IN const mac_addr_t mac,\r
+ IN ipoib_endpt_t* const p_endpt );\r
+\r
+static ib_api_status_t\r
+__endpt_mgr_add_local(\r
+ IN ipoib_port_t* const p_port,\r
+ IN ib_port_info_t* const p_port_info );\r
+\r
+static ib_api_status_t\r
+__endpt_mgr_add_bcast(\r
+ IN ipoib_port_t* const p_port,\r
+ IN ib_mcast_rec_t *p_mcast_rec );\r
+\r
+/******************************************************************************\r
+*\r
+* MCast operations.\r
+*\r
+******************************************************************************/\r
+static ib_api_status_t\r
+__port_get_bcast(\r
+ IN ipoib_port_t* const p_port );\r
+\r
+static ib_api_status_t\r
+__port_join_bcast(\r
+ IN ipoib_port_t* const p_port,\r
+ IN ib_member_rec_t* const p_member_rec );\r
+\r
+static ib_api_status_t\r
+__port_create_bcast(\r
+ IN ipoib_port_t* const p_port );\r
+\r
+\r
+\r
+static void\r
+__bcast_get_cb(\r
+ IN ib_query_rec_t *p_query_rec );\r
+\r
+\r
+static void\r
+__bcast_cb(\r
+ IN ib_mcast_rec_t *p_mcast_rec );\r
+\r
+\r
+static void\r
+__mcast_cb(\r
+ IN ib_mcast_rec_t *p_mcast_rec );\r
+\r
+void\r
+__leave_error_mcast_cb(\r
+ IN void *context );\r
+\r
+\r
+static intn_t\r
+__gid_cmp(\r
+ IN const void* const p_key1,\r
+ IN const void* const p_key2 )\r
+{\r
+ return cl_memcmp( p_key1, p_key2, sizeof(ib_gid_t) );\r
+}\r
+\r
+\r
+inline void ipoib_port_ref( ipoib_port_t * p_port, int type )\r
+{\r
+ cl_obj_ref( &p_port->obj );\r
+#if DBG\r
+ cl_atomic_inc( &p_port->ref[type % ref_mask] );\r
+ if ((p_port->obj.ref_cnt % 20)==0)\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OBJ,\r
+ ("ref type %d ref_cnt %d\n", type, p_port->obj.ref_cnt) );\r
+ //TODO remove\r
+ //ASSERT (p_port->obj.ref_cnt < 100);\r
+#else\r
+ UNREFERENCED_PARAMETER(type);\r
+#endif\r
+}\r
+\r
+\r
+inline void ipoib_port_deref(ipoib_port_t * p_port, int type)\r
+{\r
+#if DBG\r
+ cl_atomic_dec( &p_port->ref[type % ref_mask] );\r
+ if ((p_port->obj.ref_cnt % 20) == 0)\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OBJ,\r
+ ("deref type %d ref_cnt %d\n", type, p_port->obj.ref_cnt) );\r
+#else\r
+ UNREFERENCED_PARAMETER(type);\r
+#endif\r
+ cl_obj_deref( &p_port->obj );\r
+\r
+}\r
+\r
+/* function returns pointer to payload that is going after IP header.\r
+* asssuming that payload and IP header are in the same buffer\r
+*/\r
+static void* GetIpPayloadPtr(const ip_hdr_t* const p_ip_hdr)\r
+{\r
+ return (void*)((uint8_t*)p_ip_hdr + IP_HEADER_LENGTH(p_ip_hdr));\r
+}\r
+\r
+/******************************************************************************\r
+*\r
+* Implementation\r
+*\r
+******************************************************************************/\r
+ib_api_status_t\r
+ipoib_create_port(\r
+ IN ipoib_adapter_t* const p_adapter,\r
+ IN ib_pnp_port_rec_t* const p_pnp_rec,\r
+ OUT ipoib_port_t** const pp_port )\r
+{\r
+ ib_api_status_t status;\r
+ ipoib_port_t *p_port;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+ CL_ASSERT( !p_adapter->p_port );\r
+\r
+ p_port = (ipoib_port_t *) cl_zalloc( sizeof(ipoib_port_t) +\r
+ (sizeof(ipoib_hdr_t) * (p_adapter->params.sq_depth - 1)) );\r
+ if( !p_port )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed to allocate ipoib_port_t (%d bytes)\n",\r
+ sizeof(ipoib_port_t)) );\r
+ return IB_INSUFFICIENT_MEMORY;\r
+ }\r
+\r
+#ifdef _DEBUG_\r
+ gp_ipoib_port = p_port;\r
+#endif\r
+\r
+ __port_construct( p_port );\r
+\r
+ status = __port_init( p_port, p_adapter, p_pnp_rec );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ipoib_port_init returned %s.\n", \r
+ p_adapter->p_ifc->get_err_str( status )) );\r
+ __port_cleanup( &p_port->obj );\r
+ __port_free( &p_port->obj );\r
+ return status;\r
+ }\r
+\r
+ *pp_port = p_port;\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+ return IB_SUCCESS;\r
+}\r
+\r
+\r
+void\r
+ipoib_port_destroy(\r
+ IN ipoib_port_t* const p_port )\r
+{\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+ CL_ASSERT( p_port );\r
+ CL_ASSERT( p_port->p_adapter );\r
+ CL_ASSERT( !p_port->p_adapter->p_port );\r
+\r
+ cl_obj_destroy( &p_port->obj );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static void\r
+__port_construct(\r
+ IN ipoib_port_t* const p_port )\r
+{\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+ p_port->state = IB_QPS_RESET;\r
+\r
+ cl_obj_construct( &p_port->obj, IPOIB_OBJ_PORT );\r
+ cl_spinlock_construct( &p_port->send_lock );\r
+ cl_spinlock_construct( &p_port->recv_lock );\r
+ __ib_mgr_construct( p_port );\r
+ __buf_mgr_construct( p_port );\r
+\r
+ __recv_mgr_construct( p_port );\r
+ __send_mgr_construct( p_port );\r
+\r
+ __endpt_mgr_construct( p_port );\r
+\r
+ KeInitializeEvent( &p_port->sa_event, NotificationEvent, TRUE );\r
+ KeInitializeEvent( &p_port->leave_mcast_event, NotificationEvent, TRUE );\r
+ \r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__port_init(\r
+ IN ipoib_port_t* const p_port,\r
+ IN ipoib_adapter_t* const p_adapter,\r
+ IN ib_pnp_port_rec_t* const p_pnp_rec )\r
+{\r
+ cl_status_t cl_status;\r
+ ib_api_status_t status;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+ p_port->port_num = p_pnp_rec->p_port_attr->port_num;\r
+ p_port->p_adapter = p_adapter;\r
+\r
+ cl_status = cl_spinlock_init( &p_port->send_lock );\r
+ if( cl_status != CL_SUCCESS )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("cl_spinlock_init returned %#x\n", cl_status) );\r
+ return IB_ERROR;\r
+ }\r
+\r
+ cl_status = cl_spinlock_init( &p_port->recv_lock );\r
+ if( cl_status != CL_SUCCESS )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("cl_spinlock_init returned %#x\n", cl_status) );\r
+ return IB_ERROR;\r
+ }\r
+\r
+ /* Initialize the IB resource manager. */\r
+ status = __ib_mgr_init( p_port );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("__ib_mgr_init returned %s\n", \r
+ p_adapter->p_ifc->get_err_str( status )) );\r
+ return status;\r
+ }\r
+\r
+ /* Initialize the buffer manager. */\r
+ status = __buf_mgr_init( p_port );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("__buf_mgr_init returned %s\n", \r
+ p_adapter->p_ifc->get_err_str( status )) );\r
+ return status;\r
+ }\r
+\r
+ /* Initialize the receive manager. */\r
+ status = __recv_mgr_init( p_port );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("__recv_mgr_init returned %s\n", \r
+ p_adapter->p_ifc->get_err_str( status )) );\r
+ return status;\r
+ }\r
+\r
+ /* Initialize the endpoint manager. */\r
+ status = __endpt_mgr_init( p_port );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("__endpt_mgr_init returned %s\n", \r
+ p_adapter->p_ifc->get_err_str( status )) );\r
+ return status;\r
+ }\r
+\r
+ KeInitializeDpc(&p_port->recv_dpc,(PKDEFERRED_ROUTINE)__recv_cb_dpc,p_port);\r
+\r
+\r
+ /* Initialize multicast garbage collector timer and DPC object */\r
+ KeInitializeDpc(&p_port->gc_dpc,(PKDEFERRED_ROUTINE)__port_mcast_garbage_dpc,p_port);\r
+ KeInitializeTimerEx(&p_port->gc_timer,SynchronizationTimer);\r
+\r
+ /* We only ever destroy from the PnP callback thread. */\r
+ cl_status = cl_obj_init( &p_port->obj, CL_DESTROY_SYNC,\r
+ __port_destroying, __port_cleanup, __port_free );\r
+\r
+#if DBG\r
+ cl_atomic_inc( &p_port->ref[ref_init] );\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OBJ,\r
+ ("ref type %d ref_cnt %d\n", ref_init, p_port->obj.ref_cnt) );\r
+#endif\r
+\r
+ if( cl_status != CL_SUCCESS )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("cl_obj_init returned %#x\n", cl_status) );\r
+ return IB_ERROR;\r
+ }\r
+\r
+ cl_status = cl_obj_insert_rel( &p_port->rel, &p_adapter->obj, &p_port->obj );\r
+ if( cl_status != CL_SUCCESS )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("cl_obj_insert_rel returned %#x\n", cl_status) );\r
+ cl_obj_destroy( &p_port->obj );\r
+ return IB_ERROR;\r
+ }\r
+\r
+#if DBG\r
+ cl_atomic_inc( &p_port->ref[ref_init] );\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_OBJ,\r
+ ("ref type %d ref_cnt %d\n", ref_init, p_port->obj.ref_cnt) );\r
+#endif\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+ return IB_SUCCESS;\r
+}\r
+\r
+\r
+static void\r
+__port_destroying(\r
+ IN cl_obj_t* const p_obj )\r
+{\r
+ ipoib_port_t *p_port;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+ CL_ASSERT( p_obj );\r
+\r
+ p_port = PARENT_STRUCT( p_obj, ipoib_port_t, obj );\r
+\r
+ ipoib_port_down( p_port );\r
+\r
+ __endpt_mgr_remove_all( p_port );\r
+\r
+#if 0\r
+ if( p_port->p_adapter->params.cm_enabled )\r
+ {\r
+ endpt_cm_buf_mgr_destroy( p_port );\r
+ ipoib_port_srq_destroy( p_port );\r
+ p_port->endpt_mgr.thread_is_done = 1;\r
+ cl_event_signal( &p_port->endpt_mgr.event );\r
+ }\r
+#endif\r
+ ASSERT(FALSE);\r
+ //TODO NDIS6.0\r
+ ipoib_port_resume( p_port, FALSE );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static void\r
+__port_cleanup(\r
+ IN cl_obj_t* const p_obj )\r
+{\r
+ ipoib_port_t *p_port;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+ CL_ASSERT( p_obj );\r
+\r
+ p_port = PARENT_STRUCT( p_obj, ipoib_port_t, obj );\r
+\r
+ /* Wait for all sends and receives to get flushed. */\r
+ while( p_port->send_mgr.depth || p_port->recv_mgr.depth )\r
+ cl_thread_suspend( 0 );\r
+\r
+ /* Destroy the send and receive managers before closing the CA. */\r
+ __ib_mgr_destroy( p_port );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static void\r
+__port_free(\r
+ IN cl_obj_t* const p_obj )\r
+{\r
+ ipoib_port_t *p_port;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+ CL_ASSERT( p_obj );\r
+\r
+ p_port = PARENT_STRUCT( p_obj, ipoib_port_t, obj );\r
+\r
+ KeCancelTimer(&p_port->gc_timer);\r
+ KeFlushQueuedDpcs();\r
+ __endpt_mgr_destroy( p_port );\r
+ __recv_mgr_destroy( p_port );\r
+ __send_mgr_destroy( p_port );\r
+ __buf_mgr_destroy( p_port );\r
+\r
+ cl_spinlock_destroy( &p_port->send_lock );\r
+ cl_spinlock_destroy( &p_port->recv_lock );\r
+\r
+ cl_obj_deinit( p_obj );\r
+ if( p_port->p_ca_attrs )\r
+ {\r
+ cl_free ( p_port->p_ca_attrs );\r
+ }\r
+ cl_free( p_port );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+\r
+/******************************************************************************\r
+*\r
+* IB resource manager implementation.\r
+*\r
+******************************************************************************/\r
+static void\r
+__ib_mgr_construct(\r
+ IN ipoib_port_t* const p_port )\r
+{\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+ cl_memclr( &p_port->ib_mgr, sizeof(ipoib_ib_mgr_t) );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__ib_mgr_init(\r
+ IN ipoib_port_t* const p_port )\r
+{\r
+ ib_api_status_t status;\r
+ ib_cq_create_t cq_create;\r
+ ib_qp_create_t qp_create;\r
+ ib_phys_create_t phys_create;\r
+ ib_phys_range_t phys_range;\r
+ uint64_t vaddr;\r
+ net32_t rkey;\r
+ ib_qp_attr_t qp_attr;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+ /* Open the CA. */\r
+ status = p_port->p_adapter->p_ifc->open_ca(\r
+ p_port->p_adapter->h_al, p_port->p_adapter->guids.ca_guid,\r
+ NULL, p_port, &p_port->ib_mgr.h_ca );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+ EVENT_IPOIB_OPEN_CA, 1, status );\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ib_open_ca returned %s\n", \r
+ p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+ return status;\r
+ }\r
+\r
+ status = __port_query_ca_attrs( p_port, &p_port->p_ca_attrs );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Query CA attributes failed\n" ) );\r
+ return status;\r
+ }\r
+#if 0\r
+ if( p_port->p_adapter->params.cm_enabled )\r
+ {\r
+ uint32_t payload_mtu = __port_attr_to_mtu_size( \r
+ p_port->p_ca_attrs->p_port_attr[p_port->port_num - 1].mtu )\r
+ - sizeof(ipoib_hdr_t);\r
+ /* adjust ipoib UD payload MTU to actual port MTU size. */\r
+ p_port->p_adapter->params.payload_mtu = \r
+ max( DEFAULT_PAYLOAD_MTU, payload_mtu );\r
+ p_port->p_adapter->params.xfer_block_size = \r
+ (sizeof(eth_hdr_t) + p_port->p_adapter->params.payload_mtu);\r
+ }\r
+#endif\r
+#if IPOIB_USE_DMA\r
+ /* init DMA only once while running MiniportInitialize */\r
+ if ( !p_port->p_adapter->reset )\r
+ {\r
+ ULONG max_phys_mapping;\r
+ if( p_port->p_adapter->params.cm_enabled )\r
+ {\r
+ max_phys_mapping = p_port->p_adapter->params.cm_xfer_block_size;\r
+ }\r
+ else if( p_port->p_adapter->params.lso )\r
+ {\r
+ max_phys_mapping = LARGE_SEND_OFFLOAD_SIZE;\r
+ }\r
+ else\r
+ {\r
+ max_phys_mapping = p_port->p_adapter->params.xfer_block_size;\r
+ }\r
+ /*if( NdisMInitializeScatterGatherDma( p_port->p_adapter->h_adapter,\r
+ TRUE, max_phys_mapping )!= NDIS_STATUS_SUCCESS )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("NdisMInitializeScatterGatherDma failed\n" ) );\r
+ return IB_INSUFFICIENT_RESOURCES;\r
+ }*/\r
+ }\r
+#endif\r
+\r
+ /* Allocate the PD. */\r
+ status = p_port->p_adapter->p_ifc->alloc_pd(\r
+ p_port->ib_mgr.h_ca, IB_PDT_UD, p_port, &p_port->ib_mgr.h_pd );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+ EVENT_IPOIB_ALLOC_PD, 1, status );\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ib_alloc_pd returned %s\n", \r
+ p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+ return status;\r
+ }\r
+\r
+ /* Allocate receive CQ. */\r
+ cq_create.size = p_port->p_adapter->params.rq_depth;\r
+ cq_create.pfn_comp_cb = __recv_cb;\r
+ cq_create.h_wait_obj = NULL;\r
+\r
+ status = p_port->p_adapter->p_ifc->create_cq(\r
+ p_port->ib_mgr.h_ca, &cq_create, p_port,\r
+ __cq_event, &p_port->ib_mgr.h_recv_cq );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+ EVENT_IPOIB_CREATE_RECV_CQ, 1, status );\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ib_create_cq returned %s.\n", \r
+ p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+ return status;\r
+ }\r
+\r
+ /* Allocate send CQ. */\r
+ cq_create.size = p_port->p_adapter->params.sq_depth;\r
+ cq_create.pfn_comp_cb = __send_cb;\r
+\r
+ status = p_port->p_adapter->p_ifc->create_cq(\r
+ p_port->ib_mgr.h_ca, &cq_create, p_port,\r
+ __cq_event, &p_port->ib_mgr.h_send_cq );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+ EVENT_IPOIB_CREATE_SEND_CQ, 1, status );\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ib_create_cq returned %s.\n", \r
+ p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+ return status;\r
+ }\r
+ \r
+ /* Allocate the QP. */\r
+ cl_memclr( &qp_create, sizeof(qp_create) );\r
+ qp_create.qp_type = IB_QPT_UNRELIABLE_DGRM;\r
+ qp_create.rq_depth = p_port->p_adapter->params.rq_depth;\r
+ qp_create.rq_sge = 2; /* To support buffers spanning pages. */\r
+ qp_create.h_rq_cq = p_port->ib_mgr.h_recv_cq;\r
+ qp_create.sq_depth = p_port->p_adapter->params.sq_depth;\r
+\r
+#define UD_QP_USED_SGE 3\r
+ qp_create.sq_sge = MAX_SEND_SGE < p_port->p_ca_attrs->max_sges ? \r
+ MAX_SEND_SGE : ( p_port->p_ca_attrs->max_sges - UD_QP_USED_SGE );\r
+ if ( !p_port->p_ca_attrs->ipoib_csum ) \r
+ { \r
+ /* checksum is not supported by device\r
+ user must specify BYPASS to explicitly cancel checksum calculation */\r
+ if (p_port->p_adapter->params.send_chksum_offload == CSUM_ENABLED)\r
+ p_port->p_adapter->params.send_chksum_offload = CSUM_DISABLED;\r
+ if (p_port->p_adapter->params.recv_chksum_offload == CSUM_ENABLED)\r
+ p_port->p_adapter->params.recv_chksum_offload = CSUM_DISABLED;\r
+ }\r
+\r
+ qp_create.h_sq_cq = p_port->ib_mgr.h_send_cq;\r
+ qp_create.sq_signaled = FALSE;\r
+ status = p_port->p_adapter->p_ifc->create_qp(\r
+ p_port->ib_mgr.h_pd, &qp_create, p_port,\r
+ __qp_event, &p_port->ib_mgr.h_qp );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+ EVENT_IPOIB_CREATE_QP, 1, status );\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ib_create_qp returned %s\n", \r
+ p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+ return status;\r
+ }\r
+ /* Query the QP so we can get our QPN. */\r
+ status = p_port->p_adapter->p_ifc->query_qp(\r
+ p_port->ib_mgr.h_qp, &qp_attr );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+ EVENT_IPOIB_QUERY_QP, 1, status );\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ib_query_qp returned %s\n", \r
+ p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+ return status;\r
+ }\r
+ p_port->ib_mgr.qpn = qp_attr.num;\r
+\r
+ /* Register all of physical memory */\r
+ phys_create.length = MEM_REG_SIZE;\r
+ phys_create.num_ranges = 1;\r
+ phys_create.range_array = &phys_range;\r
+ phys_create.buf_offset = 0;\r
+ phys_create.hca_page_size = PAGE_SIZE;\r
+ phys_create.access_ctrl = IB_AC_LOCAL_WRITE;\r
+ phys_range.base_addr = 0;\r
+ phys_range.size = MEM_REG_SIZE;\r
+ vaddr = 0;\r
+ status = p_port->p_adapter->p_ifc->reg_phys(\r
+ p_port->ib_mgr.h_pd, &phys_create, &vaddr,\r
+ &p_port->ib_mgr.lkey, &rkey, &p_port->ib_mgr.h_mr );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+ EVENT_IPOIB_REG_PHYS, 1, status );\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ib_reg_phys returned %s\n", \r
+ p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+ return status;\r
+ }\r
+\r
+ status = ipoib_port_srq_init( p_port );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ipoib_port_srq_init failed %s\n",\r
+ p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+ /* disable further CM initialization */\r
+ p_port->p_adapter->params.cm_enabled = FALSE;\r
+\r
+ NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+ EVENT_IPOIB_CONNECTED_MODE_ERR, 1, 0xbadc0de1 );\r
+\r
+ }\r
+//CM\r
+#if 0\r
+ if( p_port->p_adapter->params.cm_enabled )\r
+ {\r
+ status = endpt_cm_buf_mgr_init( p_port );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("CM Init buf mgr failed status %#x\n", status ) );\r
+ ipoib_port_srq_destroy( p_port );\r
+ p_port->p_adapter->params.cm_enabled = FALSE;\r
+\r
+ NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+ EVENT_IPOIB_CONNECTED_MODE_ERR, 1, 0xbadc0de2 );\r
+ }\r
+ else \r
+ {\r
+ if ( p_port->p_adapter->params.send_chksum_offload )\r
+ p_port->p_adapter->params.send_chksum_offload = CSUM_DISABLED;\r
+ }\r
+ }\r
+#endif\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+ return IB_SUCCESS;\r
+}\r
+\r
+static void\r
+__srq_async_event_cb(\r
+IN ib_async_event_rec_t *p_event_rec )\r
+{\r
+ ipoib_port_t* p_port = \r
+ (ipoib_port_t *)p_event_rec->context;\r
+\r
+ switch( p_event_rec->code )\r
+ {\r
+ case IB_AE_SRQ_LIMIT_REACHED:\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("SRQ ASYNC EVENT CODE %d: %s\n", \r
+ p_event_rec->code, "IB_AE_SRQ_LIMIT_REACHED" ) );\r
+ break;\r
+ case IB_AE_SRQ_CATAS_ERROR:\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("SRQ ASYNC EVENT CODE %d: %s\n", \r
+ p_event_rec->code, "IB_AE_SRQ_CATAS_ERROR" ) );\r
+ /*SRQ is in err state, must reinitialize */\r
+ p_port->p_adapter->hung = TRUE;\r
+ break;\r
+ case IB_AE_SRQ_QP_LAST_WQE_REACHED:\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("SRQ ASYNC EVENT CODE %d: %s\n", \r
+ p_event_rec->code, "IB_AE_SRQ_QP_LAST_WQE_REACHED" ) );\r
+ /*SRQ is in err state, must reinitialize */\r
+ p_port->p_adapter->hung = TRUE;\r
+ break;\r
+ default:\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ASYNC EVENT CODE ARRIVED %d(%#x)\n", \r
+ p_event_rec->code, p_event_rec->code ) );\r
+ }\r
+}\r
+\r
+ib_api_status_t\r
+ipoib_port_srq_init(\r
+ IN ipoib_port_t* const p_port )\r
+{\r
+ ib_api_status_t ib_status;\r
+ ib_srq_handle_t h_srq;\r
+ ib_srq_attr_t srq_attr;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+ \r
+ if( !p_port->p_adapter->params.cm_enabled )\r
+ return IB_SUCCESS;\r
+\r
+ srq_attr.max_sge = min( 2, p_port->p_ca_attrs->max_srq_sges );\r
+ srq_attr.srq_limit = 10;\r
+ srq_attr.max_wr = \r
+ min( (uint32_t)p_port->p_adapter->params.rq_depth * 8,\r
+ p_port->p_ca_attrs->max_srq_wrs/2 );\r
+\r
+ ib_status = p_port->p_adapter->p_ifc->create_srq( \r
+ p_port->ib_mgr.h_pd, \r
+ &srq_attr, \r
+ p_port, \r
+ __srq_async_event_cb, \r
+ &h_srq );\r
+ if( ib_status != IB_SUCCESS )\r
+ {\r
+ NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+ EVENT_IPOIB_CREATE_QP, 1, ib_status );\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ib_create_srq failed status %s\n", \r
+ p_port->p_adapter->p_ifc->get_err_str( ib_status )) );\r
+ return ib_status;\r
+ }\r
+ p_port->ib_mgr.h_srq = h_srq;\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+\r
+ return ib_status;\r
+}\r
+\r
+/* __port_query_ca_attrs() \r
+ * returns a pointer to allocated memory.\r
+ * must be released by caller.\r
+ */\r
+static ib_api_status_t\r
+__port_query_ca_attrs( \r
+ IN ipoib_port_t* const p_port,\r
+ IN ib_ca_attr_t** pp_ca_attrs )\r
+{\r
+ ib_api_status_t ib_status;\r
+ uint32_t attr_size;\r
+ ib_ca_attr_t* p_ca_attrs;\r
+\r
+ *pp_ca_attrs = NULL;\r
+\r
+ ib_status = \r
+ p_port->p_adapter->p_ifc->query_ca( p_port->ib_mgr.h_ca, NULL , &attr_size );\r
+ if( ib_status != IB_INSUFFICIENT_MEMORY )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ib_query_ca failed status %s\n",\r
+ p_port->p_adapter->p_ifc->get_err_str( ib_status )) );\r
+ goto done;\r
+ }\r
+ CL_ASSERT( attr_size );\r
+\r
+ p_ca_attrs = (ib_ca_attr_t *) cl_zalloc( attr_size );\r
+ if ( p_ca_attrs == NULL )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Allocate %d bytes failed for CA Attributes\n", attr_size ));\r
+ ib_status = IB_INSUFFICIENT_MEMORY;\r
+ goto done;\r
+ }\r
+\r
+ ib_status = \r
+ p_port->p_adapter->p_ifc->query_ca( p_port->ib_mgr.h_ca, p_ca_attrs , &attr_size );\r
+ if ( ib_status != IB_SUCCESS )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("CA attributes query failed\n") );\r
+ cl_free ( p_ca_attrs );\r
+ goto done;\r
+ }\r
+\r
+ *pp_ca_attrs = p_ca_attrs;\r
+done:\r
+ return ib_status;\r
+}\r
+\r
+void\r
+ipoib_port_srq_destroy( \r
+ IN ipoib_port_t* const p_port )\r
+{\r
+ ib_api_status_t status;\r
+\r
+ if( p_port->ib_mgr.h_srq )\r
+ {\r
+ status =\r
+ p_port->p_adapter->p_ifc->destroy_srq( p_port->ib_mgr.h_srq, NULL );\r
+ CL_ASSERT( status == IB_SUCCESS );\r
+ p_port->ib_mgr.h_srq = NULL;\r
+ }\r
+}\r
+\r
+static void\r
+__ib_mgr_destroy(\r
+ IN ipoib_port_t* const p_port )\r
+{\r
+ ib_api_status_t status;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+ if( p_port->ib_mgr.h_ca )\r
+ {\r
+ status =\r
+ p_port->p_adapter->p_ifc->close_ca( p_port->ib_mgr.h_ca, NULL );\r
+ CL_ASSERT( status == IB_SUCCESS );\r
+ p_port->ib_mgr.h_ca = NULL;\r
+ }\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+\r
+/******************************************************************************\r
+*\r
+* Buffer manager implementation.\r
+*\r
+******************************************************************************/\r
+static void\r
+__buf_mgr_construct(\r
+ IN ipoib_port_t* const p_port )\r
+{\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+ cl_qpool_construct( &p_port->buf_mgr.recv_pool );\r
+\r
+ p_port->buf_mgr.h_packet_pool = NULL;\r
+ p_port->buf_mgr.h_buffer_pool = NULL;\r
+\r
+ NdisInitializeNPagedLookasideList( &p_port->buf_mgr.send_buf_list,\r
+ NULL, NULL, 0, MAX_XFER_BLOCK_SIZE, 'bipi', 0 );\r
+\r
+ p_port->buf_mgr.h_send_pkt_pool = NULL;\r
+ p_port->buf_mgr.h_send_buf_pool = NULL;\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__buf_mgr_init(\r
+ IN ipoib_port_t* const p_port )\r
+{\r
+ cl_status_t cl_status;\r
+ ipoib_params_t *p_params;\r
+ NET_BUFFER_LIST_POOL_PARAMETERS pool_parameters;\r
+ IPOIB_ENTER(IPOIB_DBG_INIT );\r
+\r
+ CL_ASSERT( p_port );\r
+ CL_ASSERT( p_port->p_adapter );\r
+\r
+ p_params = &p_port->p_adapter->params;\r
+\r
+ /* Allocate the receive descriptor pool */\r
+ cl_status = cl_qpool_init( &p_port->buf_mgr.recv_pool,\r
+ p_params->rq_depth * p_params->recv_pool_ratio,\r
+#if IPOIB_INLINE_RECV\r
+ 0, 0, sizeof(ipoib_recv_desc_t), __recv_ctor, NULL, p_port );\r
+#else /* IPOIB_INLINE_RECV */\r
+ 0, 0, sizeof(ipoib_recv_desc_t), __recv_ctor, __recv_dtor, p_port );\r
+#endif /* IPOIB_INLINE_RECV */\r
+ if( cl_status != CL_SUCCESS )\r
+ {\r
+ NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+ EVENT_IPOIB_RECV_POOL, 1, cl_status );\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("cl_qpool_init for recvs returned %#x\n",\r
+ cl_status) );\r
+ return IB_INSUFFICIENT_MEMORY;\r
+ }\r
+\r
+ /* Allocate the NET BUFFER list pools for receive indication. */\r
+ NdisZeroMemory(&pool_parameters, sizeof(NET_BUFFER_LIST_POOL_PARAMETERS));\r
+ pool_parameters.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;\r
+ pool_parameters.Header.Revision = NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;\r
+ pool_parameters.Header.Size = sizeof(pool_parameters);\r
+ pool_parameters.ProtocolId = 0;\r
+ pool_parameters.ContextSize = 0;\r
+ pool_parameters.fAllocateNetBuffer = TRUE;\r
+ pool_parameters.PoolTag = 'CRPI';\r
+\r
+ p_port->buf_mgr.h_packet_pool = NdisAllocateNetBufferListPool(\r
+ p_port->p_adapter->h_adapter,\r
+ &pool_parameters); \r
+\r
+ if( !p_port->buf_mgr.h_packet_pool )\r
+ {\r
+ NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+ EVENT_IPOIB_RECV_PKT_POOL, 1, NDIS_STATUS_RESOURCES );\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("NdisAllocatePacketPool returned %08X\n", (UINT)NDIS_STATUS_RESOURCES) );\r
+ return IB_INSUFFICIENT_RESOURCES;\r
+ }\r
+/*\r
+ NdisAllocateBufferPool( &ndis_status, &p_port->buf_mgr.h_buffer_pool,\r
+ p_params->rq_depth );\r
+ if( ndis_status != NDIS_STATUS_SUCCESS )\r
+ {\r
+ NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+ EVENT_IPOIB_RECV_BUF_POOL, 1, ndis_status );\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("NdisAllocateBufferPool returned %08X\n", ndis_status) );\r
+ return IB_INSUFFICIENT_RESOURCES;\r
+ }\r
+*/\r
+ /* Allocate the NET buffer list pool for send formatting. */\r
+ pool_parameters.PoolTag = 'XTPI';\r
+\r
+ p_port->buf_mgr.h_send_pkt_pool = NdisAllocateNetBufferListPool(\r
+ p_port->p_adapter->h_adapter,\r
+ &pool_parameters); \r
+ if( !p_port->buf_mgr.h_send_pkt_pool)\r
+ {\r
+ NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+ EVENT_IPOIB_SEND_PKT_POOL, 1, NDIS_STATUS_RESOURCES );\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("NdisAllocatePacketPool returned %08X\n", (UINT)NDIS_STATUS_RESOURCES) );\r
+ return IB_INSUFFICIENT_RESOURCES;\r
+ }\r
+/*\r
+ NdisAllocateBufferPool( &ndis_status,\r
+ &p_port->buf_mgr.h_send_buf_pool, 1 );\r
+ if( ndis_status != NDIS_STATUS_SUCCESS )\r
+ {\r
+ NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+ EVENT_IPOIB_SEND_BUF_POOL, 1, ndis_status );\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("NdisAllocateBufferPool returned %08X\n", ndis_status) );\r
+ return IB_INSUFFICIENT_RESOURCES;\r
+ }\r
+*/\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+ return IB_SUCCESS;\r
+}\r
+\r
+\r
+static void\r
+__buf_mgr_destroy(\r
+ IN ipoib_port_t* const p_port )\r
+{\r
+ IPOIB_ENTER(IPOIB_DBG_INIT );\r
+\r
+ CL_ASSERT( p_port );\r
+\r
+ /* Destroy the send packet and buffer pools. \r
+ if( p_port->buf_mgr.h_send_buf_pool )\r
+ NdisFreeBufferPool( p_port->buf_mgr.h_send_buf_pool );*/\r
+ if( p_port->buf_mgr.h_send_pkt_pool )\r
+ NdisFreeNetBufferListPool ( p_port->buf_mgr.h_send_pkt_pool );\r
+\r
+ /* Destroy the receive packet and buffer pools. \r
+ if( p_port->buf_mgr.h_buffer_pool )\r
+ NdisFreeBufferPool( p_port->buf_mgr.h_buffer_pool );*/\r
+ if( p_port->buf_mgr.h_packet_pool )\r
+ NdisFreeNetBufferListPool ( p_port->buf_mgr.h_packet_pool );\r
+\r
+ /* Free the receive and send descriptors. */\r
+ cl_qpool_destroy( &p_port->buf_mgr.recv_pool );\r
+\r
+ /* Free the lookaside list of scratch buffers. */\r
+ NdisDeleteNPagedLookasideList( &p_port->buf_mgr.send_buf_list );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static cl_status_t\r
+__recv_ctor(\r
+ IN void* const p_object,\r
+ IN void* context,\r
+ OUT cl_pool_item_t** const pp_pool_item )\r
+{\r
+ ipoib_recv_desc_t *p_desc;\r
+ ipoib_port_t *p_port;\r
+\r
+#if IPOIB_INLINE_RECV\r
+ uint32_t ds0_len;\r
+#endif\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_ALLOC );\r
+\r
+ CL_ASSERT( p_object );\r
+ CL_ASSERT( context );\r
+\r
+ p_desc = (ipoib_recv_desc_t*)p_object;\r
+ p_port = (ipoib_port_t*)context;\r
+\r
+ /* Setup the work request. */\r
+ p_desc->wr.ds_array = p_desc->local_ds;\r
+ p_desc->wr.wr_id = (uintn_t)p_desc;\r
+\r
+#if IPOIB_INLINE_RECV\r
+ /* Sanity check on the receive buffer layout */\r
+ CL_ASSERT( (void*)&p_desc->buf.eth.pkt.type ==\r
+ (void*)&p_desc->buf.ib.pkt.type );\r
+ CL_ASSERT( sizeof(recv_buf_t) == sizeof(ipoib_pkt_t) + sizeof(ib_grh_t) );\r
+\r
+ /* Setup the local data segment. */\r
+ p_desc->local_ds[0].vaddr = cl_get_physaddr( &p_desc->buf );\r
+ p_desc->local_ds[0].lkey = p_port->ib_mgr.lkey;\r
+ ds0_len =\r
+ PAGE_SIZE - ((uint32_t)p_desc->local_ds[0].vaddr & (PAGE_SIZE - 1));\r
+ if( ds0_len >= sizeof(recv_buf_t) )\r
+ {\r
+ /* The whole buffer is within a page. */\r
+ p_desc->local_ds[0].length = ds0_len;\r
+ p_desc->wr.num_ds = 1;\r
+ }\r
+ else\r
+ {\r
+ /* The buffer crosses page boundaries. */\r
+ p_desc->local_ds[0].length = ds0_len;\r
+ p_desc->local_ds[1].vaddr = cl_get_physaddr( \r
+ ((uint8_t*)&p_desc->buf) + ds0_len );\r
+ p_desc->local_ds[1].lkey = p_port->ib_mgr.lkey;\r
+ p_desc->local_ds[1].length = sizeof(recv_buf_t) - ds0_len;\r
+ p_desc->wr.num_ds = 2;\r
+ }\r
+#else /* IPOIB_INLINE_RECV */\r
+ /* Allocate the receive buffer. */\r
+ p_desc->p_buf = (recv_buf_t*)cl_zalloc( sizeof(recv_buf_t) );\r
+ if( !p_desc->p_buf )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed to allocate receive buffer.\n") );\r
+ return CL_INSUFFICIENT_MEMORY;\r
+ }\r
+\r
+ /* Sanity check on the receive buffer layout */\r
+ CL_ASSERT( (void*)&p_desc->p_buf->eth.pkt.type ==\r
+ (void*)&p_desc->p_buf->ib.pkt.type );\r
+\r
+ /* Setup the local data segment. */\r
+ p_desc->local_ds[0].vaddr = cl_get_physaddr( p_desc->p_buf );\r
+ p_desc->local_ds[0].length = sizeof(ipoib_pkt_t) + sizeof(ib_grh_t);\r
+ p_desc->local_ds[0].lkey = p_port->ib_mgr.lkey;\r
+ p_desc->wr.num_ds = 1;\r
+#endif /* IPOIB_INLINE_RECV */\r
+\r
+ *pp_pool_item = &p_desc->item;\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_ALLOC );\r
+ return CL_SUCCESS;\r
+}\r
+\r
+\r
+#if !IPOIB_INLINE_RECV\r
+static void\r
+__recv_dtor(\r
+ IN const cl_pool_item_t* const p_pool_item,\r
+ IN void *context )\r
+{\r
+ ipoib_recv_desc_t *p_desc;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_ALLOC );\r
+\r
+ UNUSED_PARAM( context );\r
+\r
+ p_desc = PARENT_STRUCT( p_pool_item, ipoib_recv_desc_t, item );\r
+\r
+ if( p_desc->p_buf )\r
+ cl_free( p_desc->p_buf );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_ALLOC );\r
+}\r
+#endif\r
+\r
+\r
+static inline ipoib_recv_desc_t*\r
+__buf_mgr_get_recv(\r
+ IN ipoib_port_t* const p_port )\r
+{\r
+ ipoib_recv_desc_t *p_desc;\r
+ IPOIB_ENTER( IPOIB_DBG_RECV );\r
+ p_desc = (ipoib_recv_desc_t*)cl_qpool_get( &p_port->buf_mgr.recv_pool );\r
+ /* Reference the port object for the send. */\r
+ if( p_desc )\r
+ {\r
+ ipoib_port_ref( p_port, ref_get_recv );\r
+ CL_ASSERT( p_desc->wr.wr_id == (uintn_t)p_desc );\r
+#if IPOIB_INLINE_RECV\r
+ CL_ASSERT( p_desc->local_ds[0].vaddr ==\r
+ cl_get_physaddr( &p_desc->buf ) );\r
+#else /* IPOIB_INLINE_RECV */\r
+ CL_ASSERT( p_desc->local_ds[0].vaddr ==\r
+ cl_get_physaddr( p_desc->p_buf ) );\r
+ CL_ASSERT( p_desc->local_ds[0].length ==\r
+ (sizeof(ipoib_pkt_t) + sizeof(ib_grh_t)) );\r
+#endif /* IPOIB_INLINE_RECV */\r
+ CL_ASSERT( p_desc->local_ds[0].lkey == p_port->ib_mgr.lkey );\r
+ }\r
+ IPOIB_EXIT( IPOIB_DBG_RECV );\r
+ return p_desc;\r
+}\r
+\r
+\r
+//NDIS60\r
+static inline void\r
+__buf_mgr_put_recv(\r
+ IN ipoib_port_t* const p_port,\r
+ IN ipoib_recv_desc_t* const p_desc,\r
+ IN NET_BUFFER_LIST* const p_net_buffer_list OPTIONAL )\r
+{\r
+ NET_BUFFER *p_buf = NULL;\r
+ MDL *p_mdl = NULL;\r
+ IPOIB_ENTER(IPOIB_DBG_RECV );\r
+\r
+ if( p_net_buffer_list )\r
+ {\r
+ NET_BUFFER_LIST_NEXT_NBL(p_net_buffer_list) = NULL;\r
+ p_buf = NET_BUFFER_LIST_FIRST_NB(p_net_buffer_list);\r
+ CL_ASSERT( p_buf );\r
+ p_mdl = NET_BUFFER_FIRST_MDL(p_buf);\r
+ CL_ASSERT( p_mdl );\r
+ NdisFreeMdl(p_mdl);\r
+ NdisFreeNetBufferList(p_net_buffer_list);\r
+ }\r
+\r
+ /* Return the descriptor to its pools. */\r
+ cl_qpool_put( &p_port->buf_mgr.recv_pool, &p_desc->item );\r
+\r
+ /*\r
+ * Dereference the port object since the receive is no longer outstanding.\r
+ */\r
+ ipoib_port_deref( p_port, ref_get_recv );\r
+ IPOIB_EXIT( IPOIB_DBG_RECV );\r
+}\r
+\r
+\r
+static inline void\r
+__buf_mgr_put_recv_list(\r
+ IN ipoib_port_t* const p_port,\r
+ IN cl_qlist_t* const p_list )\r
+{\r
+ //IPOIB_ENTER( IPOIB_DBG_RECV );\r
+ cl_qpool_put_list( &p_port->buf_mgr.recv_pool, p_list );\r
+ //IPOIB_EXIT( IPOIB_DBG_RECV );\r
+}\r
+\r
+\r
+static inline NET_BUFFER_LIST*\r
+__buf_mgr_get_ndis_pkt(\r
+ IN ipoib_port_t* const p_port,\r
+ IN ipoib_recv_desc_t* const p_desc )\r
+{\r
+ NET_BUFFER_LIST *p_net_buffer_list;\r
+ MDL *p_mdl;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_RECV );\r
+\r
+ p_mdl = NdisAllocateMdl(p_port->p_adapter->h_adapter,\r
+ &p_desc->buf.eth.pkt,\r
+ p_desc->len );\r
+ if( !p_mdl )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed to allocate MDL\n") );\r
+ return NULL;\r
+ }\r
+\r
+ p_net_buffer_list = NdisAllocateNetBufferAndNetBufferList(\r
+ p_port->buf_mgr.h_packet_pool,\r
+ 0,\r
+ 0,\r
+ p_mdl,\r
+ 0,\r
+ 0);\r
+\r
+ if( !p_net_buffer_list )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed to allocate NET_BUFFER_LIST\n") );\r
+ NdisFreeMdl(p_mdl);\r
+ return NULL;\r
+ }\r
+\r
+ NET_BUFFER_LIST_NEXT_NBL(p_net_buffer_list) = NULL;\r
+ IPOIB_PORT_FROM_PACKET( p_net_buffer_list ) = p_port;\r
+ IPOIB_RECV_FROM_PACKET( p_net_buffer_list ) = p_desc;\r
+ p_net_buffer_list->SourceHandle = p_port->p_adapter->h_adapter;\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_RECV );\r
+ return p_net_buffer_list;\r
+}\r
+\r
+\r
+/******************************************************************************\r
+*\r
+* Receive manager implementation.\r
+*\r
+******************************************************************************/\r
+static void\r
+__recv_mgr_construct(\r
+ IN ipoib_port_t* const p_port )\r
+{\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+ cl_qlist_init( &p_port->recv_mgr.done_list );\r
+\r
+ p_port->recv_mgr.recv_pkt_array = NULL;\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__recv_mgr_init(\r
+ IN ipoib_port_t* const p_port )\r
+{\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+ /* Allocate the NDIS_PACKET pointer array for indicating receives. */\r
+ p_port->recv_mgr.recv_pkt_array = (NET_BUFFER_LIST **)cl_malloc(\r
+ sizeof(NET_BUFFER_LIST*) * p_port->p_adapter->params.rq_depth );\r
+ if( !p_port->recv_mgr.recv_pkt_array )\r
+ {\r
+ NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+ EVENT_IPOIB_RECV_PKT_ARRAY, 0 );\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("cl_malloc for PNDIS_PACKET array failed.\n") );\r
+ return IB_INSUFFICIENT_MEMORY;\r
+ }\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+ return IB_SUCCESS;\r
+}\r
+\r
+\r
+static void\r
+__recv_mgr_destroy(\r
+ IN ipoib_port_t* const p_port )\r
+{\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+ CL_ASSERT( cl_is_qlist_empty( &p_port->recv_mgr.done_list ) );\r
+ CL_ASSERT( !p_port->recv_mgr.depth );\r
+\r
+ if( p_port->recv_mgr.recv_pkt_array )\r
+ cl_free( p_port->recv_mgr.recv_pkt_array );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+/*\r
+ * Posts receive buffers to the receive queue and returns the number\r
+ * of receives needed to bring the RQ to its low water mark. Note\r
+ * that the value is signed, and can go negative. All tests must\r
+ * be for > 0.\r
+ */\r
+int32_t\r
+__recv_mgr_repost(\r
+ IN ipoib_port_t* const p_port )\r
+{\r
+ ipoib_recv_desc_t *p_head = NULL, *p_tail = NULL, *p_next;\r
+ ib_api_status_t status;\r
+ ib_recv_wr_t *p_failed;\r
+ PERF_DECLARE( GetRecv );\r
+ PERF_DECLARE( PostRecv );\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_RECV );\r
+\r
+ CL_ASSERT( p_port );\r
+ cl_obj_lock( &p_port->obj );\r
+ if( p_port->state != IB_QPS_RTS )\r
+ {\r
+ cl_obj_unlock( &p_port->obj );\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_RECV,\r
+ ("Port in invalid state. Not reposting.\n") );\r
+ return 0;\r
+ }\r
+ ipoib_port_ref( p_port, ref_repost );\r
+ cl_obj_unlock( &p_port->obj );\r
+\r
+ while( p_port->recv_mgr.depth < p_port->p_adapter->params.rq_depth )\r
+ {\r
+ /* Pull receives out of the pool and chain them up. */\r
+ cl_perf_start( GetRecv );\r
+ p_next = __buf_mgr_get_recv( p_port );\r
+ cl_perf_stop( &p_port->p_adapter->perf, GetRecv );\r
+ if( !p_next )\r
+ {\r
+ IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_RECV,\r
+ ("Out of receive descriptors! recv queue depth 0x%x\n",p_port->recv_mgr.depth) );\r
+ break;\r
+ }\r
+\r
+ if( !p_tail )\r
+ {\r
+ p_tail = p_next;\r
+ p_next->wr.p_next = NULL;\r
+ }\r
+ else\r
+ {\r
+ p_next->wr.p_next = &p_head->wr;\r
+ }\r
+\r
+ p_head = p_next;\r
+\r
+ p_port->recv_mgr.depth++;\r
+ }\r
+\r
+ if( p_head )\r
+ {\r
+ cl_perf_start( PostRecv );\r
+ status = p_port->p_adapter->p_ifc->post_recv(\r
+ p_port->ib_mgr.h_qp, &p_head->wr, &p_failed );\r
+ cl_perf_stop( &p_port->p_adapter->perf, PostRecv );\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ip_post_recv returned %s\n", \r
+ p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+ /* return the descriptors to the pool */\r
+ while( p_failed )\r
+ {\r
+ p_head = PARENT_STRUCT( p_failed, ipoib_recv_desc_t, wr );\r
+ p_failed = p_failed->p_next;\r
+\r
+ __buf_mgr_put_recv( p_port, p_head, NULL );\r
+ p_port->recv_mgr.depth--;\r
+ }\r
+ }\r
+ }\r
+\r
+ ipoib_port_deref( p_port, ref_repost );\r
+ IPOIB_EXIT( IPOIB_DBG_RECV );\r
+ return p_port->p_adapter->params.rq_low_watermark - p_port->recv_mgr.depth;\r
+}\r
+\r
+void\r
+ipoib_return_net_buffer_list(\r
+ IN NDIS_HANDLE adapter_context,\r
+ IN NET_BUFFER_LIST *p_net_buffer_lists,\r
+ IN ULONG return_flags)\r
+{\r
+// cl_list_item_t *p_item;\r
+ ipoib_port_t *p_port;\r
+ ipoib_recv_desc_t *p_desc;\r
+ NET_BUFFER_LIST *cur_net_buffer_list,*next_net_buffer_list;\r
+// ib_api_status_t status = IB_NOT_DONE;\r
+// int32_t shortage;\r
+// ULONG complete_flags = 0;\r
+ PERF_DECLARE( ReturnPacket );\r
+ PERF_DECLARE( ReturnPutRecv );\r
+ PERF_DECLARE( ReturnRepostRecv );\r
+ PERF_DECLARE( ReturnPreparePkt );\r
+ PERF_DECLARE( ReturnNdisIndicate );\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_RECV );\r
+\r
+ UNUSED_PARAM( return_flags );\r
+\r
+ p_port = ((ipoib_adapter_t*)adapter_context)->p_port;\r
+ CL_ASSERT( p_net_buffer_lists );\r
+\r
+ cl_perf_start( ReturnPacket );\r
+ cl_spinlock_acquire( &p_port->recv_lock );\r
+ for (cur_net_buffer_list = p_net_buffer_lists;\r
+ cur_net_buffer_list != NULL;\r
+ cur_net_buffer_list = next_net_buffer_list)\r
+ {\r
+ next_net_buffer_list = NET_BUFFER_LIST_NEXT_NBL(cur_net_buffer_list);\r
+\r
+ /* Get the port and descriptor from the packet. */\r
+ CL_ASSERT(p_port == IPOIB_PORT_FROM_PACKET( cur_net_buffer_list ));\r
+ p_desc = IPOIB_RECV_FROM_PACKET( cur_net_buffer_list );\r
+\r
+ \r
+ //TODO: NDIS60, rewrite this block\r
+ /* Get descriptor from the packet. */\r
+#if 0\r
+ if( p_desc->type == PKT_TYPE_CM_UCAST )\r
+ {\r
+ NDIS_BUFFER *p_buf;\r
+\r
+ /* Unchain the NDIS buffer. */\r
+ NdisUnchainBufferAtFront( p_packet, &p_buf );\r
+ CL_ASSERT( p_buf );\r
+ /* Return the NDIS packet and NDIS buffer to their pools. */\r
+ NdisDprFreePacketNonInterlocked( p_packet );\r
+ NdisFreeBuffer( p_buf );\r
+\r
+ endpt_cm_buf_mgr_put_recv( &p_port->cm_buf_mgr, (ipoib_cm_desc_t *)p_desc );\r
+ status = endpt_cm_post_recv( p_port );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Post Recv QP failed\n" ) );\r
+ }\r
+ cl_spinlock_release( &p_port->recv_lock );\r
+ return;\r
+ }\r
+#endif\r
+\r
+ cl_perf_start( ReturnPutRecv );\r
+ __buf_mgr_put_recv( p_port, p_desc, cur_net_buffer_list );\r
+ cl_perf_stop( &p_port->p_adapter->perf, ReturnPutRecv );\r
+ }\r
+#if 0 \r
+ /* Repost buffers. */\r
+ cl_perf_start( ReturnRepostRecv );\r
+ shortage = __recv_mgr_repost( p_port );\r
+ cl_perf_stop( &p_port->p_adapter->perf, ReturnRepostRecv );\r
+\r
+ for( p_item = cl_qlist_remove_head( &p_port->recv_mgr.done_list );\r
+ p_item != cl_qlist_end( &p_port->recv_mgr.done_list );\r
+ p_item = cl_qlist_remove_head( &p_port->recv_mgr.done_list ) )\r
+ {\r
+ p_desc = (ipoib_recv_desc_t*)p_item;\r
+\r
+ cl_perf_start( ReturnPreparePkt );\r
+ status = __recv_mgr_prepare_pkt( p_port, p_desc, &cur_net_buffer_list );\r
+ cl_perf_stop( &p_port->p_adapter->perf, ReturnPreparePkt );\r
+ if( status == IB_SUCCESS )\r
+ {\r
+ if( shortage > 0 )\r
+ NET_BUFFER_LIST_STATUS( cur_net_buffer_list) = NDIS_STATUS_RESOURCES;\r
+ else\r
+ NET_BUFFER_LIST_STATUS( cur_net_buffer_list) = NDIS_STATUS_SUCCESS;\r
+\r
+ cl_spinlock_release( &p_port->recv_lock );\r
+ NET_BUFFER_LIST_NEXT_NBL(cur_net_buffer_list) = NULL;\r
+ cl_perf_start( ReturnNdisIndicate );\r
+ NdisMRecvIndicate( p_port->p_adapter->h_adapter,\r
+ cur_net_buffer_list, complete_flags );\r
+ cl_perf_stop( &p_port->p_adapter->perf, ReturnNdisIndicate );\r
+ cl_spinlock_acquire( &p_port->recv_lock );\r
+\r
+ if( shortage > 0 )\r
+ {\r
+ cl_perf_start( ReturnPutRecv );\r
+ __buf_mgr_put_recv( p_port, p_desc, cur_net_buffer_list );\r
+ cl_perf_stop( &p_port->p_adapter->perf, ReturnPutRecv );\r
+\r
+ /* Repost buffers. */\r
+ cl_perf_start( ReturnRepostRecv );\r
+ shortage = __recv_mgr_repost( p_port );\r
+ cl_perf_stop( &p_port->p_adapter->perf, ReturnRepostRecv );\r
+ }\r
+ }\r
+ else if( status != IB_NOT_DONE )\r
+ {\r
+ IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_RECV,\r
+ ("__recv_mgr_prepare_pkt returned %s\n",\r
+ p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+ /* Return the item to the head of the list. */\r
+ cl_qlist_insert_head( &p_port->recv_mgr.done_list, p_item );\r
+ break;\r
+ }\r
+ }\r
+ #endif\r
+ cl_spinlock_release( &p_port->recv_lock );\r
+ cl_perf_stop( &p_port->p_adapter->perf, ReturnPacket );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_RECV );\r
+}\r
+\r
+static void __recv_cb_dpc(KDPC *p_gc_dpc,void *context,void * s_arg1 , void * s_arg2)\r
+{\r
+\r
+ ipoib_port_t *p_port = (ipoib_port_t *) context;\r
+\r
+ UNREFERENCED_PARAMETER(p_gc_dpc);\r
+ UNREFERENCED_PARAMETER(s_arg1);\r
+ UNREFERENCED_PARAMETER(s_arg2);\r
+\r
+\r
+ __recv_cb(NULL, p_port);\r
+ ipoib_port_deref( p_port, ref_recv_cb );\r
+\r
+\r
+}\r
+\r
+\r
+static void\r
+__recv_cb(\r
+ IN const ib_cq_handle_t h_cq,\r
+ IN void *cq_context )\r
+{\r
+ ipoib_port_t *p_port;\r
+ ib_api_status_t status;\r
+ ib_wc_t wc[MAX_RECV_WC], *p_free, *p_wc;\r
+ int32_t pkt_cnt, recv_cnt = 0, shortage, discarded;\r
+ cl_qlist_t done_list, bad_list;\r
+ size_t i;\r
+ ULONG recv_complete_flags = 0;\r
+\r
+ PERF_DECLARE( RecvCompBundle );\r
+ PERF_DECLARE( RecvCb );\r
+ PERF_DECLARE( PollRecv );\r
+ PERF_DECLARE( RepostRecv );\r
+ PERF_DECLARE( FilterRecv );\r
+ PERF_DECLARE( BuildPktArray );\r
+ PERF_DECLARE( RecvNdisIndicate );\r
+ PERF_DECLARE( RearmRecv );\r
+ PERF_DECLARE( PutRecvList );\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_RECV );\r
+\r
+ cl_perf_clr( RecvCompBundle );\r
+\r
+ cl_perf_start( RecvCb );\r
+//return ;\r
+ UNUSED_PARAM( h_cq );\r
+\r
+ NDIS_SET_SEND_COMPLETE_FLAG(recv_complete_flags, NDIS_RECEIVE_FLAGS_DISPATCH_LEVEL );\r
+\r
+ p_port = (ipoib_port_t*)cq_context;\r
+\r
+ cl_qlist_init( &done_list );\r
+ cl_qlist_init( &bad_list );\r
+\r
+ ipoib_port_ref( p_port, ref_recv_cb );\r
+ for( i = 0; i < MAX_RECV_WC; i++ )\r
+ wc[i].p_next = &wc[i + 1];\r
+ wc[MAX_RECV_WC - 1].p_next = NULL;\r
+\r
+ /*\r
+ * We'll be accessing the endpoint map so take a reference\r
+ * on it to prevent modifications.\r
+ */\r
+ cl_obj_lock( &p_port->obj );\r
+ cl_atomic_inc( &p_port->endpt_rdr );\r
+ cl_obj_unlock( &p_port->obj );\r
+\r
+ do\r
+ {\r
+ /* If we get here, then the list of WCs is intact. */\r
+ p_free = wc;\r
+\r
+ cl_perf_start( PollRecv );\r
+ status = p_port->p_adapter->p_ifc->poll_cq(\r
+ p_port->ib_mgr.h_recv_cq, &p_free, &p_wc );\r
+ cl_perf_stop( &p_port->p_adapter->perf, PollRecv );\r
+ CL_ASSERT( status == IB_SUCCESS || status == IB_NOT_FOUND );\r
+\r
+ /* Look at the payload now and filter ARP and DHCP packets. */\r
+ cl_perf_start( FilterRecv );\r
+ recv_cnt += __recv_mgr_filter( p_port, p_wc, &done_list, &bad_list );\r
+ cl_perf_stop( &p_port->p_adapter->perf, FilterRecv );\r
+\r
+ } while( (!p_free) && (recv_cnt < 128));\r
+\r
+ /* We're done looking at the endpoint map, release the reference. */\r
+ cl_atomic_dec( &p_port->endpt_rdr );\r
+\r
+ cl_perf_log( &p_port->p_adapter->perf, RecvCompBundle, recv_cnt );\r
+\r
+ cl_spinlock_acquire( &p_port->recv_lock );\r
+\r
+ /* Update our posted depth. */\r
+ p_port->recv_mgr.depth -= recv_cnt;\r
+\r
+ /* Return any discarded receives to the pool */\r
+ cl_perf_start( PutRecvList );\r
+ __buf_mgr_put_recv_list( p_port, &bad_list );\r
+ cl_perf_stop( &p_port->p_adapter->perf, PutRecvList );\r
+\r
+ do\r
+ {\r
+ int32_t cnt;\r
+ /* Repost ASAP so we don't starve the RQ. */\r
+ cl_perf_start( RepostRecv );\r
+ shortage = __recv_mgr_repost( p_port );\r
+ cl_perf_stop( &p_port->p_adapter->perf, RepostRecv );\r
+\r
+ cl_perf_start( BuildPktArray );\r
+ /* Notify NDIS of any and all possible receive buffers. */\r
+ pkt_cnt = __recv_mgr_build_pkt_array(\r
+ p_port, shortage, &done_list, &discarded );\r
+ cl_perf_stop( &p_port->p_adapter->perf, BuildPktArray );\r
+\r
+ /* Only indicate receives if we actually had any. */\r
+ if( discarded && shortage > 0 )\r
+ {\r
+ /* We may have thrown away packets, and have a shortage */\r
+ cl_perf_start( RepostRecv );\r
+ __recv_mgr_repost( p_port );\r
+ cl_perf_stop( &p_port->p_adapter->perf, RepostRecv );\r
+ }\r
+\r
+ if( !pkt_cnt )\r
+ break;\r
+\r
+ cl_spinlock_release( &p_port->recv_lock );\r
+ for( cnt = 0; cnt < pkt_cnt -1; cnt++)\r
+ {\r
+ NET_BUFFER_LIST_NEXT_NBL(p_port->recv_mgr.recv_pkt_array[cnt]) = \r
+ p_port->recv_mgr.recv_pkt_array[cnt + 1];\r
+ }\r
+ cl_perf_start( RecvNdisIndicate );\r
+#ifndef NDIS_DEFAULT_PORT_NUMBER\r
+#define NDIS_DEFAULT_PORT_NUMBER 0\r
+#endif\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Indicate NDIS with %d received NBs\n",\r
+ pkt_cnt) );\r
+ NdisMIndicateReceiveNetBufferLists(\r
+ p_port->p_adapter->h_adapter,\r
+ p_port->recv_mgr.recv_pkt_array[0],\r
+ NDIS_DEFAULT_PORT_NUMBER,\r
+ pkt_cnt,\r
+ recv_complete_flags);\r
+\r
+ cl_perf_stop( &p_port->p_adapter->perf, RecvNdisIndicate );\r
+\r
+ /*\r
+ * Cap the number of receives to put back to what we just indicated\r
+ * with NDIS_STATUS_RESOURCES.\r
+ */\r
+ if( shortage > 0 )\r
+ {\r
+ if( pkt_cnt < shortage )\r
+ shortage = pkt_cnt;\r
+\r
+ /* Return all but the last packet to the pool. */\r
+ cl_spinlock_acquire( &p_port->recv_lock );\r
+ while( shortage-- > 1 )\r
+ {\r
+ __buf_mgr_put_recv( p_port,\r
+ (ipoib_recv_desc_t *)IPOIB_RECV_FROM_PACKET( p_port->recv_mgr.recv_pkt_array[shortage] ),\r
+ p_port->recv_mgr.recv_pkt_array[shortage] );\r
+ }\r
+ cl_spinlock_release( &p_port->recv_lock );\r
+\r
+ /*\r
+ * Return the last packet as if NDIS returned it, so that we repost\r
+ * and report any other pending receives.\r
+ */\r
+ ipoib_return_net_buffer_list( NULL, p_port->recv_mgr.recv_pkt_array[0],recv_complete_flags );\r
+ }\r
+ cl_spinlock_acquire( &p_port->recv_lock );\r
+\r
+ } while( pkt_cnt );\r
+ cl_spinlock_release( &p_port->recv_lock );\r
+\r
+ if (p_free ) {\r
+ /*\r
+ * Rearm after filtering to prevent contention on the enpoint maps\r
+ * and eliminate the possibility of having a call to\r
+ * __endpt_mgr_insert find a duplicate.\r
+ */\r
+ cl_perf_start( RearmRecv );\r
+ status = p_port->p_adapter->p_ifc->rearm_cq(\r
+ p_port->ib_mgr.h_recv_cq, FALSE );\r
+ cl_perf_stop( &p_port->p_adapter->perf, RearmRecv );\r
+ CL_ASSERT( status == IB_SUCCESS );\r
+\r
+ ipoib_port_deref( p_port, ref_recv_cb );\r
+ } else {\r
+ // Please note the reference is still up\r
+ KeInsertQueueDpc(&p_port->recv_dpc, NULL, NULL);\r
+ }\r
+\r
+ cl_perf_stop( &p_port->p_adapter->perf, RecvCb );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_RECV );\r
+}\r
+\r
+\r
+static void\r
+__recv_get_endpts(\r
+ IN ipoib_port_t* const p_port,\r
+ IN ipoib_recv_desc_t* const p_desc,\r
+ IN ib_wc_t* const p_wc,\r
+ OUT ipoib_endpt_t** const pp_src,\r
+ OUT ipoib_endpt_t** const pp_dst )\r
+{\r
+ ib_api_status_t status;\r
+ mac_addr_t mac;\r
+ PERF_DECLARE( GetEndptByGid );\r
+ PERF_DECLARE( GetEndptByLid );\r
+ PERF_DECLARE( EndptInsert );\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_RECV );\r
+\r
+ /* Setup our shortcut pointers based on whether GRH is valid. */\r
+ if( p_wc->recv.ud.recv_opt & IB_RECV_OPT_GRH_VALID )\r
+ {\r
+ /* Lookup the source endpoints based on GID. */\r
+ cl_perf_start( GetEndptByGid );\r
+ *pp_src =\r
+#if IPOIB_INLINE_RECV\r
+ __endpt_mgr_get_by_gid( p_port, &p_desc->buf.ib.grh.src_gid );\r
+#else /* IPOIB_INLINE_RECV */\r
+ __endpt_mgr_get_by_gid( p_port, &p_desc->p_buf->ib.grh.src_gid );\r
+#endif /* IPOIB_INLINE_RECV */\r
+ cl_perf_stop( &p_port->p_adapter->perf, GetEndptByGid );\r
+\r
+ /*\r
+ * Lookup the destination endpoint based on GID.\r
+ * This is used along with the packet filter to determine\r
+ * whether to report this to NDIS.\r
+ */\r
+ cl_perf_start( GetEndptByGid );\r
+ *pp_dst =\r
+#if IPOIB_INLINE_RECV\r
+ __endpt_mgr_get_by_gid( p_port, &p_desc->buf.ib.grh.dest_gid );\r
+#else /* IPOIB_INLINE_RECV */\r
+ __endpt_mgr_get_by_gid( p_port, &p_desc->p_buf->ib.grh.dest_gid );\r
+#endif /* IPOIB_INLINE_RECV */\r
+ cl_perf_stop( &p_port->p_adapter->perf, GetEndptByGid );\r
+\r
+ /*\r
+ * Create the source endpoint if it does not exist. Note that we\r
+ * can only do this for globally routed traffic since we need the\r
+ * information from the GRH to generate the MAC.\r
+ */\r
+ if( !*pp_src )\r
+ {\r
+ status = ipoib_mac_from_guid(\r
+#if IPOIB_INLINE_RECV\r
+ p_desc->buf.ib.grh.src_gid.unicast.interface_id, p_port->p_adapter->params.guid_mask, &mac );\r
+#else /* IPOIB_INLINE_RECV */\r
+ p_desc->p_buf->ib.grh.src_gid.unicast.interface_id, p_port->p_adapter->params.guid_mask, &mac );\r
+#endif /* IPOIB_INLINE_RECV */\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ipoib_mac_from_guid returned %s\n",\r
+ p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+ return;\r
+ }\r
+\r
+ /* Create the endpoint. */\r
+#if IPOIB_INLINE_RECV\r
+ *pp_src = ipoib_endpt_create( &p_desc->buf.ib.grh.src_gid,\r
+#else /* IPOIB_INLINE_RECV */\r
+ *pp_src = ipoib_endpt_create( &p_desc->p_buf->ib.grh.src_gid,\r
+#endif /* IPOIB_INLINE_RECV */\r
+ p_wc->recv.ud.remote_lid, p_wc->recv.ud.remote_qp );\r
+ if( !*pp_src )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ipoib_endpt_create failed\n") );\r
+ return;\r
+ }\r
+ cl_perf_start( EndptInsert );\r
+ cl_obj_lock( &p_port->obj );\r
+ status = __endpt_mgr_insert( p_port, mac, *pp_src );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ cl_obj_unlock( &p_port->obj );\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("__endpt_mgr_insert returned %s\n",\r
+ p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+ *pp_src = NULL;\r
+ return;\r
+ }\r
+ cl_obj_unlock( &p_port->obj );\r
+ cl_perf_stop( &p_port->p_adapter->perf, EndptInsert );\r
+ }\r
+ }\r
+ else\r
+ {\r
+ /*\r
+ * Lookup the remote endpoint based on LID. Note that only\r
+ * unicast traffic can be LID routed.\r
+ */\r
+ cl_perf_start( GetEndptByLid );\r
+ *pp_src = __endpt_mgr_get_by_lid( p_port, p_wc->recv.ud.remote_lid );\r
+ cl_perf_stop( &p_port->p_adapter->perf, GetEndptByLid );\r
+ *pp_dst = p_port->p_local_endpt;\r
+ CL_ASSERT( *pp_dst );\r
+ }\r
+\r
+ if( *pp_src && !ipoib_is_voltaire_router_gid( &(*pp_src)->dgid ) &&\r
+ (*pp_src)->qpn != p_wc->recv.ud.remote_qp )\r
+ {\r
+ /* Update the QPN for the endpoint. */\r
+ IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_RECV,\r
+ ("Updating QPN for MAC: %02X-%02X-%02X-%02X-%02X-%02X\n",\r
+ (*pp_src )->mac.addr[0], (*pp_src )->mac.addr[1],\r
+ (*pp_src )->mac.addr[2], (*pp_src )->mac.addr[3],\r
+ (*pp_src )->mac.addr[4], (*pp_src )->mac.addr[5]) );\r
+// (*pp_src)->qpn = p_wc->recv.ud.remote_qp;\r
+ }\r
+\r
+ if( *pp_src && *pp_dst )\r
+ {\r
+ IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_RECV,\r
+ ("Recv:\n"\r
+ "\tsrc MAC: %02X-%02X-%02X-%02X-%02X-%02X\n"\r
+ "\tdst MAC: %02X-%02X-%02X-%02X-%02X-%02X\n",\r
+ (*pp_src )->mac.addr[0], (*pp_src )->mac.addr[1],\r
+ (*pp_src )->mac.addr[2], (*pp_src )->mac.addr[3],\r
+ (*pp_src )->mac.addr[4], (*pp_src )->mac.addr[5],\r
+ (*pp_dst )->mac.addr[0], (*pp_dst )->mac.addr[1],\r
+ (*pp_dst )->mac.addr[2], (*pp_dst )->mac.addr[3],\r
+ (*pp_dst )->mac.addr[4], (*pp_dst )->mac.addr[5]) );\r
+ }\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_RECV );\r
+}\r
+\r
+\r
+static int32_t\r
+__recv_mgr_filter(\r
+ IN ipoib_port_t* const p_port,\r
+ IN ib_wc_t* const p_done_wc_list,\r
+ OUT cl_qlist_t* const p_done_list,\r
+ OUT cl_qlist_t* const p_bad_list )\r
+{\r
+ ipoib_recv_desc_t *p_desc;\r
+ ib_wc_t *p_wc;\r
+ ipoib_pkt_t *p_ipoib;\r
+ eth_pkt_t *p_eth;\r
+ ipoib_endpt_t *p_src, *p_dst;\r
+ ib_api_status_t status;\r
+ uint32_t len;\r
+ int32_t recv_cnt = 0;\r
+ PERF_DECLARE( GetRecvEndpts );\r
+ PERF_DECLARE( RecvGen );\r
+ PERF_DECLARE( RecvTcp );\r
+ PERF_DECLARE( RecvUdp );\r
+ PERF_DECLARE( RecvDhcp );\r
+ PERF_DECLARE( RecvArp );\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_RECV );\r
+\r
+ for( p_wc = p_done_wc_list; p_wc; p_wc = p_wc->p_next )\r
+ {\r
+ CL_ASSERT( p_wc->status != IB_WCS_SUCCESS || p_wc->wc_type == IB_WC_RECV );\r
+ p_desc = (ipoib_recv_desc_t*)(uintn_t)p_wc->wr_id;\r
+ recv_cnt++;\r
+\r
+ if( p_wc->status != IB_WCS_SUCCESS )\r
+ {\r
+ if( p_wc->status != IB_WCS_WR_FLUSHED_ERR )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed completion %s (vendor specific %#x)\n",\r
+ p_port->p_adapter->p_ifc->get_wc_status_str( p_wc->status ),\r
+ (int)p_wc->vendor_specific) );\r
+ ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_ERROR, 0, 0 );\r
+ }\r
+ else\r
+ {\r
+ IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_RECV,\r
+ ("Flushed completion %s\n",\r
+ p_port->p_adapter->p_ifc->get_wc_status_str( p_wc->status )) );\r
+ ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_DROPPED, 0, 0 );\r
+ }\r
+ cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item );\r
+ /* Dereference the port object on behalf of the failed receive. */\r
+ ipoib_port_deref( p_port, ref_failed_recv_wc );\r
+ continue;\r
+ }\r
+\r
+ len = p_wc->length - sizeof(ib_grh_t);\r
+\r
+ if( len < sizeof(ipoib_hdr_t) )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Received ETH packet < min size\n") );\r
+ ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_ERROR, 0, 0 );\r
+ cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item );\r
+ ipoib_port_deref( p_port, ref_recv_inv_len );\r
+ continue;\r
+ }\r
+\r
+ if((len - sizeof(ipoib_hdr_t)) > p_port->p_adapter->params.payload_mtu)\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Received ETH packet len %d > payload MTU (%d)\n",\r
+ (len - sizeof(ipoib_hdr_t)),\r
+ p_port->p_adapter->params.payload_mtu) );\r
+ ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_ERROR, 0, 0 );\r
+ cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item );\r
+ ipoib_port_deref( p_port, ref_recv_inv_len );\r
+ continue;\r
+ \r
+ }\r
+ /* Successful completion. Get the receive information. */\r
+ p_desc->ndis_csum.Value = ( ( p_wc->recv.ud.recv_opt & IB_RECV_OPT_CSUM_MASK ) >> 8 );\r
+ p_desc->len = len + 14 - 4 ;\r
+ cl_perf_start( GetRecvEndpts );\r
+ __recv_get_endpts( p_port, p_desc, p_wc, &p_src, &p_dst );\r
+ cl_perf_stop( &p_port->p_adapter->perf, GetRecvEndpts );\r
+\r
+#if IPOIB_INLINE_RECV\r
+ p_ipoib = &p_desc->buf.ib.pkt;\r
+ p_eth = &p_desc->buf.eth.pkt;\r
+#else /* IPOIB_INLINE_RECV */\r
+ p_ipoib = &p_desc->p_buf->ib.pkt;\r
+ p_eth = &p_desc->p_buf->eth.pkt;\r
+#endif /*IPOIB_INLINE_RECV */\r
+\r
+ if( p_src )\r
+ {\r
+ /* Don't report loopback traffic - we requested SW loopback. */\r
+ if( !cl_memcmp( &p_port->p_adapter->params.conf_mac,\r
+ &p_src->mac, sizeof(p_port->p_adapter->params.conf_mac) ) )\r
+ {\r
+ /*\r
+ * "This is not the packet you're looking for" - don't update\r
+ * receive statistics, the packet never happened.\r
+ */\r
+ cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item );\r
+ /* Dereference the port object on behalf of the failed recv. */\r
+ ipoib_port_deref( p_port, ref_recv_loopback );\r
+ continue;\r
+ }\r
+ }\r
+\r
+ switch( p_ipoib->hdr.type )\r
+ {\r
+ case ETH_PROT_TYPE_IP:\r
+ if( len < (sizeof(ipoib_hdr_t) + sizeof(ip_hdr_t)) )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Received IP packet < min size\n") );\r
+ status = IB_INVALID_SETTING;\r
+ break;\r
+ }\r
+\r
+ if( p_ipoib->type.ip.hdr.offset ||\r
+ p_ipoib->type.ip.hdr.prot != IP_PROT_UDP )\r
+ {\r
+ /* Unfiltered. Setup the ethernet header and report. */\r
+ cl_perf_start( RecvTcp );\r
+ status = __recv_gen( p_ipoib, p_eth, p_src, p_dst );\r
+ cl_perf_stop( &p_port->p_adapter->perf, RecvTcp );\r
+ break;\r
+ }\r
+\r
+ /* First packet of a UDP transfer. */\r
+ if( len <\r
+ (sizeof(ipoib_hdr_t) + sizeof(ip_hdr_t) + sizeof(udp_hdr_t)) )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Received UDP packet < min size\n") );\r
+ status = IB_INVALID_SETTING;\r
+ break;\r
+ }\r
+\r
+ /* Check if DHCP conversion is required. */\r
+ if( (p_ipoib->type.ip.prot.udp.hdr.dst_port == DHCP_PORT_SERVER &&\r
+ p_ipoib->type.ip.prot.udp.hdr.src_port == DHCP_PORT_CLIENT) ||\r
+ (p_ipoib->type.ip.prot.udp.hdr.dst_port == DHCP_PORT_CLIENT &&\r
+ p_ipoib->type.ip.prot.udp.hdr.src_port == DHCP_PORT_SERVER) )\r
+ {\r
+ if( len < (sizeof(ipoib_hdr_t) + sizeof(ip_hdr_t) +\r
+ sizeof(udp_hdr_t) + DHCP_MIN_SIZE) )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Received DHCP < min size\n") );\r
+ status = IB_INVALID_SETTING;\r
+ break;\r
+ }\r
+ if ((p_ipoib->type.ip.hdr.ver_hl & 0x0f) != 5 ) {\r
+ // If there are IP options in this message, we are in trouble in any case\r
+ status = IB_INVALID_SETTING;\r
+ break; \r
+ }\r
+ /* UDP packet with BOOTP ports in src/dst port numbers. */\r
+ cl_perf_start( RecvDhcp );\r
+ status = __recv_dhcp( p_port, p_ipoib, p_eth, p_src, p_dst );\r
+ cl_perf_stop( &p_port->p_adapter->perf, RecvDhcp );\r
+ }\r
+ else\r
+ {\r
+ /* Unfiltered. Setup the ethernet header and report. */\r
+ cl_perf_start( RecvUdp );\r
+ status = __recv_gen( p_ipoib, p_eth, p_src, p_dst );\r
+ cl_perf_stop( &p_port->p_adapter->perf, RecvUdp );\r
+ }\r
+ break;\r
+\r
+ case ETH_PROT_TYPE_ARP:\r
+ if( len < (sizeof(ipoib_hdr_t) + sizeof(ipoib_arp_pkt_t)) )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Received ARP < min size\n") );\r
+ status = IB_INVALID_SETTING;\r
+ break;\r
+ }\r
+ cl_perf_start( RecvArp );\r
+ status = __recv_arp( p_port, p_wc, p_ipoib, p_eth, &p_src, p_dst );\r
+ cl_perf_stop( &p_port->p_adapter->perf, RecvArp );\r
+ len = sizeof(ipoib_hdr_t) + sizeof(arp_pkt_t);\r
+ break;\r
+\r
+ default:\r
+ /* Unfiltered. Setup the ethernet header and report. */\r
+ cl_perf_start( RecvGen );\r
+ status = __recv_gen( p_ipoib, p_eth, p_src, p_dst );\r
+ cl_perf_stop( &p_port->p_adapter->perf, RecvGen );\r
+ }\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ /* Update stats. */\r
+ ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_ERROR, 0, 0 );\r
+ cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item );\r
+ /* Dereference the port object on behalf of the failed receive. */\r
+ ipoib_port_deref( p_port, ref_recv_filter );\r
+ }\r
+ else\r
+ {\r
+ ip_stat_sel_t ip_stat;\r
+ p_desc->len =\r
+ len + sizeof(eth_hdr_t) - sizeof(ipoib_hdr_t);\r
+ if( p_dst->h_mcast)\r
+ {\r
+ if( p_dst->dgid.multicast.raw_group_id[10] == 0xFF &&\r
+ p_dst->dgid.multicast.raw_group_id[11] == 0xFF &&\r
+ p_dst->dgid.multicast.raw_group_id[12] == 0xFF &&\r
+ p_dst->dgid.multicast.raw_group_id[13] == 0xFF )\r
+ {\r
+ p_desc->type = PKT_TYPE_BCAST;\r
+ ip_stat = IP_STAT_BCAST_BYTES;\r
+ }\r
+ else\r
+ {\r
+ p_desc->type = PKT_TYPE_MCAST;\r
+ ip_stat = IP_STAT_MCAST_BYTES;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ p_desc->type = PKT_TYPE_UCAST;\r
+ ip_stat = IP_STAT_UCAST_BYTES;\r
+ \r
+ }\r
+ cl_qlist_insert_tail( p_done_list, &p_desc->item.list_item );\r
+ ipoib_inc_recv_stat( p_port->p_adapter, ip_stat, len, 1 ); \r
+ }\r
+ }\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_RECV );\r
+ return recv_cnt;\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__recv_gen(\r
+ IN const ipoib_pkt_t* const p_ipoib,\r
+ OUT eth_pkt_t* const p_eth,\r
+ IN ipoib_endpt_t* const p_src,\r
+ IN ipoib_endpt_t* const p_dst )\r
+{\r
+ IPOIB_ENTER( IPOIB_DBG_RECV );\r
+\r
+ if( !p_src || !p_dst )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Received packet with no matching endpoints.\n") );\r
+ return IB_NOT_DONE;\r
+ }\r
+\r
+ /*\r
+ * Fill in the ethernet header. Note that doing so will overwrite\r
+ * the IPoIB header, so start by moving the information from the IPoIB\r
+ * header.\r
+ */\r
+ p_eth->hdr.type = p_ipoib->hdr.type;\r
+ p_eth->hdr.src = p_src->mac;\r
+ p_eth->hdr.dst = p_dst->mac;\r
+\r
+ if ( p_eth->hdr.dst.addr[0] == 1 && \r
+ p_eth->hdr.type == ETH_PROT_TYPE_IP &&\r
+ p_eth->hdr.dst.addr[2] == 0x5E) \r
+ {\r
+ p_eth->hdr.dst.addr[1] = 0;\r
+ p_eth->hdr.dst.addr[3] = p_eth->hdr.dst.addr[3] & 0x7f;\r
+ }\r
+ if (p_dst->h_mcast)\r
+ p_dst->is_in_use = TRUE;\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_RECV );\r
+ return IB_SUCCESS;\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__recv_dhcp(\r
+ IN ipoib_port_t* const p_port,\r
+ IN const ipoib_pkt_t* const p_ipoib,\r
+ OUT eth_pkt_t* const p_eth,\r
+ IN ipoib_endpt_t* const p_src,\r
+ IN ipoib_endpt_t* const p_dst )\r
+{\r
+ ib_api_status_t status;\r
+ dhcp_pkt_t *p_dhcp;\r
+ uint8_t *p_option;\r
+ uint8_t *p_cid = NULL;\r
+ ib_gid_t gid;\r
+ uint8_t msg = 0;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_RECV );\r
+\r
+ UNUSED_PARAM( p_port );\r
+\r
+ /* Create the ethernet header. */\r
+ status = __recv_gen( p_ipoib, p_eth, p_src, p_dst );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("__recv_gen returned %s.\n", \r
+ p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+ return status;\r
+ }\r
+\r
+ /* Fixup the payload. */\r
+ p_dhcp = &p_eth->type.ip.prot.udp.dhcp;\r
+ if( p_dhcp->op != DHCP_REQUEST && p_dhcp->op != DHCP_REPLY )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Invalid DHCP op code.\n") );\r
+ return IB_INVALID_SETTING;\r
+ }\r
+\r
+ /*\r
+ * Find the client identifier option, making sure to skip\r
+ * the "magic cookie".\r
+ */\r
+ p_option = &p_dhcp->options[0];\r
+ if ( *(uint32_t *)p_option != DHCP_COOKIE )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("DHCP cookie corrupted.\n") );\r
+ return IB_INVALID_PARAMETER;\r
+ }\r
+\r
+ p_option = &p_dhcp->options[4];\r
+ while( *p_option != DHCP_OPT_END && p_option < &p_dhcp->options[312] )\r
+ {\r
+ switch( *p_option )\r
+ {\r
+ case DHCP_OPT_PAD:\r
+ p_option++;\r
+ break;\r
+\r
+ case DHCP_OPT_MSG:\r
+ msg = p_option[2];\r
+ p_option += 3;\r
+ break;\r
+\r
+ case DHCP_OPT_CLIENT_ID:\r
+ p_cid = p_option;\r
+ /* Fall through. */\r
+\r
+ default:\r
+ /*\r
+ * All other options have a length byte following the option code.\r
+ * Offset by the length to get to the next option.\r
+ */\r
+ p_option += (p_option[1] + 2);\r
+ }\r
+ }\r
+\r
+ switch( msg )\r
+ {\r
+ /* message from client */\r
+ case DHCPDISCOVER:\r
+ case DHCPREQUEST:\r
+ case DHCPDECLINE:\r
+ case DHCPRELEASE:\r
+ case DHCPINFORM:\r
+ if( !p_cid )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed to find required Client-identifier option.\n") );\r
+ return IB_INVALID_SETTING;\r
+ }\r
+ if( p_dhcp->htype != DHCP_HW_TYPE_IB )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Invalid hardware address type.\n") );\r
+ return IB_INVALID_SETTING;\r
+ }\r
+ break;\r
+ /* message from DHCP server */\r
+ case DHCPOFFER:\r
+ case DHCPACK:\r
+ case DHCPNAK:\r
+ break;\r
+\r
+ default:\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Invalide message type.\n") );\r
+ return IB_INVALID_PARAMETER;\r
+ }\r
+ p_eth->type.ip.prot.udp.hdr.chksum = 0;\r
+ p_dhcp->htype = DHCP_HW_TYPE_ETH;\r
+ p_dhcp->hlen = HW_ADDR_LEN;\r
+\r
+ if( p_cid ) /* from client */\r
+ {\r
+ /* Validate that the length and type of the option is as required. */\r
+ if( p_cid[1] != 21 )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Client-identifier length not 21 as required.\n") );\r
+ return IB_INVALID_SETTING;\r
+ }\r
+ if( p_cid[2] != DHCP_HW_TYPE_IB )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Client-identifier type is wrong.\n") );\r
+ return IB_INVALID_SETTING;\r
+ }\r
+ /*\r
+ * Copy the GID value from the option so that we can make aligned\r
+ * accesses to the contents.\r
+ * Recover CID to standard type.\r
+ */\r
+ cl_memcpy( &gid, &p_cid[7], sizeof(ib_gid_t) );\r
+ p_cid[1] = HW_ADDR_LEN +1;// CID length \r
+ p_cid[2] = DHCP_HW_TYPE_ETH;// CID type \r
+ status = ipoib_mac_from_guid( gid.unicast.interface_id, p_port->p_adapter->params.guid_mask, (mac_addr_t*)&p_cid[3] );\r
+ if (status == IB_INVALID_GUID_MASK)\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_ERROR,\r
+ ("Invalid GUID mask received, rejecting it") );\r
+ ipoib_create_log(p_port->p_adapter->h_adapter, GUID_MASK_LOG_INDEX, EVENT_IPOIB_WRONG_PARAMETER_WRN);\r
+ status = IB_SUCCESS;\r
+ }\r
+ p_cid[HW_ADDR_LEN + 3] = DHCP_OPT_END; //terminate tag\r
+ }\r
+ IPOIB_EXIT( IPOIB_DBG_RECV );\r
+ return status;\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__recv_arp(\r
+ IN ipoib_port_t* const p_port,\r
+ IN ib_wc_t* const p_wc,\r
+ IN const ipoib_pkt_t* const p_ipoib,\r
+ OUT eth_pkt_t* const p_eth,\r
+ IN ipoib_endpt_t** const pp_src,\r
+ IN ipoib_endpt_t* const p_dst )\r
+{\r
+ ib_api_status_t status;\r
+ arp_pkt_t *p_arp;\r
+ const ipoib_arp_pkt_t *p_ib_arp;\r
+ ib_gid_t gid;\r
+ mac_addr_t mac;\r
+ ipoib_hw_addr_t null_hw = {0};\r
+ uint8_t cm_capable = 0;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_RECV );\r
+\r
+ if( !p_dst )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Unknown destination endpoint\n") );\r
+ return IB_INVALID_SETTING;\r
+ }\r
+\r
+ p_ib_arp = &p_ipoib->type.arp;\r
+ p_arp = &p_eth->type.arp;\r
+\r
+ if( p_ib_arp->hw_type != ARP_HW_TYPE_IB )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ARP hardware type is not IB\n") );\r
+ return IB_INVALID_SETTING;\r
+ }\r
+\r
+ if( p_ib_arp->hw_size != sizeof(ipoib_hw_addr_t) )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ARP hardware address size is not sizeof(ipoib_hw_addr_t)\n") );\r
+ return IB_INVALID_SETTING;\r
+ }\r
+\r
+ if( p_ib_arp->prot_type != ETH_PROT_TYPE_IP )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ARP protocal type not IP\n") );\r
+ return IB_INVALID_SETTING;\r
+ }\r
+\r
+ cm_capable = ipoib_addr_get_flags( &p_ib_arp->src_hw );\r
+\r
+ /*\r
+ * If we don't have a source, lookup the endpoint specified in the payload.\r
+ */\r
+ if( !*pp_src )\r
+ *pp_src = __endpt_mgr_get_by_gid( p_port, &p_ib_arp->src_hw.gid );\r
+\r
+ /*\r
+ * If the endpoint exists for the GID, make sure\r
+ * the dlid and qpn match the arp.\r
+ */\r
+ if( *pp_src )\r
+ {\r
+ if( cl_memcmp( &(*pp_src)->dgid, &p_ib_arp->src_hw.gid,\r
+ sizeof(ib_gid_t) ) )\r
+ {\r
+ /*\r
+ * GIDs for the endpoint are different. The ARP must\r
+ * have been proxied. Dereference it.\r
+ */\r
+ *pp_src = NULL;\r
+ }\r
+ else if( (*pp_src)->dlid &&\r
+ (*pp_src)->dlid != p_wc->recv.ud.remote_lid )\r
+ {\r
+ /* Out of date! Destroy the endpoint and replace it. */\r
+ __endpt_mgr_remove( p_port, *pp_src );\r
+ *pp_src = NULL;\r
+ }\r
+ else if ( ! ((*pp_src)->dlid)) {\r
+ /* Out of date! Destroy the endpoint and replace it. */\r
+ __endpt_mgr_remove( p_port, *pp_src );\r
+ *pp_src = NULL;\r
+ }\r
+ else if( ipoib_is_voltaire_router_gid( &(*pp_src)->dgid ) )\r
+ {\r
+ if( (*pp_src)->qpn != ipoib_addr_get_qpn( &p_ib_arp->src_hw ) &&\r
+ p_wc->recv.ud.remote_qp != ipoib_addr_get_qpn( &p_ib_arp->src_hw ) )\r
+ {\r
+ /* Out of date! Destroy the endpoint and replace it. */\r
+ __endpt_mgr_remove( p_port, *pp_src );\r
+ *pp_src = NULL;\r
+ }\r
+ }\r
+ else if( (*pp_src)->qpn != p_wc->recv.ud.remote_qp )\r
+ {\r
+ /* Out of date! Destroy the endpoint and replace it. */\r
+ __endpt_mgr_remove( p_port, *pp_src );\r
+ *pp_src = NULL;\r
+ }\r
+ }\r
+\r
+ /* Do we need to create an endpoint for this GID? */\r
+ if( !*pp_src )\r
+ {\r
+ /* Copy the src GID to allow aligned access */\r
+ cl_memcpy( &gid, &p_ib_arp->src_hw.gid, sizeof(ib_gid_t) );\r
+ status = ipoib_mac_from_guid( gid.unicast.interface_id, p_port->p_adapter->params.guid_mask, &mac );\r
+ if (status == IB_INVALID_GUID_MASK)\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_ERROR,\r
+ ("Invalid GUID mask received, rejecting it") );\r
+ ipoib_create_log(p_port->p_adapter->h_adapter, GUID_MASK_LOG_INDEX, EVENT_IPOIB_WRONG_PARAMETER_WRN);\r
+ }\r
+ else if( status != IB_SUCCESS )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ipoib_mac_from_guid returned %s\n",\r
+ p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+ return status;\r
+ }\r
+ /*\r
+ * Create the endpoint.\r
+ */\r
+ *pp_src = ipoib_endpt_create( &p_ib_arp->src_hw.gid,\r
+ p_wc->recv.ud.remote_lid, ipoib_addr_get_qpn( &p_ib_arp->src_hw ) );\r
+\r
+ if( !*pp_src )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ipoib_endpt_create failed\n") );\r
+ return status;\r
+ }\r
+\r
+ cl_obj_lock( &p_port->obj );\r
+ status = __endpt_mgr_insert( p_port, mac, *pp_src );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ cl_obj_unlock( &p_port->obj );\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("__endpt_mgr_insert return %s \n",\r
+ p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+ return status;\r
+ }\r
+\r
+ cl_obj_unlock( &p_port->obj );\r
+ }\r
+\r
+ (*pp_src)->cm_flag = cm_capable;\r
+\r
+ CL_ASSERT( !cl_memcmp(\r
+ &(*pp_src)->dgid, &p_ib_arp->src_hw.gid, sizeof(ib_gid_t) ) );\r
+ CL_ASSERT( ipoib_is_voltaire_router_gid( &(*pp_src)->dgid ) ||\r
+ (*pp_src)->qpn == ipoib_addr_get_qpn( &p_ib_arp->src_hw ) );\r
+#if 0\r
+ if( p_port->p_adapter->params.cm_enabled &&\r
+ p_ib_arp->op == ARP_OP_REQ &&\r
+ cm_capable == IPOIB_CM_FLAG_RC )\r
+ {\r
+ /* if we've got ARP request and RC flag is set, \r
+ save SID for connect REQ to be sent in ARP reply\r
+ when requestor's path get resolved */\r
+ if( endpt_cm_get_state( (*pp_src) ) == IPOIB_CM_DISCONNECTED )\r
+ {\r
+ (*pp_src)->cm_flag = cm_capable;\r
+ ipoib_addr_set_sid( \r
+ &(*pp_src)->conn.service_id,\r
+ ipoib_addr_get_qpn( &p_ib_arp->src_hw ) );\r
+ }\r
+ }\r
+#endif\r
+#if 0 //DBG\r
+ if( p_port->p_adapter->params.cm_enabled )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+ (" ARP %s from ENDPT[%p] state %d CM cap: %d QPN: %#x MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",\r
+ ((p_ib_arp->op == ARP_OP_REQ )? "REQUEST" : "REPLY"),\r
+ *pp_src, endpt_cm_get_state( *pp_src ), \r
+ ((cm_capable == IPOIB_CM_FLAG_RC)? 1: 0),\r
+ cl_ntoh32( ipoib_addr_get_qpn( &p_ib_arp->src_hw ) ),\r
+ (*pp_src)->mac.addr[0], (*pp_src)->mac.addr[1],\r
+ (*pp_src)->mac.addr[2], (*pp_src)->mac.addr[3],\r
+ (*pp_src)->mac.addr[4], (*pp_src)->mac.addr[5] ));\r
+ }\r
+#endif\r
+\r
+ /* Now swizzle the data. */\r
+ p_arp->hw_type = ARP_HW_TYPE_ETH;\r
+ p_arp->hw_size = sizeof(mac_addr_t);\r
+ p_arp->src_hw = (*pp_src)->mac;\r
+ p_arp->src_ip = p_ib_arp->src_ip;\r
+\r
+ if( cl_memcmp( &p_ib_arp->dst_hw, &null_hw, sizeof(ipoib_hw_addr_t) ) )\r
+ {\r
+ if( cl_memcmp( &p_dst->dgid, &p_ib_arp->dst_hw.gid, sizeof(ib_gid_t) ) )\r
+ {\r
+ /*\r
+ * We received bcast ARP packet that means\r
+ * remote port lets everyone know it was changed IP/MAC\r
+ * or just activated\r
+ */\r
+\r
+ /* Guy: TODO: Check why this check fails in case of Voltaire IPR */\r
+\r
+ if ( !ipoib_is_voltaire_router_gid( &(*pp_src)->dgid ) &&\r
+ !ib_gid_is_multicast( (const ib_gid_t*)&p_dst->dgid ) )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ARP: is not ARP MCAST\n") );\r
+ return IB_INVALID_SETTING;\r
+ }\r
+\r
+ p_arp->dst_hw = p_port->p_local_endpt->mac;\r
+ p_dst->mac = p_port->p_local_endpt->mac;\r
+ /*\r
+ * we don't care what receiver ip addr is,\r
+ * as long as OS' ARP table is global ???\r
+ */\r
+ p_arp->dst_ip = (net32_t)0;\r
+ }\r
+ else /* we've got reply to our ARP request */\r
+ {\r
+ p_arp->dst_hw = p_dst->mac;\r
+ p_arp->dst_ip = p_ib_arp->dst_ip;\r
+ CL_ASSERT( p_dst->qpn == ipoib_addr_get_qpn( &p_ib_arp->dst_hw ) );\r
+ }\r
+ }\r
+ else /* we got ARP reqeust */\r
+ {\r
+ cl_memclr( &p_arp->dst_hw, sizeof(mac_addr_t) );\r
+ p_arp->dst_ip = p_ib_arp->dst_ip;\r
+ }\r
+\r
+ /*\r
+ * Create the ethernet header. Note that this is done last so that\r
+ * we have a chance to create a new endpoint.\r
+ */\r
+ status = __recv_gen( p_ipoib, p_eth, *pp_src, p_dst );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("__recv_gen returned %s.\n", \r
+ p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+ return status;\r
+ }\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_RECV );\r
+ return IB_SUCCESS;\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__recv_mgr_prepare_pkt(\r
+ IN ipoib_port_t* const p_port,\r
+ IN ipoib_recv_desc_t* const p_desc,\r
+ OUT NET_BUFFER_LIST** const pp_net_buffer_list )\r
+{\r
+ NDIS_STATUS status;\r
+ uint32_t pkt_filter;\r
+ ip_stat_sel_t type;\r
+ //NDIS60\r
+ NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO chksum;\r
+ //NDIS_TCP_IP_CHECKSUM_PACKET_INFO chksum;\r
+\r
+ PERF_DECLARE( GetNdisPkt );\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_RECV );\r
+\r
+ pkt_filter = p_port->p_adapter->packet_filter;\r
+ /* Check the packet filter. */\r
+ switch( p_desc->type )\r
+ {\r
+ default:\r
+ case PKT_TYPE_UCAST:\r
+ \r
+ if( pkt_filter & NDIS_PACKET_TYPE_PROMISCUOUS ||\r
+ pkt_filter & NDIS_PACKET_TYPE_ALL_FUNCTIONAL ||\r
+ pkt_filter & NDIS_PACKET_TYPE_SOURCE_ROUTING ||\r
+ pkt_filter & NDIS_PACKET_TYPE_DIRECTED )\r
+ {\r
+ /* OK to report. */\r
+ type = IP_STAT_UCAST_BYTES;\r
+ status = NDIS_STATUS_SUCCESS;\r
+ IPOIB_PRINT( TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR,\r
+ ("Received UCAST PKT.\n"));\r
+ }\r
+ else\r
+ {\r
+ type = IP_STAT_DROPPED;\r
+ status = NDIS_STATUS_FAILURE;\r
+ IPOIB_PRINT( TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR,\r
+ ("Received UCAST PKT with ERROR !!!!\n"));\r
+ }\r
+ break;\r
+ case PKT_TYPE_BCAST:\r
+ if( pkt_filter & NDIS_PACKET_TYPE_PROMISCUOUS ||\r
+ pkt_filter & NDIS_PACKET_TYPE_BROADCAST )\r
+ {\r
+ /* OK to report. */\r
+ type = IP_STAT_BCAST_BYTES;\r
+ status = NDIS_STATUS_SUCCESS;\r
+ IPOIB_PRINT( TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR,\r
+ ("Received BCAST PKT.\n"));\r
+ }\r
+ else\r
+ {\r
+ type = IP_STAT_DROPPED;\r
+ status = NDIS_STATUS_FAILURE;\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Received BCAST PKT with ERROR !!!!\n"));\r
+ }\r
+ break;\r
+ case PKT_TYPE_MCAST:\r
+ if( pkt_filter & NDIS_PACKET_TYPE_PROMISCUOUS ||\r
+ pkt_filter & NDIS_PACKET_TYPE_ALL_MULTICAST ||\r
+ pkt_filter & NDIS_PACKET_TYPE_MULTICAST )\r
+ {\r
+ /* OK to report. */\r
+ type = IP_STAT_MCAST_BYTES;\r
+ status = NDIS_STATUS_SUCCESS;\r
+ IPOIB_PRINT( TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR,\r
+ ("Received UCAST PKT.\n"));\r
+ }\r
+ else\r
+ {\r
+ type = IP_STAT_DROPPED;\r
+ status = NDIS_STATUS_FAILURE;\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Received MCAST PKT with ERROR !!!!\n"));\r
+ }\r
+ break;\r
+ }\r
+\r
+ if( status != NDIS_STATUS_SUCCESS )\r
+ {\r
+ ipoib_inc_recv_stat( p_port->p_adapter, type, 0, 0 );\r
+ /* Return the receive descriptor to the pool. */\r
+ __buf_mgr_put_recv( p_port, p_desc, NULL );\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_RECV,\r
+ ("Packet filter doesn't match receive. Dropping.\n") );\r
+ /*\r
+ * Return IB_NOT_DONE since the packet has been completed,\r
+ * but has not consumed an array entry.\r
+ */\r
+ return IB_NOT_DONE;\r
+ }\r
+\r
+ cl_perf_start( GetNdisPkt );\r
+ *pp_net_buffer_list = __buf_mgr_get_ndis_pkt( p_port, p_desc );\r
+ cl_perf_stop( &p_port->p_adapter->perf, GetNdisPkt );\r
+ if( !*pp_net_buffer_list )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("__buf_mgr_get_ndis_pkt failed\n") );\r
+ return IB_INSUFFICIENT_RESOURCES;\r
+ }\r
+\r
+ chksum.Value = 0;\r
+\r
+{\r
+ PNET_BUFFER NetBuffer = NET_BUFFER_LIST_FIRST_NB(*pp_net_buffer_list);\r
+ NET_BUFFER_DATA_LENGTH(NetBuffer) = p_desc->len;\r
+}\r
+ \r
+ switch( p_port->p_adapter->params.recv_chksum_offload )\r
+ {\r
+ default:\r
+ CL_ASSERT( FALSE );\r
+ case CSUM_DISABLED:\r
+ //NDIS60\r
+ //NDIS_PER_PACKET_INFO_FROM_PACKET( *pp_packet, TcpIpChecksumPacketInfo ) =\r
+ //(void*)(uintn_t)chksum.Value;\r
+ NET_BUFFER_LIST_INFO(*pp_net_buffer_list, TcpIpChecksumNetBufferListInfo) = \r
+ (void*)(uintn_t)chksum.Value;\r
+ break;\r
+ case CSUM_ENABLED:\r
+ /* Get the checksums directly from packet information. */\r
+ /* In this case, no one of cheksum's cat get false value */\r
+ /* If hardware checksum failed or wasn't calculated, NDIS will recalculate it again */\r
+ //NDIS60\r
+ //NDIS_PER_PACKET_INFO_FROM_PACKET( *pp_packet, TcpIpChecksumPacketInfo ) = \r
+ NET_BUFFER_LIST_INFO(*pp_net_buffer_list, TcpIpChecksumNetBufferListInfo) =\r
+ (void*)(uintn_t)(p_desc->ndis_csum.Value);\r
+ break;\r
+ case CSUM_BYPASS:\r
+ /* Flag the checksums as having been calculated. */\r
+ chksum.Receive.TcpChecksumSucceeded = TRUE;\r
+ chksum.Receive.UdpChecksumSucceeded = TRUE;\r
+ chksum.Receive.IpChecksumSucceeded = TRUE;\r
+ //NDIS60\r
+ //NDIS_PER_PACKET_INFO_FROM_PACKET( *pp_packet, TcpIpChecksumPacketInfo ) =\r
+ NET_BUFFER_LIST_INFO(*pp_net_buffer_list, TcpIpChecksumNetBufferListInfo) =\r
+ (void*)(uintn_t)chksum.Value;\r
+ break;\r
+ }\r
+ ipoib_inc_recv_stat( p_port->p_adapter, type, p_desc->len, 1 );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_RECV );\r
+ return IB_SUCCESS;\r
+}\r
+\r
+\r
+static uint32_t\r
+__recv_mgr_build_pkt_array(\r
+ IN ipoib_port_t* const p_port,\r
+ IN int32_t shortage,\r
+ OUT cl_qlist_t* const p_done_list,\r
+ OUT int32_t* const p_discarded )\r
+{\r
+ cl_list_item_t *p_item;\r
+ ipoib_recv_desc_t *p_desc;\r
+ uint32_t i = 0;\r
+ ib_api_status_t status;\r
+ PERF_DECLARE( PreparePkt );\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_RECV );\r
+\r
+ *p_discarded = 0;\r
+\r
+ /* Move any existing receives to the head to preserve ordering. */\r
+ cl_qlist_insert_list_head( p_done_list, &p_port->recv_mgr.done_list );\r
+ p_item = cl_qlist_remove_head( p_done_list );\r
+ while( p_item != cl_qlist_end( p_done_list ) )\r
+ {\r
+ p_desc = (ipoib_recv_desc_t*)p_item;\r
+\r
+ cl_perf_start( PreparePkt );\r
+ status = __recv_mgr_prepare_pkt( p_port, p_desc,\r
+ &p_port->recv_mgr.recv_pkt_array[i] );\r
+ cl_perf_stop( &p_port->p_adapter->perf, PreparePkt );\r
+ if( status == IB_SUCCESS )\r
+ {\r
+ CL_ASSERT( p_port->recv_mgr.recv_pkt_array[i] );\r
+ if( shortage-- > 0 )\r
+ {\r
+ NET_BUFFER_LIST_STATUS(p_port->recv_mgr.recv_pkt_array[i])= NDIS_STATUS_RESOURCES; \r
+ }\r
+ else\r
+ {\r
+ NET_BUFFER_LIST_STATUS(p_port->recv_mgr.recv_pkt_array[i])= NDIS_STATUS_SUCCESS;\r
+ }\r
+ i++;\r
+ }\r
+ else if( status == IB_NOT_DONE )\r
+ {\r
+ (*p_discarded)++;\r
+ }\r
+ else\r
+ {\r
+ IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_RECV,\r
+ ("__recv_mgr_prepare_pkt returned %s\n",\r
+ p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+ /* Put all completed receives on the port's done list. */\r
+ cl_qlist_insert_tail( &p_port->recv_mgr.done_list, p_item );\r
+ cl_qlist_insert_list_tail( &p_port->recv_mgr.done_list, p_done_list );\r
+ break;\r
+ }\r
+\r
+ p_item = cl_qlist_remove_head( p_done_list );\r
+ }\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_RECV );\r
+ return i;\r
+}\r
+\r
+\r
+\r
+\r
+/******************************************************************************\r
+*\r
+* Send manager implementation.\r
+*\r
+******************************************************************************/\r
+static void\r
+__send_mgr_construct(\r
+ IN ipoib_port_t* const p_port )\r
+{\r
+ IPOIB_ENTER( IPOIB_DBG_SEND );\r
+ p_port->send_mgr.depth = 0;\r
+ cl_qlist_init( &p_port->send_mgr.pending_list );\r
+ IPOIB_EXIT( IPOIB_DBG_SEND );\r
+}\r
+\r
+\r
+static void \r
+__pending_list_destroy(\r
+ IN ipoib_port_t* const p_port )\r
+{\r
+ cl_list_item_t *p_item;\r
+ NET_BUFFER_LIST **pp_net_buffer_list, *p_head;\r
+ \r
+ p_head = NULL;\r
+ cl_spinlock_acquire( &p_port->send_lock );\r
+ /* Complete any pending packets. */\r
+ pp_net_buffer_list = &p_head;\r
+ for( p_item = cl_qlist_remove_head( &p_port->send_mgr.pending_list );\r
+ p_item != cl_qlist_end( &p_port->send_mgr.pending_list );\r
+ p_item = cl_qlist_remove_head( &p_port->send_mgr.pending_list ) )\r
+ {\r
+ *pp_net_buffer_list = IPOIB_PACKET_FROM_LIST_ITEM( p_item );\r
+ NET_BUFFER_LIST_STATUS(*pp_net_buffer_list) = NDIS_STATUS_RESET_IN_PROGRESS;\r
+ pp_net_buffer_list = &(NET_BUFFER_LIST_NEXT_NBL(*pp_net_buffer_list));\r
+ }\r
+ cl_spinlock_release( &p_port->send_lock );\r
+ if(p_head)\r
+ NdisMSendNetBufferListsComplete(\r
+ p_port->p_adapter->h_adapter,\r
+ p_head,\r
+ 0); \r
+}\r
+\r
+static void\r
+__send_mgr_destroy(\r
+ IN ipoib_port_t* const p_port )\r
+{\r
+ IPOIB_ENTER( IPOIB_DBG_SEND );\r
+ __pending_list_destroy(p_port);\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_SEND );\r
+}\r
+\r
+\r
+static NDIS_STATUS\r
+__send_mgr_filter(\r
+ IN ipoib_port_t* const p_port,\r
+ IN const eth_hdr_t* const p_eth_hdr,\r
+ IN MDL* const p_mdl,\r
+ IN size_t buf_len,\r
+ IN SCATTER_GATHER_LIST *p_sgl,\r
+ IN OUT ipoib_send_desc_t* const p_desc )\r
+{\r
+ NDIS_STATUS status;\r
+\r
+ PERF_DECLARE( FilterIp );\r
+ PERF_DECLARE( FilterArp );\r
+ PERF_DECLARE( SendGen );\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+ /*\r
+ * We already checked the ethernet header length, so we know it's safe\r
+ * to decrement the buf_len without underflowing.\r
+ */\r
+ buf_len -= sizeof(eth_hdr_t);\r
+\r
+ switch( p_eth_hdr->type )\r
+ {\r
+ case ETH_PROT_TYPE_IP:\r
+ cl_perf_start( FilterIp );\r
+ status = __send_mgr_filter_ip(\r
+ p_port, p_eth_hdr, p_mdl, buf_len, p_sgl, p_desc);\r
+ cl_perf_stop( &p_port->p_adapter->perf, FilterIp );\r
+ break;\r
+\r
+ case ETH_PROT_TYPE_ARP:\r
+ cl_perf_start( FilterArp );\r
+ status = __send_mgr_filter_arp(\r
+ p_port, p_eth_hdr, p_mdl, buf_len, p_desc );\r
+ p_desc->send_dir = SEND_UD_QP;\r
+ cl_perf_stop( &p_port->p_adapter->perf, FilterArp );\r
+ break;\r
+\r
+ default:\r
+ /*\r
+ * The IPoIB spec doesn't define how to send non IP or ARP packets.\r
+ * Just send the payload and hope for the best.\r
+ */\r
+\r
+ p_desc->send_dir = SEND_UD_QP;\r
+ cl_perf_start( SendGen );\r
+ status = __send_gen( p_port, p_desc, p_sgl, 0 );\r
+ cl_perf_stop( &p_port->p_adapter->perf, SendGen );\r
+ break;\r
+ }\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_SEND );\r
+ return status;\r
+}\r
+\r
+\r
+static NDIS_STATUS\r
+__send_copy(\r
+ IN ipoib_port_t* const p_port,\r
+ IN ipoib_send_desc_t* const p_desc )\r
+{\r
+ NET_BUFFER_LIST *p_net_buffer_list;\r
+ NET_BUFFER *p_netbuffer;\r
+ MDL *p_mdl;\r
+ UINT tot_len = 0;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+ UNREFERENCED_PARAMETER(p_port);\r
+ UNREFERENCED_PARAMETER(p_desc);\r
+\r
+ p_desc->p_buf = \r
+ (send_buf_t *) NdisAllocateFromNPagedLookasideList( &p_port->buf_mgr.send_buf_list );\r
+ if( !p_desc->p_buf )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed to allocate buffer for packet copy.\n") );\r
+ return NDIS_STATUS_RESOURCES;\r
+ }\r
+\r
+ p_mdl = NdisAllocateMdl(p_port->p_adapter->h_adapter,\r
+ p_desc->p_buf,\r
+ p_port->p_adapter->params.xfer_block_size );\r
+ if( !p_mdl )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed to allocate MDL\n") );\r
+ return NDIS_STATUS_RESOURCES;\r
+ }\r
+\r
+ p_net_buffer_list = NdisAllocateNetBufferAndNetBufferList(\r
+ p_port->buf_mgr.h_send_buf_pool,\r
+ 0,\r
+ 0,\r
+ p_mdl,\r
+ 0,\r
+ 0);\r
+\r
+ if( !p_net_buffer_list )\r
+ {\r
+ NdisFreeMdl(p_mdl);\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_WARNING, IPOIB_DBG_SEND,\r
+ ("Failed to allocate NDIS_PACKET for copy.\n") );\r
+ return NDIS_STATUS_RESOURCES;\r
+ }\r
+\r
+ for (p_netbuffer = NET_BUFFER_LIST_FIRST_NB(p_net_buffer_list); \r
+ p_netbuffer != NULL;\r
+ p_netbuffer = NET_BUFFER_NEXT_NB(p_netbuffer))\r
+ {\r
+ tot_len +=NET_BUFFER_DATA_LENGTH(p_netbuffer);\r
+ }\r
+\r
+ /* Setup the work request. */\r
+ p_desc->send_wr[0].local_ds[1].vaddr = cl_get_physaddr(\r
+ ((uint8_t*)p_desc->p_buf) + sizeof(eth_hdr_t) );\r
+ p_desc->send_wr[0].local_ds[1].length = tot_len - sizeof(eth_hdr_t);\r
+ p_desc->send_wr[0].local_ds[1].lkey = p_port->ib_mgr.lkey;\r
+ p_desc->send_wr[0].wr.num_ds = 2;\r
+ \r
+ /* Free our temp packet now that the data is copied. */\r
+ NdisFreeMdl(p_mdl);\r
+ NdisFreeNetBufferList(p_net_buffer_list);\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_SEND );\r
+ return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+static inline NDIS_STATUS\r
+__send_mgr_get_eth_hdr(\r
+ IN PNET_BUFFER p_net_buffer,\r
+ OUT MDL** const pp_mdl,\r
+ OUT eth_hdr_t** const pp_eth_hdr,\r
+ OUT UINT* p_mdl_len)\r
+{\r
+ PUCHAR p_head = NULL;\r
+ IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+ *pp_mdl = NET_BUFFER_FIRST_MDL(p_net_buffer);\r
+\r
+ NdisQueryMdl(*pp_mdl,&p_head,p_mdl_len,NormalPagePriority);\r
+ if( ! p_head )\r
+ {\r
+ /* Failed to get first buffer. */\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("NdisQueryMdl failed.\n") );\r
+ return NDIS_STATUS_FAILURE;\r
+ }\r
+\r
+ if( *p_mdl_len < sizeof(eth_hdr_t) )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("First buffer in packet smaller than eth_hdr_t: %d.\n",\r
+ *p_mdl_len) );\r
+ return NDIS_STATUS_BUFFER_TOO_SHORT;\r
+ }\r
+\r
+ *pp_eth_hdr = (eth_hdr_t*)(p_head + NET_BUFFER_CURRENT_MDL_OFFSET(p_net_buffer));\r
+\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_SEND,\r
+ ("Ethernet header:\n"\r
+ "\tsrc MAC: %02X-%02X-%02X-%02X-%02X-%02X\n"\r
+ "\tdst MAC: %02X-%02X-%02X-%02X-%02X-%02X\n"\r
+ "\tprotocol type: %04X\n",\r
+ (*pp_eth_hdr)->src.addr[0], (*pp_eth_hdr)->src.addr[1],\r
+ (*pp_eth_hdr)->src.addr[2], (*pp_eth_hdr)->src.addr[3],\r
+ (*pp_eth_hdr)->src.addr[4], (*pp_eth_hdr)->src.addr[5],\r
+ (*pp_eth_hdr)->dst.addr[0], (*pp_eth_hdr)->dst.addr[1],\r
+ (*pp_eth_hdr)->dst.addr[2], (*pp_eth_hdr)->dst.addr[3],\r
+ (*pp_eth_hdr)->dst.addr[4], (*pp_eth_hdr)->dst.addr[5],\r
+ cl_ntoh16( (*pp_eth_hdr)->type )) );\r
+\r
+ return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+\r
+#if !IPOIB_USE_DMA\r
+/* Send using the MDL's page information rather than the SGL. */\r
+static ib_api_status_t\r
+__send_gen(\r
+ IN ipoib_port_t* const p_port,\r
+ IN ipoib_send_desc_t* const p_desc )\r
+{\r
+ uint32_t i, j = 1;\r
+ ULONG offset;\r
+ MDL *p_mdl;\r
+ UINT num_pages, tot_len;\r
+ ULONG buf_len;\r
+ PPFN_NUMBER page_array;\r
+ boolean_t hdr_done = FALSE;\r
+ ib_api_status_t status;\r
+ PNET_BUFFER p_net_buf;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_SEND );\r
+ p_net_buf = NET_BUFFER_LIST_FIRST_NB(p_desc->p_netbuf_list);\r
+ NdisQueryBuffer( p_net_buf, &num_pages, NULL, &p_mdl,\r
+ &tot_len );\r
+\r
+ if( !p_mdl )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("No buffers associated with packet.\n") );\r
+ return IB_ERROR;\r
+ }\r
+\r
+ /* Remember that one of the DS entries is reserved for the IPoIB header. */\r
+ if( num_pages >= MAX_SEND_SGE )\r
+ {\r
+ IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_SEND,\r
+ ("Too many buffers to fit in WR ds_array. Copying data.\n") );\r
+ status = __send_copy( p_port, p_desc );\r
+ IPOIB_EXIT( IPOIB_DBG_SEND );\r
+ return status;\r
+ }\r
+\r
+ CL_ASSERT( tot_len > sizeof(eth_hdr_t) );\r
+ CL_ASSERT( tot_len <= p_port->p_adapter->params.xfer_block_size );\r
+ /*\r
+ * Assume that the ethernet header is always fully contained\r
+ * in the first page of the first MDL. This makes for much\r
+ * simpler code.\r
+ */\r
+ offset = MmGetMdlByteOffset( p_mdl ) + sizeof(eth_hdr_t);\r
+ CL_ASSERT( offset <= PAGE_SIZE );\r
+\r
+ while( tot_len )\r
+ {\r
+ buf_len = MmGetMdlByteCount( p_mdl );\r
+ page_array = MmGetMdlPfnArray( p_mdl );\r
+ CL_ASSERT( page_array );\r
+ i = 0;\r
+ if( !hdr_done )\r
+ {\r
+ CL_ASSERT( buf_len >= sizeof(eth_hdr_t) );\r
+ /* Skip the ethernet header. */\r
+ buf_len -= sizeof(eth_hdr_t);\r
+ CL_ASSERT( buf_len <= p_port->p_adapter->params.payload_mtu );\r
+ if( buf_len )\r
+ {\r
+ /* The ethernet header is a subset of this MDL. */\r
+ CL_ASSERT( i == 0 );\r
+ if( offset < PAGE_SIZE )\r
+ {\r
+ p_desc->send_wr[0].local_ds[j].lkey = p_port->ib_mgr.lkey;\r
+ p_desc->send_wr[0].local_ds[j].vaddr = (page_array[i] << PAGE_SHIFT);\r
+ /* Add the byte offset since we're on the 1st page. */\r
+ p_desc->send_wr[0].local_ds[j].vaddr += offset;\r
+ if( offset + buf_len > PAGE_SIZE )\r
+ {\r
+ p_desc->send_wr[0].local_ds[j].length = PAGE_SIZE - offset;\r
+ buf_len -= p_desc->send_wr[0].local_ds[j].length;\r
+ }\r
+ else\r
+ {\r
+ p_desc->send_wr[0].local_ds[j].length = buf_len;\r
+ buf_len = 0;\r
+ }\r
+ /* This data segment is done. Move to the next. */\r
+ j++;\r
+ }\r
+ /* This page is done. Move to the next. */\r
+ i++;\r
+ }\r
+ /* Done handling the ethernet header. */\r
+ hdr_done = TRUE;\r
+ }\r
+\r
+ /* Finish this MDL */\r
+ while( buf_len )\r
+ {\r
+ p_desc->send_wr[0].local_ds[j].lkey = p_port->ib_mgr.lkey;\r
+ p_desc->send_wr[0].local_ds[j].vaddr = (page_array[i] << PAGE_SHIFT);\r
+ /* Add the first page's offset if we're on the first page. */\r
+ if( i == 0 )\r
+ p_desc->send_wr[0].local_ds[j].vaddr += MmGetMdlByteOffset( p_mdl );\r
+\r
+ if( i == 0 && (MmGetMdlByteOffset( p_mdl ) + buf_len) > PAGE_SIZE )\r
+ {\r
+ /* Buffers spans pages. */\r
+ p_desc->send_wr[0].local_ds[j].length =\r
+ PAGE_SIZE - MmGetMdlByteOffset( p_mdl );\r
+ buf_len -= p_desc->send_wr[0].local_ds[j].length;\r
+ /* This page is done. Move to the next. */\r
+ i++;\r
+ }\r
+ else\r
+ {\r
+ /* Last page of the buffer. */\r
+ p_desc->send_wr[0].local_ds[j].length = buf_len;\r
+ buf_len = 0;\r
+ }\r
+ /* This data segment is done. Move to the next. */\r
+ j++;\r
+ }\r
+\r
+ tot_len -= MmGetMdlByteCount( p_mdl );\r
+ if( !tot_len )\r
+ break;\r
+\r
+ NdisGetNextBuffer( p_mdl, &p_mdl );\r
+ if( !p_mdl )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed to get next buffer.\n") );\r
+ return IB_ERROR;\r
+ }\r
+ }\r
+\r
+ /* Set the number of data segments. */\r
+ p_desc->send_wr[0].wr.num_ds = j;\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_SEND );\r
+ return IB_SUCCESS;\r
+}\r
+\r
+#else\r
+\r
+#if 0\r
+void \r
+ipoib_process_sg_list1(\r
+ IN PDEVICE_OBJECT pDO,\r
+ IN PVOID pIrp,\r
+ IN PSCATTER_GATHER_LIST p_sgl,\r
+ IN PVOID context\r
+ )\r
+{\r
+ int i;\r
+ char temp[200];\r
+ for (i = 0 ; i < 1;i++)\r
+ temp[i] = 5;\r
+}\r
+#endif\r
+\r
+void \r
+ipoib_process_sg_list(\r
+ IN PDEVICE_OBJECT pDO,\r
+ IN PVOID pIrp,\r
+ IN PSCATTER_GATHER_LIST p_sgl,\r
+ IN PVOID context\r
+ )\r
+{ \r
+ NDIS_STATUS status;\r
+ ipoib_port_t *p_port;\r
+ MDL *p_mdl;\r
+ eth_hdr_t *p_eth_hdr;\r
+ UINT mdl_len;\r
+ static ipoib_send_desc_t *p_desc = NULL;\r
+ ib_send_wr_t *p_wr_failed;\r
+ NET_BUFFER_LIST *p_net_buffer_list;\r
+ NET_BUFFER *p_netbuf;\r
+ boolean_t from_queue;\r
+ ib_api_status_t ib_status;\r
+ ULONG complete_flags = 0;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+ UNREFERENCED_PARAMETER(pDO);\r
+ UNREFERENCED_PARAMETER(pIrp);\r
+\r
+ PERF_DECLARE( SendCopy );\r
+ PERF_DECLARE( BuildSendDesc );\r
+ PERF_DECLARE( GetEthHdr );\r
+ PERF_DECLARE( QueuePacket );\r
+ PERF_DECLARE( SendMgrQueue );\r
+ PERF_DECLARE( PostSend );\r
+ PERF_DECLARE( ProcessFailedSends );\r
+ PERF_DECLARE( GetEndpt );\r
+\r
+\r
+ p_netbuf = (NET_BUFFER*)context;\r
+ p_net_buffer_list = (NET_BUFFER_LIST*)IPOIB_NET_BUFFER_LIST_FROM_NETBUFFER(p_netbuf);\r
+ p_port = (ipoib_port_t*)IPOIB_PORT_FROM_PACKET(p_net_buffer_list);\r
+ NDIS_SET_SEND_COMPLETE_FLAG(complete_flags, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL);\r
+\r
+\r
+ cl_spinlock_acquire( &p_port->send_lock );\r
+ if (p_desc == NULL) {\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_SEND, ("Allocating send_desc First Time\n") );\r
+ p_desc = \r
+ (ipoib_send_desc_t *)ExAllocatePoolWithTag(NonPagedPool ,sizeof (ipoib_send_desc_t), 'XMXA');\r
+ }\r
+ ASSERT(p_desc);\r
+ p_desc->p_netbuf_list = p_net_buffer_list;\r
+ p_desc->p_endpt = NULL;\r
+ p_desc->p_buf = NULL;\r
+ p_desc->num_wrs = 1;\r
+\r
+ //IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_SEND,\r
+ // ("\n*******\nRECEIVED NB= %x with SG= %x\n********\n", p_netbuf, p_sgl) );\r
+ /* Get the ethernet header so we can find the endpoint. */\r
+ cl_perf_start( GetEthHdr );\r
+ status = __send_mgr_get_eth_hdr(\r
+ p_netbuf, &p_mdl, &p_eth_hdr, &mdl_len );\r
+ cl_perf_stop( &p_port->p_adapter->perf, GetEthHdr );\r
+\r
+ if( status != NDIS_STATUS_SUCCESS )\r
+ {\r
+ cl_perf_start( ProcessFailedSends );\r
+ /* fail net buffer list */\r
+ __process_failed_send( p_port, p_desc, status, complete_flags);\r
+ cl_perf_stop( &p_port->p_adapter->perf, ProcessFailedSends );\r
+ goto send_end;\r
+ }\r
+ //from_queue = (boolean_t)(IPOIB_FROM_QUEUE(p_netbuf) == (void*)1);\r
+ from_queue = (boolean_t)(IPOIB_FROM_QUEUE(p_netbuf) != NULL);\r
+ if (from_queue)\r
+ {\r
+ cl_perf_start( GetEndpt );\r
+ status = __endpt_mgr_ref( p_port, p_eth_hdr->dst, &p_desc->p_endpt );\r
+ cl_perf_stop( &p_port->p_adapter->perf, GetEndpt );\r
+ if( status == NDIS_STATUS_PENDING )\r
+ {\r
+ IPOIB_FROM_QUEUE(p_netbuf) = p_sgl;\r
+ cl_qlist_insert_head( &p_port->send_mgr.pending_list,\r
+ IPOIB_LIST_ITEM_FROM_PACKET( p_desc->p_netbuf_list ) );\r
+ goto send_end;\r
+ }\r
+ else if( status != NDIS_STATUS_SUCCESS )\r
+ {\r
+ ASSERT( status == NDIS_STATUS_NO_ROUTE_TO_DESTINATION );\r
+\r
+ if( ETH_IS_MULTICAST( p_eth_hdr->dst.addr ) )\r
+ {\r
+ if( ipoib_port_join_mcast( p_port, p_eth_hdr->dst,\r
+ IB_MC_REC_STATE_FULL_MEMBER) == IB_SUCCESS )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_SEND,\r
+ ("Multicast Mac - trying to join.\n") );\r
+ IPOIB_FROM_QUEUE(p_netbuf) = p_sgl;\r
+ cl_qlist_insert_head( &p_port->send_mgr.pending_list,\r
+ IPOIB_LIST_ITEM_FROM_PACKET( p_desc->p_netbuf_list ) );\r
+ goto send_end;\r
+ }\r
+ }\r
+ /*\r
+ * Complete the send as if we sent it - WHQL tests don't like the\r
+ * sends to fail.\r
+ */\r
+ cl_perf_start( ProcessFailedSends );\r
+ __process_failed_send( p_port, p_desc, NDIS_STATUS_SUCCESS,complete_flags );\r
+ cl_perf_stop( &p_port->p_adapter->perf, ProcessFailedSends );\r
+ goto send_end;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ cl_perf_start( SendMgrQueue );\r
+ if ( ETH_IS_MULTICAST( p_eth_hdr->dst.addr ) && \r
+ p_eth_hdr->type == ETH_PROT_TYPE_IP &&\r
+ !ETH_IS_BROADCAST( p_eth_hdr->dst.addr ) ) \r
+ {\r
+ ip_hdr_t *p_ip_hdr;\r
+ uint8_t *p_tmp;\r
+ MDL *p_ip_hdr_mdl;\r
+ UINT ip_hdr_mdl_len;\r
+\r
+ if(mdl_len >= sizeof(ip_hdr_t) + sizeof(eth_hdr_t))\r
+ {\r
+ p_ip_hdr = (ip_hdr_t*)(p_eth_hdr + 1);\r
+ }\r
+ else\r
+ {\r
+ NdisGetNextMdl(p_mdl,&p_ip_hdr_mdl);\r
+ // Extract the ip hdr \r
+ if( !p_ip_hdr_mdl )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed to get IP header buffer.\n") );\r
+ goto mc_end;\r
+ } \r
+ NdisQueryMdl(p_ip_hdr_mdl,&p_tmp,&ip_hdr_mdl_len,NormalPagePriority);\r
+ if( !p_tmp )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed to get IP header.\n") );\r
+ goto mc_end;\r
+ } \r
+ if( ip_hdr_mdl_len < sizeof(ip_hdr_t) )\r
+ {\r
+ /* This buffer is done for. Get the next buffer. */\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Buffer too small for IP packet.\n") );\r
+ goto mc_end;\r
+ }\r
+ p_ip_hdr = (ip_hdr_t*)(p_tmp + NET_BUFFER_CURRENT_MDL_OFFSET(p_netbuf));\r
+ p_eth_hdr->dst.addr[1] = ((unsigned char*)&p_ip_hdr->dst_ip)[0] & 0x0f;\r
+ p_eth_hdr->dst.addr[3] = ((unsigned char*)&p_ip_hdr->dst_ip)[1];\r
+ }\r
+ }\r
+mc_end:\r
+ status = __send_mgr_queue( p_port, p_eth_hdr, &p_desc->p_endpt );\r
+ cl_perf_stop( &p_port->p_adapter->perf, SendMgrQueue );\r
+ if( status == NDIS_STATUS_PENDING )\r
+ {\r
+ /* Queue net buffer list. */\r
+ cl_perf_start( QueuePacket );\r
+ NET_BUFFER_LIST_NEXT_NBL(p_net_buffer_list) = NULL;\r
+ IPOIB_FROM_QUEUE(p_netbuf) = p_sgl;\r
+ cl_qlist_insert_tail( &p_port->send_mgr.pending_list,\r
+ IPOIB_LIST_ITEM_FROM_PACKET(p_net_buffer_list) );\r
+ cl_perf_stop( &p_port->p_adapter->perf, QueuePacket );\r
+ goto send_end;\r
+ }\r
+ if( status != NDIS_STATUS_SUCCESS )\r
+ {\r
+ ASSERT( status == NDIS_STATUS_NO_ROUTE_TO_DESTINATION );\r
+ /*\r
+ * Complete the send as if we sent it - WHQL tests don't like the\r
+ * sends to fail.\r
+ */\r
+ cl_perf_start( ProcessFailedSends );\r
+ __process_failed_send( p_port, p_desc, NDIS_STATUS_SUCCESS, complete_flags );\r
+ cl_perf_stop( &p_port->p_adapter->perf, ProcessFailedSends );\r
+ goto send_end;\r
+ }\r
+ }\r
+ cl_perf_start( BuildSendDesc );\r
+ status = __build_send_desc( p_port, p_eth_hdr, p_mdl, mdl_len, p_sgl, p_desc );\r
+ cl_perf_stop( &p_port->p_adapter->perf, BuildSendDesc );\r
+\r
+ if( status != NDIS_STATUS_SUCCESS )\r
+ {\r
+ cl_perf_start( ProcessFailedSends );\r
+ __process_failed_send( p_port, p_desc, status, complete_flags );\r
+ cl_perf_stop( &p_port->p_adapter->perf, ProcessFailedSends );\r
+ goto send_end;\r
+ }\r
+\r
+ /* Post the WR. */\r
+ cl_perf_start( PostSend );\r
+ cl_msg_out("sending packet with wr-id =0x%x\n",&p_desc->send_wr[0].wr.wr_id );\r
+ 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 );\r
+ cl_perf_stop( &p_port->p_adapter->perf, PostSend );\r
+ if( ib_status != IB_SUCCESS )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ib_post_send returned %s\n", \r
+ p_port->p_adapter->p_ifc->get_err_str( ib_status )) );\r
+ cl_perf_start( ProcessFailedSends );\r
+ __process_failed_send( p_port, p_desc, NDIS_STATUS_FAILURE, complete_flags );\r
+ cl_perf_stop( &p_port->p_adapter->perf, ProcessFailedSends );\r
+ /* Flag the adapter as hung since posting is busted. */\r
+ p_port->p_adapter->hung = TRUE;\r
+ }\r
+ cl_atomic_inc( &p_port->send_mgr.depth );\r
+\r
+send_end:\r
+ if (status != NDIS_STATUS_SUCCESS) {\r
+// IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_SEND,\r
+ // ("Free S/G List: 0x%x.\n", (UINT) (PVOID) p_sgl) );\r
+ /*NdisMFreeNetBufferSGList(\r
+ p_port->p_adapter->NdisMiniportDmaHandle,\r
+ p_sgl,\r
+ p_netbuf);*/\r
+ \r
+ }\r
+ \r
+ \r
+ cl_spinlock_release( &p_port->send_lock );\r
+ IPOIB_EXIT( IPOIB_DBG_SEND );\r
+}\r
+\r
+static NDIS_STATUS\r
+__send_gen(\r
+ IN ipoib_port_t* const p_port,\r
+ IN ipoib_send_desc_t* const p_desc,\r
+ IN SCATTER_GATHER_LIST *p_sgl,\r
+ IN INT lso_data_index\r
+ )\r
+{\r
+ NDIS_STATUS status;\r
+ uint32_t i, j = 1;\r
+ uint32_t offset = sizeof(eth_hdr_t);\r
+ PERF_DECLARE( SendCopy );\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+ if( !p_sgl )\r
+ {\r
+ ASSERT( p_sgl );\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed to get SGL from packet.\n") );\r
+ return NDIS_STATUS_FAILURE;\r
+ }\r
+\r
+ /* Remember that one of the DS entries is reserved for the IPoIB header. */\r
+ if( ( p_sgl->NumberOfElements >= MAX_SEND_SGE ||\r
+ p_sgl->Elements[0].Length < sizeof(eth_hdr_t)) )\r
+ {\r
+\r
+ IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_SEND,\r
+ ("Too many buffers %d to fit in WR ds_array[%d] \\r
+ Or buffer[0] length %d < Eth header. Copying data.\n",\r
+ p_sgl->NumberOfElements, MAX_SEND_SGE, p_sgl->Elements[0].Length ) );\r
+ status = NDIS_STATUS_RESOURCES;\r
+ if( !p_port->p_adapter->params.cm_enabled )\r
+ {\r
+ cl_perf_start( SendCopy );\r
+ status = __send_copy( p_port, p_desc );\r
+ cl_perf_stop( &p_port->p_adapter->perf, SendCopy );\r
+ }\r
+ IPOIB_EXIT( IPOIB_DBG_SEND );\r
+ return status;\r
+ }\r
+\r
+ /*\r
+ * Skip the ethernet header. It is either the first element,\r
+ * or part of it.\r
+ */\r
+ i = 0;\r
+ if( lso_data_index )\r
+ { /* we have an LSO packet */\r
+ i = lso_data_index;\r
+ j = 0;\r
+ }\r
+ else while( offset )\r
+ {\r
+ if( p_sgl->Elements[i].Length <= offset )\r
+ {\r
+ offset -= p_sgl->Elements[i++].Length;\r
+ }\r
+ else\r
+ {\r
+ p_desc->send_wr[0].local_ds[j].vaddr =\r
+ p_sgl->Elements[i].Address.QuadPart + offset;\r
+ p_desc->send_wr[0].local_ds[j].length =\r
+ p_sgl->Elements[i].Length - offset;\r
+ p_desc->send_wr[0].local_ds[j].lkey = p_port->ib_mgr.lkey;\r
+ i++;\r
+ j++;\r
+ break;\r
+ }\r
+ }\r
+ /* Now fill in the rest of the local data segments. */\r
+ while( i < p_sgl->NumberOfElements )\r
+ {\r
+ p_desc->send_wr[0].local_ds[j].vaddr = p_sgl->Elements[i].Address.QuadPart;\r
+ p_desc->send_wr[0].local_ds[j].length = p_sgl->Elements[i].Length;\r
+ p_desc->send_wr[0].local_ds[j].lkey = p_port->ib_mgr.lkey;\r
+ i++;\r
+ j++;\r
+ }\r
+\r
+ /* Set the number of data segments. */\r
+ p_desc->send_wr[0].wr.num_ds = j;\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_SEND );\r
+ return NDIS_STATUS_SUCCESS;\r
+}\r
+#endif\r
+\r
+\r
+static NDIS_STATUS\r
+__send_mgr_filter_ip(\r
+ IN ipoib_port_t* const p_port,\r
+ IN const eth_hdr_t* const p_eth_hdr,\r
+ IN MDL* p_mdl,\r
+ IN size_t buf_len,\r
+ IN SCATTER_GATHER_LIST *p_sgl,\r
+ IN OUT ipoib_send_desc_t* const p_desc )\r
+{\r
+ NDIS_STATUS status;\r
+ ip_hdr_t *p_ip_hdr;\r
+ uint32_t ip_packet_len;\r
+ size_t iph_size_in_bytes;\r
+ size_t iph_options_size;\r
+ \r
+ PERF_DECLARE( QueryIp );\r
+ PERF_DECLARE( SendTcp );\r
+ PERF_DECLARE( FilterUdp );\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+ if( !buf_len )\r
+ {\r
+ cl_perf_start( QueryIp );\r
+ NdisGetNextMdl ( p_mdl, &p_mdl );\r
+ if( !p_mdl )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed to get IP header buffer.\n") );\r
+ return NDIS_STATUS_FAILURE;\r
+ }\r
+\r
+ NdisQueryMdl(p_mdl, &p_ip_hdr, &buf_len, NormalPagePriority);\r
+ if( !p_ip_hdr )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed to query IP header buffer.\n") );\r
+ return NDIS_STATUS_FAILURE;\r
+ }\r
+ cl_perf_stop( &p_port->p_adapter->perf, QueryIp );\r
+ }\r
+ else\r
+ {\r
+ p_ip_hdr = (ip_hdr_t*)(p_eth_hdr + 1);\r
+ }\r
+ if( buf_len < sizeof(ip_hdr_t) )\r
+ {\r
+ /* This buffer is done for. Get the next buffer. */\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Buffer too small for IP packet.\n") );\r
+ return NDIS_STATUS_BUFFER_TOO_SHORT;\r
+ }\r
+\r
+ switch( p_ip_hdr->prot )\r
+ {\r
+ case IP_PROT_UDP:\r
+\r
+ cl_perf_start( FilterUdp );\r
+ status = __send_mgr_filter_udp(\r
+ p_port, p_ip_hdr, p_mdl, (buf_len - sizeof(ip_hdr_t)), p_sgl, p_desc );\r
+ cl_perf_stop( &p_port->p_adapter->perf, FilterUdp );\r
+ if( status == NDIS_STATUS_PENDING )\r
+ { /* not DHCP packet, keep going */\r
+ if( ETH_IS_MULTICAST( p_eth_hdr->dst.addr ) )\r
+ p_desc->send_dir = SEND_UD_QP;\r
+ else\r
+ p_desc->send_dir = SEND_RC_QP;\r
+ break;\r
+ }\r
+ return status;\r
+ \r
+ case IP_PROT_TCP:\r
+ p_desc->send_dir = SEND_RC_QP;\r
+ break;\r
+ case IP_PROT_IGMP:\r
+ /*\r
+ In igmp packet I saw that iph arrive in 2 NDIS_BUFFERs:\r
+ 1. iph\r
+ 2. ip options\r
+ So to get the IGMP packet we need to skip the ip options NDIS_BUFFER\r
+ */\r
+ iph_size_in_bytes = (p_ip_hdr->ver_hl & 0xf) * 4;\r
+ iph_options_size = iph_size_in_bytes - buf_len;\r
+ buf_len -= sizeof(ip_hdr_t);//without ipheader\r
+\r
+ /*\r
+ Could be a case that arrived igmp packet not from type IGMPv2 ,\r
+ but IGMPv1 or IGMPv3.\r
+ We anyway pass it to __send_mgr_filter_igmp_v2().\r
+ */\r
+ status =\r
+ __send_mgr_filter_igmp_v2( p_port, p_ip_hdr, iph_options_size, p_mdl, buf_len );\r
+ if( status != NDIS_STATUS_SUCCESS )\r
+ return status;\r
+\r
+ case IP_PROT_ICMP:\r
+ p_desc->send_dir = SEND_UD_QP;\r
+ default:\r
+ break;\r
+ }\r
+ \r
+ if( !p_port->p_adapter->params.cm_enabled )\r
+ {\r
+ p_desc->send_dir = SEND_UD_QP;\r
+ goto send_gen;\r
+ }\r
+ else if( endpt_cm_get_state( p_desc->p_endpt ) != IPOIB_CM_CONNECTED )\r
+ {\r
+ p_desc->send_dir = SEND_UD_QP;\r
+ }\r
+ if( p_desc->send_dir == SEND_UD_QP )\r
+ {\r
+ ip_packet_len = cl_ntoh16( p_ip_hdr->length );\r
+ if( ip_packet_len > p_port->p_adapter->params.payload_mtu )\r
+ {\r
+ //TODO: NDIS60\r
+ #if 0\r
+ status = __send_fragments( p_port, p_desc, (eth_hdr_t* const)p_eth_hdr,\r
+ (ip_hdr_t* const)p_ip_hdr, (uint32_t)buf_len, p_mdl );\r
+ return status;\r
+ #endif\r
+ ASSERT(FALSE);\r
+ }\r
+ }\r
+\r
+send_gen:\r
+ cl_perf_start( SendTcp );\r
+ status = __send_gen( p_port, p_desc, p_sgl, 0 );\r
+ cl_perf_stop( &p_port->p_adapter->perf, SendTcp );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_SEND );\r
+ return status;\r
+}\r
+\r
+static NDIS_STATUS\r
+__send_mgr_filter_igmp_v2(\r
+ IN ipoib_port_t* const p_port,\r
+ IN const ip_hdr_t* const p_ip_hdr,\r
+ IN size_t iph_options_size,\r
+ IN MDL* p_mdl,\r
+ IN size_t buf_len )\r
+{\r
+ igmp_v2_hdr_t *p_igmp_v2_hdr = NULL;\r
+ NDIS_STATUS endpt_status;\r
+ ipoib_endpt_t* p_endpt = NULL;\r
+ mac_addr_t fake_mcast_mac;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_MCAST,\r
+ ("buf_len = %d,iph_options_size = %d\n",(int)buf_len,(int)iph_options_size ) );\r
+\r
+ if( !buf_len )\r
+ {\r
+ // To get the IGMP packet we need to skip the ip options NDIS_BUFFER (if exists)\r
+ while ( iph_options_size )\r
+ {\r
+ NdisGetNextMdl( p_mdl, &p_mdl );\r
+ if( !p_mdl )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed to get IGMPv2 header buffer.\n") );\r
+ return NDIS_STATUS_FAILURE;\r
+ }\r
+ NdisQueryMdl( p_mdl, &p_igmp_v2_hdr, &buf_len, NormalPagePriority );\r
+ if( !p_igmp_v2_hdr )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed to query IGMPv2 header buffer.\n") );\r
+ return NDIS_STATUS_FAILURE;\r
+ }\r
+ iph_options_size-=buf_len;\r
+ }\r
+ \r
+ NdisGetNextMdl( p_mdl, &p_mdl );\r
+ if( !p_mdl )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed to get IGMPv2 header buffer.\n") );\r
+ return NDIS_STATUS_FAILURE;\r
+ }\r
+ NdisQueryMdl( p_mdl, &p_igmp_v2_hdr, &buf_len, NormalPagePriority );\r
+ if( !p_igmp_v2_hdr )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed to query IGMPv2 header buffer.\n") );\r
+ return NDIS_STATUS_FAILURE;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ /* assuming ip header and options are in the same packet */\r
+ p_igmp_v2_hdr = (igmp_v2_hdr_t *) GetIpPayloadPtr(p_ip_hdr);\r
+ }\r
+ /* Get the IGMP header length. */\r
+ if( buf_len < sizeof(igmp_v2_hdr_t) )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Buffer not large enough for IGMPv2 packet.\n") );\r
+ return NDIS_STATUS_BUFFER_TOO_SHORT;\r
+ }\r
+\r
+ // build fake mac from igmp packet group address\r
+ fake_mcast_mac.addr[0] = 1;\r
+ fake_mcast_mac.addr[1] = ((unsigned char*)&p_igmp_v2_hdr->group_address)[0] & 0x0f;\r
+ fake_mcast_mac.addr[2] = 0x5E;\r
+ fake_mcast_mac.addr[3] = ((unsigned char*)&p_igmp_v2_hdr->group_address)[1];\r
+ fake_mcast_mac.addr[4] = ((unsigned char*)&p_igmp_v2_hdr->group_address)[2];\r
+ fake_mcast_mac.addr[5] = ((unsigned char*)&p_igmp_v2_hdr->group_address)[3];\r
+\r
+ switch ( p_igmp_v2_hdr->type )\r
+ {\r
+ case IGMP_V2_MEMBERSHIP_REPORT:\r
+ /* \r
+ This mean that some body open listener on this group \r
+ Change type of mcast endpt to SEND_RECV endpt. So mcast garbage collector \r
+ will not delete this mcast endpt.\r
+ */\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_MCAST,\r
+ ("Catched IGMP_V2_MEMBERSHIP_REPORT message\n") );\r
+ endpt_status = __endpt_mgr_ref( p_port, fake_mcast_mac, &p_endpt );\r
+ if ( p_endpt )\r
+ {\r
+ cl_obj_lock( &p_port->obj );\r
+ p_endpt->is_mcast_listener = TRUE;\r
+ cl_obj_unlock( &p_port->obj );\r
+ ipoib_endpt_deref( p_endpt );\r
+ }\r
+ break;\r
+\r
+ case IGMP_V2_LEAVE_GROUP:\r
+ /* \r
+ This mean that somebody CLOSE listener on this group .\r
+ Change type of mcast endpt to SEND_ONLY endpt. So mcast \r
+ garbage collector will delete this mcast endpt next time.\r
+ */\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_MCAST,\r
+ ("Catched IGMP_V2_LEAVE_GROUP message\n") );\r
+ endpt_status = __endpt_mgr_ref( p_port, fake_mcast_mac, &p_endpt );\r
+ if ( p_endpt )\r
+ {\r
+ cl_obj_lock( &p_port->obj );\r
+ p_endpt->is_mcast_listener = FALSE;\r
+ p_endpt->is_in_use = FALSE;\r
+ cl_obj_unlock( &p_port->obj );\r
+ ipoib_endpt_deref( p_endpt );\r
+ }\r
+\r
+ __port_do_mcast_garbage(p_port);\r
+\r
+ break;\r
+\r
+ default:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_MCAST,\r
+ ("Send Unknown IGMP message: 0x%x \n", p_igmp_v2_hdr->type ) );\r
+ break;\r
+ }\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_SEND );\r
+ return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+static NDIS_STATUS\r
+__send_mgr_filter_udp(\r
+ IN ipoib_port_t* const p_port,\r
+ IN const ip_hdr_t* const p_ip_hdr,\r
+ IN MDL* p_mdl,\r
+ IN size_t buf_len,\r
+ IN SCATTER_GATHER_LIST *p_sgl,\r
+ IN OUT ipoib_send_desc_t* const p_desc )\r
+{\r
+ NDIS_STATUS status;\r
+ udp_hdr_t *p_udp_hdr;\r
+ PERF_DECLARE( QueryUdp );\r
+ PERF_DECLARE( SendUdp );\r
+ PERF_DECLARE( FilterDhcp );\r
+ //TODO NDIS60 remove this param\r
+ UNUSED_PARAM(p_sgl);\r
+ IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+ if( !buf_len )\r
+ {\r
+ cl_perf_start( QueryUdp );\r
+ NdisGetNextMdl( p_mdl, &p_mdl );\r
+ if( !p_mdl )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed to get UDP header buffer.\n") );\r
+ return NDIS_STATUS_FAILURE;\r
+ }\r
+ NdisQueryMdl( p_mdl, &p_udp_hdr, &buf_len, NormalPagePriority );\r
+ if( !p_udp_hdr )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed to query UDP header buffer.\n") );\r
+ return NDIS_STATUS_FAILURE;\r
+ }\r
+ cl_perf_stop( &p_port->p_adapter->perf, QueryUdp );\r
+ }\r
+ else\r
+ {\r
+ p_udp_hdr = (udp_hdr_t*)GetIpPayloadPtr(p_ip_hdr);\r
+ }\r
+ /* Get the UDP header and check the destination port numbers. */\r
+ \r
+ if (p_ip_hdr->offset > 0) {\r
+ /* This is a fragmented part of UDP packet\r
+ * Only first packet will contain UDP header in such case\r
+ * So, return if offset > 0\r
+ */\r
+ return NDIS_STATUS_PENDING;\r
+ }\r
+ \r
+ if( buf_len < sizeof(udp_hdr_t) )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Buffer not large enough for UDP packet.\n") );\r
+ return NDIS_STATUS_BUFFER_TOO_SHORT;\r
+ }\r
+\r
+ if( (p_udp_hdr->src_port != DHCP_PORT_CLIENT ||\r
+ p_udp_hdr->dst_port != DHCP_PORT_SERVER) &&\r
+ (p_udp_hdr->src_port != DHCP_PORT_SERVER ||\r
+ p_udp_hdr->dst_port != DHCP_PORT_CLIENT) )\r
+ {\r
+ /* Not a DHCP packet. */\r
+ return NDIS_STATUS_PENDING;\r
+ }\r
+\r
+ buf_len -= sizeof(udp_hdr_t);\r
+\r
+ /* Allocate our scratch buffer. */\r
+ p_desc->p_buf = (send_buf_t*)\r
+ ExAllocateFromNPagedLookasideList( &p_port->buf_mgr.send_buf_list );\r
+ if( !p_desc->p_buf )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed to query DHCP packet buffer.\n") );\r
+ return NDIS_STATUS_RESOURCES;\r
+ }\r
+ /* Copy the IP and UDP headers. */\r
+ cl_memcpy( &p_desc->p_buf->ip.hdr, p_ip_hdr , sizeof(ip_hdr_t) );\r
+ cl_memcpy(\r
+ &p_desc->p_buf->ip.prot.udp.hdr, p_udp_hdr, sizeof(udp_hdr_t) );\r
+\r
+ cl_perf_start( FilterDhcp );\r
+ status = __send_mgr_filter_dhcp(\r
+ p_port, p_udp_hdr, p_mdl, buf_len, p_desc );\r
+ cl_perf_stop( &p_port->p_adapter->perf, FilterDhcp );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_SEND );\r
+ return status;\r
+}\r
+\r
+unsigned short ipchksum(unsigned short *ip, int len)\r
+{\r
+ unsigned long sum = 0;\r
+\r
+ len >>= 1;\r
+ while (len--) {\r
+ sum += *(ip++);\r
+ if (sum > 0xFFFF)\r
+ sum -= 0xFFFF;\r
+ }\r
+ return (unsigned short)((~sum) & 0x0000FFFF);\r
+}\r
+\r
+static NDIS_STATUS\r
+__send_mgr_filter_dhcp(\r
+ IN ipoib_port_t* const p_port,\r
+ IN const udp_hdr_t* const p_udp_hdr,\r
+ IN NDIS_BUFFER* p_mdl,\r
+ IN size_t buf_len,\r
+ IN OUT ipoib_send_desc_t* const p_desc )\r
+{\r
+ dhcp_pkt_t *p_dhcp;\r
+ dhcp_pkt_t *p_ib_dhcp;\r
+ uint8_t *p_option, *p_cid = NULL;\r
+ uint8_t msg = 0;\r
+ size_t len;\r
+ ib_gid_t gid;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+ if( !buf_len )\r
+ {\r
+ NdisGetNextMdl( p_mdl, &p_mdl );\r
+ if( !p_mdl )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed to get DHCP buffer.\n") );\r
+ return NDIS_STATUS_FAILURE;\r
+ }\r
+ NdisQueryMdl( p_mdl, &p_dhcp, &buf_len, NormalPagePriority );\r
+ if( !p_dhcp )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed to query DHCP buffer.\n") );\r
+ return NDIS_STATUS_FAILURE;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ p_dhcp = (dhcp_pkt_t*)(p_udp_hdr + 1);\r
+ }\r
+\r
+ if( buf_len < DHCP_MIN_SIZE )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Buffer not large enough for DHCP packet.\n") );\r
+ return NDIS_STATUS_BUFFER_TOO_SHORT;\r
+ }\r
+\r
+ p_ib_dhcp = &p_desc->p_buf->ip.prot.udp.dhcp;\r
+ cl_memcpy( p_ib_dhcp, p_dhcp, buf_len );\r
+\r
+ /* Now scan through the options looking for the client identifier. */\r
+ p_option = &p_ib_dhcp->options[4];\r
+ while( *p_option != DHCP_OPT_END && p_option < &p_ib_dhcp->options[312] )\r
+ {\r
+ switch( *p_option )\r
+ {\r
+ case DHCP_OPT_PAD:\r
+ p_option++;\r
+ break;\r
+\r
+ case DHCP_OPT_MSG:\r
+ msg = p_option[2];\r
+ p_option += 3;\r
+ break;\r
+\r
+ case DHCP_OPT_CLIENT_ID:\r
+ p_cid = p_option;\r
+ /* Fall through. */\r
+\r
+ default:\r
+ /*\r
+ * All other options have a length byte following the option code.\r
+ * Offset by the length to get to the next option.\r
+ */\r
+ p_option += (p_option[1] + 2);\r
+ }\r
+ }\r
+\r
+ switch( msg )\r
+ {\r
+ /* Client messages */\r
+ case DHCPDISCOVER:\r
+ case DHCPREQUEST:\r
+ p_ib_dhcp->flags |= DHCP_FLAGS_BROADCAST;\r
+ /* Fall through */\r
+ case DHCPDECLINE:\r
+ case DHCPRELEASE:\r
+ case DHCPINFORM:\r
+ /* Fix up the client identifier option */\r
+ if( p_cid )\r
+ {\r
+ /* do we need to replace it ? len eq ETH MAC sz 'and' MAC is mine */\r
+ if( p_cid[1] == HW_ADDR_LEN+1 && !cl_memcmp( &p_cid[3],\r
+ &p_port->p_adapter->params.conf_mac.addr, HW_ADDR_LEN ) )\r
+ {\r
+ /* Make sure there's room to extend it. 23 is the size of\r
+ * the CID option for IPoIB.\r
+ */\r
+ if( buf_len + 23 - p_cid[1] > sizeof(dhcp_pkt_t) )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Can't convert CID to IPoIB format.\n") );\r
+ return NDIS_STATUS_RESOURCES;\r
+ }\r
+ /* Move the existing options down, and add a new CID option */\r
+ len = p_option - ( p_cid + p_cid[1] + 2 );\r
+ p_option = p_cid + p_cid[1] + 2;\r
+ RtlMoveMemory( p_cid, p_option, len );\r
+ \r
+ p_cid += len;\r
+ p_cid[0] = DHCP_OPT_CLIENT_ID;\r
+ p_cid[1] = 21;\r
+ p_cid[2] = DHCP_HW_TYPE_IB;\r
+ }\r
+ else\r
+ {\r
+ p_cid[2] = DHCP_HW_TYPE_IB;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ /*\r
+ * Make sure there's room to extend it. 23 is the size of\r
+ * the CID option for IPoIB.\r
+ */\r
+ if( buf_len + 23 > sizeof(dhcp_pkt_t) )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Can't convert CID to IPoIB format.\n") );\r
+ return NDIS_STATUS_RESOURCES;\r
+ }\r
+\r
+ p_cid = p_option;\r
+ p_option = p_cid + 23;\r
+ p_option[0] = DHCP_OPT_END;\r
+ p_cid[0] = DHCP_OPT_CLIENT_ID;\r
+ p_cid[1] = 21;\r
+ p_cid[2] = DHCP_HW_TYPE_IB;\r
+ }\r
+\r
+ CL_ASSERT( p_cid[1] == 21 );\r
+ p_cid[23]= DHCP_OPT_END;\r
+ ib_gid_set_default( &gid, p_port->p_adapter->guids.port_guid.guid );\r
+ cl_memcpy( &p_cid[7], &gid, sizeof(ib_gid_t) );\r
+ cl_memcpy( &p_cid[3], &p_port->ib_mgr.qpn, sizeof(p_port->ib_mgr.qpn) ); \r
+ p_ib_dhcp->htype = DHCP_HW_TYPE_IB;\r
+\r
+ /* update lengths to include any change we made */\r
+ p_desc->p_buf->ip.hdr.length = cl_ntoh16( sizeof(ip_hdr_t) + sizeof(udp_hdr_t) + sizeof(dhcp_pkt_t) );\r
+ p_desc->p_buf->ip.prot.udp.hdr.length = cl_ntoh16( sizeof(udp_hdr_t) + sizeof(dhcp_pkt_t) );\r
+\r
+ /* update crc in ip header */\r
+ //if( !p_port->p_adapter->params.send_chksum_offload )\r
+ //{ //TODO ?\r
+ p_desc->p_buf->ip.hdr.chksum = 0;\r
+ p_desc->p_buf->ip.hdr.chksum = ipchksum((unsigned short*) &p_desc->p_buf->ip.hdr, sizeof(ip_hdr_t));\r
+ //} TODO ??\r
+ break;\r
+\r
+ /* Server messages. */\r
+ case DHCPOFFER:\r
+ case DHCPACK:\r
+ case DHCPNAK:\r
+ /* don't touch server messages */\r
+ break;\r
+\r
+ default:\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Invalide message type.\n") );\r
+ return NDIS_STATUS_INVALID_DATA;\r
+ }\r
+ /* no chksum for udp */\r
+ p_desc->p_buf->ip.prot.udp.hdr.chksum = 0;\r
+ p_desc->send_wr[0].local_ds[1].vaddr = cl_get_physaddr( p_desc->p_buf );\r
+ p_desc->send_wr[0].local_ds[1].length = sizeof(ip_hdr_t) + sizeof(udp_hdr_t) + sizeof(dhcp_pkt_t);\r
+ p_desc->send_wr[0].local_ds[1].lkey = p_port->ib_mgr.lkey;\r
+ p_desc->send_wr[0].wr.num_ds = 2;\r
+ p_desc->send_dir = SEND_UD_QP;\r
+ IPOIB_EXIT( IPOIB_DBG_SEND );\r
+ return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NDIS_STATUS\r
+__send_mgr_filter_arp(\r
+ IN ipoib_port_t* const p_port,\r
+ IN const eth_hdr_t* const p_eth_hdr,\r
+ IN MDL* p_mdl,\r
+ IN size_t buf_len,\r
+ IN OUT ipoib_send_desc_t* const p_desc )\r
+{\r
+ arp_pkt_t *p_arp;\r
+ ipoib_arp_pkt_t *p_ib_arp;\r
+ NDIS_STATUS status;\r
+ mac_addr_t null_hw = {0};\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_SEND );\r
+ \r
+ if( !buf_len )\r
+ {\r
+ NdisGetNextMdl( p_mdl, &p_mdl );\r
+ if( !p_mdl )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed to get ARP buffer.\n") );\r
+ return NDIS_STATUS_FAILURE;\r
+ }\r
+ NdisQueryMdl( p_mdl, &p_arp, &buf_len, NormalPagePriority );\r
+ if( !p_arp )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed to get query ARP buffer.\n") );\r
+ return NDIS_STATUS_FAILURE;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ p_arp = (arp_pkt_t*)(p_eth_hdr + 1);\r
+ }\r
+\r
+ /* Single buffer ARP packet. */\r
+ if( buf_len < sizeof(arp_pkt_t) )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Buffer too short for ARP.\n") );\r
+ return NDIS_STATUS_BUFFER_TOO_SHORT;\r
+ }\r
+\r
+ if( p_arp->prot_type != ETH_PROT_TYPE_IP )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Unsupported protocol type.\n") );\r
+ return NDIS_STATUS_INVALID_DATA;\r
+ }\r
+\r
+ /* Allocate our scratch buffer. */\r
+ p_desc->p_buf = (send_buf_t*)\r
+ NdisAllocateFromNPagedLookasideList( &p_port->buf_mgr.send_buf_list );\r
+ if( !p_desc->p_buf )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed to query ARP packet buffer.\n") );\r
+ return NDIS_STATUS_RESOURCES;\r
+ }\r
+ p_ib_arp = (ipoib_arp_pkt_t*)p_desc->p_buf;\r
+\r
+ /* Convert the ARP payload. */\r
+ p_ib_arp->hw_type = ARP_HW_TYPE_IB;\r
+ p_ib_arp->prot_type = p_arp->prot_type;\r
+ p_ib_arp->hw_size = sizeof(ipoib_hw_addr_t);\r
+ p_ib_arp->prot_size = p_arp->prot_size;\r
+ p_ib_arp->op = p_arp->op;\r
+ \r
+ ipoib_addr_set_qpn( &p_ib_arp->src_hw, p_port->ib_mgr.qpn );\r
+#if 0\r
+\r
+ if( p_port->p_adapter->params.cm_enabled )\r
+ {\r
+ ipoib_addr_set_flags( &p_ib_arp->src_hw, IPOIB_CM_FLAG_RC );\r
+ }\r
+#endif\r
+\r
+ ib_gid_set_default( &p_ib_arp->src_hw.gid,\r
+ p_port->p_adapter->guids.port_guid.guid );\r
+ p_ib_arp->src_ip = p_arp->src_ip;\r
+ if( cl_memcmp( &p_arp->dst_hw, &null_hw, sizeof(mac_addr_t) ) )\r
+ {\r
+ /* Get the endpoint referenced by the dst_hw address. */\r
+ net32_t qpn = 0;\r
+ status = __endpt_mgr_get_gid_qpn( p_port, p_arp->dst_hw,\r
+ &p_ib_arp->dst_hw.gid, &qpn );\r
+ if( status != NDIS_STATUS_SUCCESS )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed lookup of destination HW address\n") );\r
+ return status;\r
+ }\r
+ ipoib_addr_set_qpn( &p_ib_arp->dst_hw, qpn );\r
+#if 0\r
+ if( p_arp->op == ARP_OP_REP && \r
+ p_port->p_adapter->params.cm_enabled && \r
+ p_desc->p_endpt->cm_flag == IPOIB_CM_FLAG_RC )\r
+ {\r
+ cm_state_t cm_state;\r
+ cm_state = \r
+ ( cm_state_t )InterlockedCompareExchange( (volatile LONG *)&p_desc->p_endpt->conn.state,\r
+ IPOIB_CM_CONNECT, IPOIB_CM_DISCONNECTED );\r
+ switch( cm_state )\r
+ {\r
+ case IPOIB_CM_DISCONNECTED:\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+ ("ARP REPLY pending Endpt[%p] QPN %#x MAC %02x:%02x:%02x:%02x:%02x:%02x\n",\r
+ p_desc->p_endpt, \r
+ cl_ntoh32( ipoib_addr_get_qpn( &p_ib_arp->dst_hw )),\r
+ p_desc->p_endpt->mac.addr[0], p_desc->p_endpt->mac.addr[1],\r
+ p_desc->p_endpt->mac.addr[2], p_desc->p_endpt->mac.addr[3],\r
+ p_desc->p_endpt->mac.addr[4], p_desc->p_endpt->mac.addr[5] ) );\r
+ ipoib_addr_set_sid( &p_desc->p_endpt->conn.service_id,\r
+ ipoib_addr_get_qpn( &p_ib_arp->dst_hw ) );\r
+\r
+ NdisFreeToNPagedLookasideList(\r
+ &p_port->buf_mgr.send_buf_list, p_desc->p_buf );\r
+ cl_qlist_insert_tail( &p_port->send_mgr.pending_list,\r
+ IPOIB_LIST_ITEM_FROM_PACKET( p_desc->p_buf ) );\r
+ NdisInterlockedInsertTailList( &p_port->endpt_mgr.pending_conns, \r
+ &p_desc->p_endpt->list_item, \r
+ &p_port->endpt_mgr.conn_lock );\r
+ cl_event_signal( &p_port->endpt_mgr.event );\r
+ return NDIS_STATUS_PENDING;\r
+ \r
+ case IPOIB_CM_CONNECT:\r
+ /* queue ARP REP packet until connected */\r
+ NdisFreeToNPagedLookasideList(\r
+ &p_port->buf_mgr.send_buf_list, p_desc->p_buf );\r
+ cl_qlist_insert_tail( &p_port->send_mgr.pending_list,\r
+ IPOIB_LIST_ITEM_FROM_PACKET( p_desc->p_pkt ) );\r
+ return NDIS_STATUS_PENDING;\r
+ default:\r
+ break;\r
+ }\r
+ }\r
+#endif\r
+ }\r
+ else\r
+ {\r
+ cl_memclr( &p_ib_arp->dst_hw, sizeof(ipoib_hw_addr_t) );\r
+ }\r
+ \r
+#if 0 //DBG\r
+ if( p_port->p_adapter->params.cm_enabled )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+ (" ARP %s SEND to ENDPT[%p] State: %d flag: %#x, QPN: %#x MAC %02x:%02x:%02x:%02x:%02x:%02x\n",\r
+ ( p_ib_arp->op == ARP_OP_REP ? "REP": "REQ"), p_desc->p_endpt, \r
+ endpt_cm_get_state( p_desc->p_endpt ),\r
+ p_desc->p_endpt->cm_flag, \r
+ cl_ntoh32( ipoib_addr_get_qpn( &p_ib_arp->dst_hw )),\r
+ p_desc->p_endpt->mac.addr[0], p_desc->p_endpt->mac.addr[1],\r
+ p_desc->p_endpt->mac.addr[2], p_desc->p_endpt->mac.addr[3],\r
+ p_desc->p_endpt->mac.addr[4], p_desc->p_endpt->mac.addr[5] ));\r
+ }\r
+#endif\r
+\r
+ p_ib_arp->dst_ip = p_arp->dst_ip;\r
+\r
+ p_desc->send_wr[0].local_ds[1].vaddr = cl_get_physaddr( p_ib_arp );\r
+ p_desc->send_wr[0].local_ds[1].length = sizeof(ipoib_arp_pkt_t);\r
+ p_desc->send_wr[0].local_ds[1].lkey = p_port->ib_mgr.lkey;\r
+ p_desc->send_wr[0].wr.num_ds = 2;\r
+ p_desc->send_wr[0].wr.p_next = NULL;\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_SEND );\r
+ return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+static inline NDIS_STATUS\r
+__send_mgr_queue(\r
+ IN ipoib_port_t* const p_port,\r
+ IN eth_hdr_t* const p_eth_hdr,\r
+ OUT ipoib_endpt_t** const pp_endpt )\r
+{\r
+ NDIS_STATUS status;\r
+\r
+ PERF_DECLARE( GetEndpt );\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+ /* Check the send queue and pend the request if not empty. */\r
+ if( cl_qlist_count( &p_port->send_mgr.pending_list ) )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_WARNING, IPOIB_DBG_SEND,\r
+ ("Pending list not empty.\n") );\r
+ return NDIS_STATUS_PENDING;\r
+ }\r
+\r
+ /* Check the send queue and pend the request if not empty. */\r
+ if( p_port->send_mgr.depth == p_port->p_adapter->params.sq_depth )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_WARNING, IPOIB_DBG_SEND,\r
+ ("No available WQEs.\n") );\r
+ return NDIS_STATUS_PENDING;\r
+ }\r
+\r
+ cl_perf_start( GetEndpt );\r
+ status = __endpt_mgr_ref( p_port, p_eth_hdr->dst, pp_endpt );\r
+ cl_perf_stop( &p_port->p_adapter->perf, GetEndpt );\r
+\r
+ if( status == NDIS_STATUS_NO_ROUTE_TO_DESTINATION &&\r
+ ETH_IS_MULTICAST( p_eth_hdr->dst.addr ) )\r
+ {\r
+ if( ipoib_port_join_mcast( p_port, p_eth_hdr->dst, \r
+ IB_MC_REC_STATE_FULL_MEMBER) == IB_SUCCESS )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_SEND,\r
+ ("Multicast Mac - trying to join.\n") );\r
+ return NDIS_STATUS_PENDING;\r
+ }\r
+ }\r
+ else if ( status == NDIS_STATUS_SUCCESS && \r
+ ETH_IS_MULTICAST( p_eth_hdr->dst.addr ) && \r
+ !ETH_IS_BROADCAST( p_eth_hdr->dst.addr ) )\r
+ {\r
+ CL_ASSERT( (*pp_endpt) );\r
+ CL_ASSERT((*pp_endpt)->h_mcast != NULL);\r
+ (*pp_endpt)->is_in_use = TRUE;\r
+ }\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_SEND );\r
+ return status;\r
+}\r
+\r
+\r
+static NDIS_STATUS\r
+__build_send_desc(\r
+ IN ipoib_port_t* const p_port,\r
+ IN eth_hdr_t* const p_eth_hdr,\r
+ IN MDL* const p_mdl,\r
+ IN const size_t mdl_len,\r
+ IN SCATTER_GATHER_LIST *p_sgl,\r
+ IN OUT ipoib_send_desc_t* const p_desc )\r
+{\r
+ NDIS_STATUS status;\r
+ int32_t hdr_idx;\r
+ uint32_t mss = 0;\r
+\r
+ PNDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO p_checksum_list_info;\r
+ PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO p_lso_info;\r
+ PERF_DECLARE( SendMgrFilter );\r
+ \r
+ IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+ /* Format the send descriptor. */\r
+ p_checksum_list_info =\r
+ (PNDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO) NET_BUFFER_LIST_INFO( p_desc->p_netbuf_list,TcpIpChecksumNetBufferListInfo);\r
+\r
+ // Calculate LSO\r
+ if( p_port->p_adapter->params.lso ) {\r
+ p_lso_info = \r
+ (PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO) \r
+ NET_BUFFER_LIST_INFO( p_desc->p_netbuf_list, TcpLargeSendNetBufferListInfo );\r
+ ASSERT(p_lso_info);\r
+ if (p_lso_info) {\r
+ mss = (p_lso_info->LsoV1Transmit.MSS | p_lso_info->LsoV2Transmit.MSS);\r
+ }\r
+ }\r
+ \r
+ /* Format the send descriptor. */\r
+ hdr_idx = cl_atomic_inc( &p_port->hdr_idx );\r
+ hdr_idx &= (p_port->p_adapter->params.sq_depth - 1);\r
+ ASSERT( hdr_idx < p_port->p_adapter->params.sq_depth );\r
+ p_port->hdr[hdr_idx].type = p_eth_hdr->type;\r
+ p_port->hdr[hdr_idx].resv = 0;\r
+\r
+ p_desc->send_wr[0].local_ds[0].vaddr = cl_get_physaddr( &p_port->hdr[hdr_idx] );\r
+ p_desc->send_wr[0].local_ds[0].length = sizeof(ipoib_hdr_t);\r
+ p_desc->send_wr[0].local_ds[0].lkey = p_port->ib_mgr.lkey;\r
+ p_desc->send_wr[0].wr.send_opt = 0;\r
+\r
+ \r
+ \r
+ if (mss) { //We have LSO packet\r
+ ASSERT( mss == (p_lso_info->LsoV1Transmit.MSS & p_lso_info->LsoV2Transmit.MSS));\r
+ ASSERT ( (mss & (1<<20)) == mss);\r
+ status = __build_lso_desc( p_port, p_desc, mss, p_sgl, hdr_idx, p_lso_info );\r
+ if( status != NDIS_STATUS_SUCCESS )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("__build_lso_desc returned 0x%08X.\n", status) );\r
+ return status;\r
+ }\r
+ }\r
+ \r
+ else\r
+ {\r
+ uint32_t i;\r
+ cl_perf_start( SendMgrFilter );\r
+ status = __send_mgr_filter(\r
+ p_port, p_eth_hdr, p_mdl, mdl_len,p_sgl, p_desc );\r
+ cl_perf_stop( &p_port->p_adapter->perf, SendMgrFilter );\r
+ if( status != NDIS_STATUS_SUCCESS )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("__send_mgr_filter returned 0x%08X.\n", status) );\r
+ return status;\r
+ }\r
+\r
+ if( p_desc->send_dir == SEND_UD_QP )\r
+ {\r
+ p_desc->send_qp = p_port->ib_mgr.h_qp; // UD QP\r
+ for( i = 0; i < p_desc->num_wrs; i++ )\r
+ {\r
+ p_desc->send_wr[i].wr.dgrm.ud.remote_qp = p_desc->p_endpt->qpn;\r
+ p_desc->send_wr[i].wr.dgrm.ud.remote_qkey = p_port->ib_mgr.bcast_rec.qkey;\r
+ p_desc->send_wr[i].wr.dgrm.ud.h_av = p_desc->p_endpt->h_av;\r
+ p_desc->send_wr[i].wr.dgrm.ud.pkey_index = p_port->pkey_index;\r
+ p_desc->send_wr[i].wr.dgrm.ud.rsvd = NULL;\r
+ p_desc->send_wr[i].wr.send_opt = 0;\r
+\r
+ if( p_port->p_adapter->params.send_chksum_offload && \r
+ ( p_checksum_list_info->Transmit.IsIPv4 || \r
+ p_checksum_list_info->Transmit.IsIPv6 ))\r
+ {\r
+ // Set transimition checksum offloading\r
+ if( p_checksum_list_info->Transmit.IpHeaderChecksum )\r
+ {\r
+ p_desc->send_wr[i].wr.send_opt |= IB_SEND_OPT_TX_IP_CSUM;\r
+ }\r
+ if( p_checksum_list_info->Transmit.TcpChecksum )\r
+ {\r
+ p_desc->send_wr[i].wr.send_opt |= IB_SEND_OPT_TX_TCP_UDP_CSUM;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ else // RC QP\r
+ {\r
+ CL_ASSERT( p_desc->send_dir == SEND_RC_QP );\r
+ p_desc->send_qp = p_desc->p_endpt->conn.h_work_qp;\r
+ }\r
+ for( i = 0; i < p_desc->num_wrs; i++ )\r
+ {\r
+ p_desc->send_wr[i].wr.wr_type = WR_SEND;\r
+ p_desc->send_wr[i].wr.wr_id = 0;\r
+ p_desc->send_wr[i].wr.ds_array = &p_desc->send_wr[i].local_ds[0];\r
+ if( i )\r
+ {\r
+ p_desc->send_wr[i-1].wr.p_next = &p_desc->send_wr[i].wr;\r
+ }\r
+ }\r
+ //TODO p_net_buf or p_buf\r
+// p_desc->send_wr[p_desc->num_wrs - 1].wr.wr_id = (uintn_t)NET_BUFFER_LIST_FIRST_NB(p_desc->p_netbuf_list );\r
+//???? IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, ("WR_ID was set to NBL 0x%x \n",p_desc->p_netbuf_list ));\r
+ p_desc->send_wr[p_desc->num_wrs - 1].wr.wr_id = (uintn_t)p_desc->p_netbuf_list ;\r
+\r
+ p_desc->send_wr[p_desc->num_wrs - 1].wr.send_opt |= IB_SEND_OPT_SIGNALED;\r
+ p_desc->send_wr[p_desc->num_wrs - 1].wr.p_next = NULL;\r
+ }\r
+\r
+ /* Store context in our reserved area of the packet. */\r
+ IPOIB_PORT_FROM_PACKET( p_desc->p_netbuf_list ) = p_port;\r
+ IPOIB_ENDPT_FROM_PACKET( p_desc->p_netbuf_list ) = p_desc->p_endpt;\r
+ IPOIB_SEND_FROM_NETBUFFER( NET_BUFFER_LIST_FIRST_NB(p_desc->p_netbuf_list ))= p_desc->p_buf;\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_SEND );\r
+ return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+static NDIS_STATUS\r
+__build_lso_desc(\r
+ IN ipoib_port_t* const p_port,\r
+ IN OUT ipoib_send_desc_t* const p_desc,\r
+ IN ULONG mss,\r
+ IN SCATTER_GATHER_LIST *p_sgl,\r
+ IN int32_t hdr_idx, \r
+ IN PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO p_lso_info)\r
+{\r
+ NDIS_STATUS status;\r
+ LsoData TheLsoData;\r
+ UINT IndexOfData = 0;\r
+ \r
+ PNET_BUFFER FirstBuffer = NET_BUFFER_LIST_FIRST_NB (p_desc->p_netbuf_list);\r
+ ULONG PacketLength = NET_BUFFER_DATA_LENGTH(FirstBuffer);\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+\r
+\r
+ memset(&TheLsoData, 0, sizeof TheLsoData );\r
+ status = GetLsoHeaderSize(\r
+ FirstBuffer, \r
+ &TheLsoData, \r
+ &IndexOfData,\r
+ &p_port->hdr[hdr_idx] );\r
+\r
+ if ((status != NDIS_STATUS_SUCCESS ) || \r
+ (TheLsoData.FullBuffers != TheLsoData.UsedBuffers)) \r
+ {\r
+ ASSERT(FALSE);\r
+\r
+ IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, ("<-- Throwing this packet\n"));\r
+\r
+ if( status == NDIS_STATUS_SUCCESS )\r
+ {\r
+ status = NDIS_STATUS_INVALID_PACKET;\r
+ }\r
+ return status;\r
+ }\r
+ ASSERT(TheLsoData.LsoHeaderSize> 0);\r
+ // Tell NDIS how much we will send.\r
+ //PktExt->NdisPacketInfo[TcpLargeSendPacketInfo] = UlongToPtr(PacketLength);\r
+ p_lso_info->LsoV1TransmitComplete.TcpPayload = PacketLength;\r
+\r
+ p_desc->send_wr[0].wr.dgrm.ud.mss = mss;\r
+ p_desc->send_wr[0].wr.dgrm.ud.header = TheLsoData.LsoBuffers[0].pData;\r
+ p_desc->send_wr[0].wr.dgrm.ud.hlen = TheLsoData.LsoHeaderSize ;//lso_header_size; \r
+ p_desc->send_wr[0].wr.dgrm.ud.remote_qp = p_desc->p_endpt->qpn;\r
+ p_desc->send_wr[0].wr.dgrm.ud.remote_qkey = p_port->ib_mgr.bcast_rec.qkey;\r
+ p_desc->send_wr[0].wr.dgrm.ud.h_av = p_desc->p_endpt->h_av;\r
+ p_desc->send_wr[0].wr.dgrm.ud.pkey_index = p_port->pkey_index;\r
+ p_desc->send_wr[0].wr.dgrm.ud.rsvd = NULL;\r
+\r
+ //TODO: Should be NBL or p_desc\r
+ p_desc->send_wr[0].wr.wr_id = (uintn_t)p_desc->p_netbuf_list;\r
+ p_desc->send_wr[0].wr.ds_array = p_desc->send_wr[0].local_ds;\r
+ p_desc->send_wr[0].wr.wr_type = WR_LSO;\r
+ p_desc->send_wr[0].wr.send_opt = \r
+ (IB_SEND_OPT_TX_IP_CSUM | IB_SEND_OPT_TX_TCP_UDP_CSUM) | IB_SEND_OPT_SIGNALED;\r
+ \r
+ p_desc->send_wr[0].wr.p_next = NULL;\r
+ p_desc->send_qp = p_port->ib_mgr.h_qp;\r
+ p_desc->send_dir = SEND_UD_QP;\r
+ status = __send_gen(p_port, p_desc, p_sgl, IndexOfData );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_SEND );\r
+ return status;\r
+}\r
+\r
+static inline void\r
+__process_failed_send(\r
+ IN ipoib_port_t* const p_port,\r
+ IN ipoib_send_desc_t* const p_desc,\r
+ IN const NDIS_STATUS status,\r
+ IN ULONG compl_flags)\r
+{\r
+ IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+ /* Complete the packet. */\r
+ NET_BUFFER_LIST_NEXT_NBL(p_desc->p_netbuf_list) = NULL;\r
+ NET_BUFFER_LIST_STATUS(p_desc->p_netbuf_list) = status;\r
+ NdisMSendNetBufferListsComplete( p_port->p_adapter->h_adapter,\r
+ p_desc->p_netbuf_list, compl_flags );\r
+ ipoib_inc_send_stat( p_port->p_adapter, IP_STAT_ERROR, 0 );\r
+ /* Deref the endpoint. */\r
+ if( p_desc->p_endpt )\r
+ ipoib_endpt_deref( p_desc->p_endpt );\r
+\r
+ if( p_desc->p_buf )\r
+ {\r
+ NdisFreeToNPagedLookasideList(\r
+ &p_port->buf_mgr.send_buf_list, p_desc->p_buf );\r
+ }\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_SEND );\r
+}\r
+\r
+// max number of physical fragmented buffers \r
+#define MAX_PHYS_BUF_FRAG_ELEMENTS 0x29\r
+#define MP_FRAG_ELEMENT SCATTER_GATHER_ELEMENT \r
+#define PMP_FRAG_ELEMENT PSCATTER_GATHER_ELEMENT \r
+\r
+\r
+typedef struct _MP_FRAG_LIST {\r
+ ULONG NumberOfElements;\r
+ ULONG_PTR Reserved;\r
+ SCATTER_GATHER_ELEMENT Elements[MAX_PHYS_BUF_FRAG_ELEMENTS];\r
+} MP_FRAG_LIST, *PMP_FRAG_LIST;\r
+\r
+\r
+void \r
+CreateFragList(\r
+ ULONG PhysBufCount,\r
+ PNET_BUFFER NetBuff,\r
+ ULONG PacketLength,\r
+ PMP_FRAG_LIST pFragList\r
+ )\r
+{\r
+// ETH_ENTER(ETH_SND);\r
+\r
+ ULONG i = 0;\r
+ int j=0;\r
+\r
+ UINT buf_len = NET_BUFFER_DATA_LENGTH(NetBuff);\r
+ PMDL pMdl = NET_BUFFER_CURRENT_MDL(NetBuff);\r
+\r
+ ULONG CurrentMdlDataOffset = NET_BUFFER_CURRENT_MDL_OFFSET(NetBuff);\r
+ ASSERT(MmGetMdlByteCount(pMdl) >= CurrentMdlDataOffset);\r
+\r
+ \r
+ ASSERT(NetBuff != NULL);\r
+#ifdef DBG\r
+ ASSERT(PhysBufCount <= MAX_PHYS_BUF_FRAG_ELEMENTS);\r
+#else\r
+ UNREFERENCED_PARAMETER(PhysBufCount);\r
+#endif\r
+ \r
+ ASSERT(buf_len > 0);\r
+ UNREFERENCED_PARAMETER(PacketLength);\r
+\r
+\r
+// ETH_PRINT(TRACE_LEVEL_VERBOSE, ETH_SND, "CreateFragList: NetBuff %p, Length =0x%x\n", NetBuff, buf_len);\r
+\r
+ while ( (pMdl != NULL) && (buf_len != 0) )\r
+ {\r
+ PPFN_NUMBER page_array = MmGetMdlPfnArray(pMdl);\r
+ int MdlBufCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(pMdl), MmGetMdlByteCount(pMdl));\r
+ \r
+ ULONG offset = MmGetMdlByteOffset(pMdl) + CurrentMdlDataOffset ; \r
+ ULONG MdlBytesCount = MmGetMdlByteCount(pMdl) - CurrentMdlDataOffset;\r
+ CurrentMdlDataOffset = 0;\r
+ \r
+ if( MdlBytesCount == 0 )\r
+ {\r
+ pMdl = pMdl->Next;\r
+ continue;\r
+ }\r
+\r
+ ASSERT( (buf_len > 0) && (MdlBytesCount > 0) );\r
+ \r
+// ETH_PRINT(TRACE_LEVEL_VERBOSE, ETH_SND, "CreateFragList: pMdl=%p, MdlBytesCount=x%x, MdlBufCount=0x%x\n", pMdl, MdlBytesCount, MdlBufCount);\r
+\r
+ if (MdlBytesCount > 0)\r
+ {\r
+ if( buf_len > MdlBytesCount)\r
+ {\r
+ buf_len -= MdlBytesCount; \r
+ }\r
+ else\r
+ {\r
+ MdlBytesCount = buf_len;\r
+ buf_len = 0; \r
+ } \r
+ //\r
+ // In some cases the mdlcount is greater than needed and in the last page\r
+ // there is 0 bytes\r
+ //\r
+ for (j=0; ((j< MdlBufCount) && (MdlBytesCount > 0)); j++) \r
+ {\r
+ ASSERT(MdlBytesCount > 0);\r
+ if (j ==0 ) \r
+ {\r
+ //\r
+ // First page\r
+ //\r
+ ULONG64 ul64PageNum = page_array[j];\r
+ pFragList->Elements[i].Address.QuadPart = (ul64PageNum << PAGE_SHIFT)+ offset;\r
+ if( offset + MdlBytesCount > PAGE_SIZE )\r
+ {\r
+ //\r
+ // the data slides behind the page boundry\r
+ //\r
+ ASSERT(PAGE_SIZE > offset);\r
+ pFragList->Elements[i].Length = PAGE_SIZE - offset;\r
+ MdlBytesCount -= pFragList->Elements[i].Length;\r
+ }\r
+ else\r
+ {\r
+ //\r
+ // All the data is hold in one page\r
+ // \r
+ pFragList->Elements[i].Length = MdlBytesCount;\r
+ MdlBytesCount = 0;\r
+ }\r
+\r
+// 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); \r
+ } \r
+ else \r
+ {\r
+ if (page_array[j] == (page_array[j-1] + 1))\r
+ {\r
+ \r
+ ULONG size = min(PAGE_SIZE, MdlBytesCount);\r
+ i -= 1;\r
+ pFragList->Elements[i].Length += size;\r
+ MdlBytesCount -= size;\r
+ }\r
+ else \r
+ {\r
+ //\r
+ // Not first page. so the data always start at the begining of the page\r
+ //\r
+ ULONG64 ul64PageNum = page_array[j];\r
+ pFragList->Elements[i].Address.QuadPart = (ul64PageNum << PAGE_SHIFT);\r
+ pFragList->Elements[i].Length = min(PAGE_SIZE, MdlBytesCount);\r
+ MdlBytesCount -= pFragList->Elements[i].Length;\r
+ }\r
+\r
+// 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); \r
+ } \r
+ i++;\r
+ ASSERT(i <= MAX_PHYS_BUF_FRAG_ELEMENTS);\r
+ }\r
+ }\r
+\r
+ pMdl = pMdl->Next;\r
+ }\r
+ \r
+ if (buf_len != 0)\r
+ {\r
+ //\r
+ // In some cases the size in MDL isn't equal to the buffer size. In such \r
+ // a case we need to add the rest of packet to last chunk\r
+ //\r
+ ASSERT(i > 0); // To prevent array underflow\r
+ pFragList->Elements[i-1].Length += buf_len;\r
+// 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); \r
+ }\r
+\r
+ ASSERT(i <= PhysBufCount);\r
+ pFragList->NumberOfElements = i;\r
+\r
+#ifdef DBG\r
+{\r
+ ULONG size = 0;\r
+ for (i = 0; i < pFragList->NumberOfElements; ++i)\r
+ {\r
+ size += pFragList->Elements[i].Length;\r
+ }\r
+ ASSERT(size == PacketLength);\r
+}\r
+#endif\r
+\r
+// ETH_EXIT(ETH_SND);\r
+}\r
+\r
+\r
+\r
+\r
+void\r
+ipoib_port_send(\r
+ IN ipoib_port_t* const p_port,\r
+ IN NET_BUFFER_LIST *p_net_buffer_list,\r
+ IN ULONG send_flags)\r
+{\r
+ NDIS_STATUS status;\r
+ PNET_BUFFER p_netbuf;\r
+ UINT buf_cnt = 0;\r
+ //ipoib_send_desc_t *p_desc;\r
+ ULONG send_complete_flags = 0;\r
+ KIRQL old_irql;\r
+ PVOID p_sgl;\r
+ \r
+ PERF_DECLARE( GetEthHdr );\r
+ PERF_DECLARE( BuildSendDesc );\r
+ PERF_DECLARE( QueuePacket );\r
+ PERF_DECLARE( SendMgrQueue );\r
+ PERF_DECLARE( PostSend );\r
+ PERF_DECLARE( ProcessFailedSends );\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_SEND );\r
+ \r
+ if (NDIS_TEST_SEND_AT_DISPATCH_LEVEL(send_flags))\r
+ {\r
+ //TODO Tzachid: make an assert here to validate your IRQL\r
+ //ASSERT (KeGetCurrentIRQL() == DISPATCH_LEVEL);\r
+ NDIS_SET_SEND_COMPLETE_FLAG(send_complete_flags, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL);\r
+ } else {\r
+ //ASSERT (KeGetCurrentIRQL() == PASSIVE_LEVEL);\r
+ }\r
+ \r
+ cl_obj_lock( &p_port->obj );\r
+ if( p_port->state != IB_QPS_RTS )\r
+ {\r
+ \r
+ \r
+ cl_obj_unlock( &p_port->obj );\r
+ \r
+ \r
+ NET_BUFFER_LIST_STATUS(p_net_buffer_list) = NDIS_STATUS_FAILURE;\r
+ NET_BUFFER_LIST_NEXT_NBL(p_net_buffer_list) = NULL;\r
+ ipoib_inc_send_stat( p_port->p_adapter, IP_STAT_DROPPED, 0 );\r
+ \r
+ NdisMSendNetBufferListsComplete(\r
+ p_port->p_adapter->h_adapter,\r
+ p_net_buffer_list,\r
+ send_complete_flags); \r
+ \r
+ return;\r
+ }\r
+ cl_obj_unlock( &p_port->obj );\r
+ \r
+ //IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ // ("Processing netbuffer list: %x\n", p_net_buffer_list));\r
+ for (p_netbuf = NET_BUFFER_LIST_FIRST_NB(p_net_buffer_list);\r
+ p_netbuf != NULL; \r
+ p_netbuf = NET_BUFFER_NEXT_NB(p_netbuf))\r
+ {\r
+ IPOIB_PORT_FROM_PACKET(p_net_buffer_list) = p_port;\r
+ IPOIB_NET_BUFFER_LIST_FROM_NETBUFFER(p_netbuf) = p_net_buffer_list;\r
+ IPOIB_FROM_QUEUE(p_netbuf) = NULL;\r
+ /*p_desc = &p_port->send_mgr.desc;\r
+ p_desc->p_buf = p_netbuf;\r
+ p_desc->p_endpt = NULL;\r
+ p_desc->p_buf = NULL;\r
+ p_desc->send_qp = NULL;\r
+ p_desc->num_wrs = 1;\r
+ p_desc->send_dir = 0;*/\r
+ \r
+ old_irql = KeGetCurrentIrql();\r
+ if (old_irql < DISPATCH_LEVEL) \r
+ {\r
+ KeRaiseIrqlToDpcLevel();\r
+ }\r
+ ++buf_cnt;\r
+ //IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ // ("[%d] Netbuf = %x\n",buf_cnt, p_netbuf) );\r
+ if (cl_is_item_in_qlist( &p_port->send_mgr.pending_list,\r
+ IPOIB_LIST_ITEM_FROM_PACKET( p_net_buffer_list ))) {\r
+ p_sgl = IPOIB_FROM_QUEUE(p_netbuf); \r
+ //IPOIB_FROM_QUEUE(p_net_buffer) = (void*)1;\r
+ ASSERT (p_sgl); \r
+ //IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ // ("[%d] FROM_QUEUE Netbuf = %x, found SGL = %x\n",buf_cnt, p_netbuf, p_sgl) );\r
+ status = NDIS_STATUS_SUCCESS;\r
+ } else {\r
+\r
+//#if 0\r
+ CHAR *pTemp = (CHAR *) ExAllocatePoolWithTag(NonPagedPool , p_port->p_adapter->sg_list_size, 'abcd');\r
+ CL_ASSERT(pTemp != NULL);\r
+ status = NDIS_STATUS_SUCCESS;\r
+ p_sgl = pTemp;\r
+ CreateFragList(NdisQueryNetBufferPhysicalCount(p_netbuf), p_netbuf, NET_BUFFER_DATA_LENGTH(p_netbuf), (PMP_FRAG_LIST) p_sgl);\r
+ IPOIB_FROM_QUEUE(p_netbuf) = NULL;\r
+ /*IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("[%d] Allocation from scratch: Netbuf = %x, found SGL = %x, PhysBufCnt=%ld, NB LEN = %ld, sg_list_size=%ld\n",\r
+ buf_cnt, p_netbuf, p_sgl,NdisQueryNetBufferPhysicalCount(p_netbuf) ,\r
+ NET_BUFFER_DATA_LENGTH(p_netbuf),p_port->p_adapter->sg_list_size) );\r
+ */\r
+ ipoib_process_sg_list(NULL, NULL, (PSCATTER_GATHER_LIST)p_sgl, p_netbuf);\r
+ status = NDIS_STATUS_SUCCESS;\r
+//#endif\r
+#if 0 \r
+ status = NdisMAllocateNetBufferSGList(\r
+ p_port->p_adapter->NdisMiniportDmaHandle,\r
+ p_netbuf,\r
+ p_netbuf,\r
+ NDIS_SG_LIST_WRITE_TO_DEVICE,\r
+ NULL,\r
+ 0);\r
+#endif\r
+ }\r
+ KeLowerIrql (old_irql);\r
+ \r
+ if( status != NDIS_STATUS_SUCCESS )\r
+ {\r
+ /* fail net buffer list */\r
+ NET_BUFFER_LIST_NEXT_NBL(p_net_buffer_list) = NULL;\r
+ NET_BUFFER_LIST_STATUS(p_net_buffer_list) = NDIS_STATUS_RESOURCES;\r
+ NdisMSendNetBufferListsComplete(\r
+ p_port->p_adapter->h_adapter,\r
+ p_net_buffer_list,\r
+ send_complete_flags); \r
+ break;\r
+ }\r
+ ASSERT(buf_cnt);\r
+ IPOIB_GET_NET_BUFFER_LIST_REF_COUNT(p_net_buffer_list) = (PVOID)(ULONG_PTR)buf_cnt;\r
+ }\r
+ \r
+}\r
+\r
+\r
+void\r
+ipoib_port_resume(\r
+ IN ipoib_port_t* const p_port,\r
+ IN boolean_t b_pending )\r
+{\r
+ NDIS_STATUS status;\r
+ cl_list_item_t *p_item;\r
+ NET_BUFFER *p_net_buffer;\r
+ NET_BUFFER_LIST *p_net_buffer_list;\r
+ //ipoib_send_desc_t *p_desc;\r
+ KIRQL old_irql;\r
+ UINT buf_cnt = 0;\r
+ NET_BUFFER_LIST *p_prev_nbl = NULL;\r
+ PVOID p_sgl;\r
+ static PVOID p_prev_sgl = NULL;\r
+ \r
+ PERF_DECLARE( GetEndpt );\r
+ PERF_DECLARE( BuildSendDesc );\r
+ PERF_DECLARE( ProcessFailedSends );\r
+ PERF_DECLARE( PostSend );\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+ UNUSED_PARAM(b_pending);\r
+ \r
+ cl_obj_lock( &p_port->obj );\r
+ if( p_port->state != IB_QPS_RTS )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_WARNING, IPOIB_DBG_SEND,\r
+ ("Invalid state - Aborting.\n") );\r
+ cl_obj_unlock( &p_port->obj );\r
+ return;\r
+ }\r
+ cl_obj_unlock( &p_port->obj );\r
+\r
+//TODO NDIS60\r
+////?????????????? cl_spinlock_acquire( &p_port->send_lock );\r
+\r
+ for( p_item = cl_qlist_head( &p_port->send_mgr.pending_list );\r
+ p_item != cl_qlist_end( &p_port->send_mgr.pending_list );\r
+ p_item = cl_qlist_head( &p_port->send_mgr.pending_list ) )\r
+ {\r
+ \r
+ \r
+ /* Check the send queue and pend the request if not empty. */\r
+ if( p_port->send_mgr.depth == p_port->p_adapter->params.sq_depth )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_SEND,\r
+ ("No available WQEs.\n") );\r
+ break;\r
+ }\r
+ \r
+ p_net_buffer_list = IPOIB_PACKET_FROM_LIST_ITEM(\r
+ cl_qlist_remove_head( &p_port->send_mgr.pending_list ) );\r
+ if (p_prev_nbl == p_net_buffer_list) {\r
+// IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ // ("TRYING TO PROCESS ONCE AGAIN, EXITING: %x\n", p_net_buffer_list));\r
+ break; //TODO more sophisticated mechanism to avoid starvation\r
+ }\r
+ old_irql = KeGetCurrentIrql();\r
+ if (old_irql < DISPATCH_LEVEL) \r
+ {\r
+ KeRaiseIrqlToDpcLevel();\r
+ }\r
+// IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ // ("Processing netbuffer list from queue: %x\n", (UINT) (PVOID) p_net_buffer_list));\r
+ \r
+ for( p_net_buffer = NET_BUFFER_LIST_FIRST_NB(p_net_buffer_list);\r
+ p_net_buffer != NULL;\r
+ p_net_buffer = NET_BUFFER_NEXT_NB(p_net_buffer), buf_cnt++)\r
+ {\r
+\r
+ \r
+ p_sgl = IPOIB_FROM_QUEUE(p_net_buffer); \r
+ //IPOIB_FROM_QUEUE(p_net_buffer) = (void*)1;\r
+ ASSERT (p_sgl);\r
+ IPOIB_PORT_FROM_PACKET(p_net_buffer_list) = p_port;\r
+ IPOIB_NET_BUFFER_LIST_FROM_NETBUFFER(p_net_buffer) = p_net_buffer_list;\r
+ /*p_desc = &p_port->send_mgr.desc;\r
+ p_desc->p_buf = p_net_buffer;\r
+ p_desc->p_endpt = NULL;\r
+ p_desc->p_buf = NULL;\r
+ p_desc->send_qp = NULL;\r
+ p_desc->num_wrs = 1;\r
+ p_desc->send_dir = 0;*/\r
+\r
+// IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ // ("[%d] Netbuf = %x, p_sgl = %x\n",buf_cnt, p_net_buffer, p_sgl) );\r
+ ASSERT(p_sgl);\r
+ if (p_sgl != (void*) 1) {\r
+ ipoib_process_sg_list(NULL, NULL, (PSCATTER_GATHER_LIST) p_sgl, p_net_buffer);\r
+ status = NDIS_STATUS_SUCCESS;\r
+ }\r
+ else {\r
+ ASSERT(FALSE);\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Getting strange flow\n") );\r
+ NdisMFreeNetBufferSGList(\r
+ p_port->p_adapter->NdisMiniportDmaHandle,\r
+ (PSCATTER_GATHER_LIST)p_sgl,\r
+ p_net_buffer );\r
+ status = NdisMAllocateNetBufferSGList(\r
+ p_port->p_adapter->NdisMiniportDmaHandle,\r
+ p_net_buffer,\r
+ p_net_buffer,\r
+ NDIS_SG_LIST_WRITE_TO_DEVICE,\r
+ NULL,\r
+ 0 /*p_port->p_adapter->sg_list_size*/ );\r
+ }\r
+ p_prev_sgl = p_sgl; \r
+ if( status != NDIS_STATUS_SUCCESS )\r
+ {\r
+ /* fail net buffer list */\r
+ NET_BUFFER_LIST_NEXT_NBL(p_net_buffer_list) = NULL;\r
+ NET_BUFFER_LIST_STATUS(p_net_buffer_list) = NDIS_STATUS_RESOURCES;\r
+ NdisMSendNetBufferListsComplete(\r
+ p_port->p_adapter->h_adapter,\r
+ p_net_buffer_list,\r
+ 0); \r
+ break;\r
+ }\r
+ }\r
+ \r
+ KeLowerIrql (old_irql);\r
+ \r
+ \r
+ p_prev_nbl = p_net_buffer_list;\r
+ \r
+ }\r
+ IPOIB_EXIT( IPOIB_DBG_SEND );\r
+}\r
+\r
+\r
+\r
+static void\r
+__send_cb(\r
+ IN const ib_cq_handle_t h_cq,\r
+ IN void *cq_context )\r
+{\r
+ ipoib_port_t *p_port;\r
+ ib_api_status_t status;\r
+ ib_wc_t wc[MAX_SEND_WC], *p_wc, *p_free;\r
+ cl_qlist_t done_list;\r
+ NET_BUFFER_LIST *p_nbl;\r
+ uint32_t length;\r
+ ipoib_endpt_t *p_endpt;\r
+ send_buf_t *p_send_buf;\r
+ ip_stat_sel_t type;\r
+ size_t i;\r
+ NET_BUFFER *p_netbuffer = NULL;\r
+\r
+ PERF_DECLARE( SendCompBundle );\r
+ PERF_DECLARE( SendCb );\r
+ PERF_DECLARE( PollSend );\r
+ PERF_DECLARE( SendComp );\r
+ PERF_DECLARE( FreeSendBuf );\r
+ PERF_DECLARE( RearmSend );\r
+ PERF_DECLARE( PortResume );\r
+ \r
+ IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+ cl_perf_clr( SendCompBundle );\r
+\r
+ cl_perf_start( SendCb );\r
+\r
+ UNUSED_PARAM( h_cq );\r
+\r
+ cl_qlist_init( &done_list );\r
+\r
+ p_port = (ipoib_port_t*)cq_context;\r
+\r
+ ipoib_port_ref( p_port, ref_send_cb );\r
+\r
+ for( i = 0; i < MAX_SEND_WC; i++ )\r
+ wc[i].p_next = &wc[i + 1];\r
+ wc[MAX_SEND_WC - 1].p_next = NULL;\r
+\r
+ do\r
+ {\r
+ p_free = wc;\r
+ cl_perf_start( PollSend );\r
+ status = p_port->p_adapter->p_ifc->poll_cq( p_port->ib_mgr.h_send_cq, &p_free, &p_wc );\r
+ cl_perf_stop( &p_port->p_adapter->perf, PollSend );\r
+ CL_ASSERT( status == IB_SUCCESS || status == IB_NOT_FOUND );\r
+\r
+ while( p_wc )\r
+ {\r
+ cl_perf_start( SendComp );\r
+ CL_ASSERT( p_wc->status != IB_WCS_SUCCESS || p_wc->wc_type == IB_WC_SEND );\r
+ p_nbl = (NET_BUFFER_LIST*)(uintn_t)p_wc->wr_id;\r
+ //IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_SEND,\r
+ //("[1]Successfull send completion for NBL=0x%x .\n", (UINT) (PVOID) p_nbl ));\r
+ CL_ASSERT( p_nbl );\r
+ CL_ASSERT( IPOIB_PORT_FROM_PACKET( p_nbl ) == p_port );\r
+ length = 0;\r
+ p_endpt = IPOIB_ENDPT_FROM_PACKET( p_nbl );\r
+ p_send_buf = IPOIB_SEND_FROM_NETBUFFER( NET_BUFFER_LIST_FIRST_NB (p_nbl ));\r
+ \r
+ switch( p_wc->status )\r
+ {\r
+ case IB_WCS_SUCCESS:\r
+ if( p_endpt->h_mcast )\r
+ {\r
+ if( p_endpt->dgid.multicast.raw_group_id[11] == 0xFF &&\r
+ p_endpt->dgid.multicast.raw_group_id[10] == 0xFF &&\r
+ p_endpt->dgid.multicast.raw_group_id[12] == 0xFF &&\r
+ p_endpt->dgid.multicast.raw_group_id[13] == 0xFF )\r
+ {\r
+ type = IP_STAT_BCAST_BYTES;\r
+ }\r
+ else\r
+ {\r
+ type = IP_STAT_MCAST_BYTES;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ type = IP_STAT_UCAST_BYTES;\r
+ }\r
+ for (p_netbuffer = NET_BUFFER_LIST_FIRST_NB(p_nbl);\r
+ p_netbuffer != NULL;\r
+ p_netbuffer = NET_BUFFER_NEXT_NB(p_netbuffer))\r
+ {\r
+ length += NET_BUFFER_DATA_LENGTH(p_netbuffer);\r
+ } \r
+ ipoib_inc_send_stat( p_port->p_adapter, type, length );\r
+ // IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_SEND,\r
+ //("Successfull send completion for NBL=0x%x .\n", (UINT) (PVOID) p_nbl) );\r
+ NET_BUFFER_LIST_STATUS(p_nbl) = NDIS_STATUS_SUCCESS;\r
+ IPOIB_DEC_NET_BUFFER_LIST_REF_COUNT(p_nbl);\r
+ if (IPOIB_GET_NET_BUFFER_LIST_REF_COUNT(p_nbl) == 0)\r
+ NdisMSendNetBufferListsComplete(p_port->p_adapter->h_adapter,\r
+ p_nbl,\r
+ 0);\r
+ break;\r
+\r
+ case IB_WCS_WR_FLUSHED_ERR:\r
+ IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_SEND,\r
+ ("Flushed send completion.\n") );\r
+ ipoib_inc_send_stat( p_port->p_adapter, IP_STAT_DROPPED, 0 );\r
+ NET_BUFFER_LIST_STATUS(p_nbl) = NDIS_STATUS_RESET_IN_PROGRESS;\r
+ NdisMSendNetBufferListsComplete(p_port->p_adapter->h_adapter,\r
+ p_nbl,\r
+ 0); \r
+ break;\r
+\r
+ default:\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Send failed with %s (vendor specific %#x)\n",\r
+ p_port->p_adapter->p_ifc->get_wc_status_str( p_wc->status ),\r
+ (int)p_wc->vendor_specific) );\r
+ ipoib_inc_send_stat( p_port->p_adapter, IP_STAT_ERROR, 0 );\r
+ NET_BUFFER_LIST_STATUS(p_nbl) = NDIS_STATUS_FAILURE;\r
+ NdisMSendNetBufferListsComplete(p_port->p_adapter->h_adapter,\r
+ p_nbl,\r
+ 0); \r
+ break;\r
+ }\r
+ cl_perf_stop( &p_port->p_adapter->perf, SendComp );\r
+ /* Dereference the enpoint used for the transfer. */\r
+ ipoib_endpt_deref( p_endpt );\r
+\r
+ if( p_send_buf )\r
+ {\r
+ cl_perf_start( FreeSendBuf );\r
+ NdisFreeToNPagedLookasideList( &p_port->buf_mgr.send_buf_list,\r
+ p_send_buf );\r
+ cl_perf_stop( &p_port->p_adapter->perf, FreeSendBuf );\r
+ }\r
+\r
+ cl_atomic_dec( &p_port->send_mgr.depth );\r
+\r
+ p_wc = p_wc->p_next;\r
+ cl_perf_inc( SendCompBundle );\r
+ }\r
+ /* If we didn't use up every WC, break out. */\r
+ } while( !p_free );\r
+\r
+ /* Rearm the CQ. */\r
+ cl_perf_start( RearmSend );\r
+ status = p_port->p_adapter->p_ifc->rearm_cq( p_port->ib_mgr.h_send_cq, FALSE );\r
+ cl_perf_stop( &p_port->p_adapter->perf, RearmSend );\r
+ CL_ASSERT( status == IB_SUCCESS );\r
+\r
+ /* Resume any sends awaiting resources. */\r
+ cl_perf_start( PortResume );\r
+ ipoib_port_resume( p_port, TRUE );\r
+ cl_perf_stop( &p_port->p_adapter->perf, PortResume );\r
+ \r
+ ipoib_port_deref( p_port, ref_send_cb );\r
+\r
+ cl_perf_stop( &p_port->p_adapter->perf, SendCb );\r
+ cl_perf_update_ctr( &p_port->p_adapter->perf, SendCompBundle );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_SEND );\r
+}\r
+\r
+\r
+/******************************************************************************\r
+*\r
+* Endpoint manager implementation\r
+*\r
+******************************************************************************/\r
+static void\r
+__endpt_mgr_construct(\r
+ IN ipoib_port_t* const p_port )\r
+{\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+ cl_qmap_init( &p_port->endpt_mgr.mac_endpts );\r
+ cl_qmap_init( &p_port->endpt_mgr.lid_endpts );\r
+ cl_fmap_init( &p_port->endpt_mgr.gid_endpts, __gid_cmp );\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+//TODO Restore CM\r
+#if 0\r
+static void\r
+__endpt_cm_mgr_thread(\r
+IN void* p_context );\r
+#endif\r
+\r
+static ib_api_status_t\r
+__endpt_mgr_init(\r
+ IN ipoib_port_t* const p_port )\r
+{\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+#if 0\r
+ if( p_port->p_adapter->params.cm_enabled )\r
+ {\r
+ cl_fmap_init( &p_port->endpt_mgr.conn_endpts, __gid_cmp );\r
+ \r
+ NdisInitializeListHead( &p_port->endpt_mgr.pending_conns );\r
+ NdisAllocateSpinLock( &p_port->endpt_mgr.conn_lock );\r
+ cl_event_init( &p_port->endpt_mgr.event, FALSE );\r
+ \r
+ NdisInitializeListHead( &p_port->endpt_mgr.remove_conns );\r
+ NdisAllocateSpinLock( &p_port->endpt_mgr.remove_lock );\r
+\r
+ cl_thread_init( &p_port->endpt_mgr.h_thread, \r
+ __endpt_cm_mgr_thread,\r
+ ( const void *)p_port, \r
+ "CmEndPtMgr" );\r
+ }\r
+#endif\r
+ UNUSED_PARAM(p_port);\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+ return IB_SUCCESS;\r
+}\r
+\r
+//TODO CM Restore\r
+#if 0\r
+static void\r
+__endpt_cm_mgr_thread(\r
+IN void* p_context )\r
+{\r
+ ib_api_status_t ib_status;\r
+ LIST_ENTRY *p_item;\r
+ ipoib_endpt_t *p_endpt;\r
+ ipoib_port_t *p_port =( ipoib_port_t *)p_context;\r
+ \r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, \r
+ ("Starting Port [%d] Endpt CM thread \n", p_port->port_num ) );\r
+\r
+ while( !p_port->endpt_mgr.thread_is_done )\r
+ {\r
+ cl_event_wait_on( &p_port->endpt_mgr.event, EVENT_NO_TIMEOUT, FALSE );\r
+ \r
+ while( ( p_item = NdisInterlockedRemoveHeadList( \r
+ &p_port->endpt_mgr.pending_conns,\r
+ &p_port->endpt_mgr.conn_lock) ) != NULL )\r
+ {\r
+\r
+ p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, list_item );\r
+ if( p_port->endpt_mgr.thread_is_done )\r
+ {\r
+ endpt_cm_set_state( p_endpt, IPOIB_CM_DISCONNECTED );\r
+ continue;\r
+ }\r
+\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+ ("Endpt[%p] CONNECT REQ to MAC %02x:%02x:%02x:%02x:%02x:%02x\n",\r
+ p_endpt,\r
+ p_endpt->mac.addr[0], p_endpt->mac.addr[1],\r
+ p_endpt->mac.addr[2], p_endpt->mac.addr[3],\r
+ p_endpt->mac.addr[4], p_endpt->mac.addr[5] ) );\r
+ \r
+ if( !p_endpt->conn.h_send_qp )\r
+ {\r
+ ib_status = endpt_cm_create_qp( p_endpt, &p_endpt->conn.h_send_qp );\r
+ if( ib_status != IB_SUCCESS )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Endpt [%p ] CM create QP failed status %#x\n", p_endpt, ib_status ) );\r
+ }\r
+ else\r
+ {\r
+ ib_status = ipoib_endpt_connect( p_endpt );\r
+ if( ib_status != IB_SUCCESS && ib_status != IB_PENDING )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Endpt [ %p ] conn REQ failed status %#x\n", p_endpt, ib_status ) );\r
+ }\r
+ }\r
+ if( ib_status != IB_SUCCESS && ib_status != IB_PENDING )\r
+ {\r
+ endpt_cm_set_state( p_endpt, IPOIB_CM_DESTROY );\r
+ endpt_cm_flush_recv( p_port, p_endpt );\r
+ endpt_cm_set_state( p_endpt, IPOIB_CM_DISCONNECTED );\r
+ }\r
+ }\r
+\r
+ }//while( p_item != NULL )\r
+\r
+ while( ( p_item = NdisInterlockedRemoveHeadList(\r
+ &p_port->endpt_mgr.remove_conns,\r
+ &p_port->endpt_mgr.remove_lock ) ) != NULL )\r
+ {\r
+ p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, list_item );\r
+\r
+ endpt_cm_set_state( p_endpt, IPOIB_CM_DESTROY );\r
+\r
+ IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_INIT,\r
+ ("\nDESTROYING Endpt[%p] MAC %02x:%02x:%02x:%02x:%02x:%02x\n",\r
+ p_endpt,\r
+ p_endpt->mac.addr[0], p_endpt->mac.addr[1],\r
+ p_endpt->mac.addr[2], p_endpt->mac.addr[3],\r
+ p_endpt->mac.addr[4], p_endpt->mac.addr[5] ) );\r
+ endpt_cm_flush_recv( p_port, p_endpt );\r
+ endpt_cm_set_state( p_endpt, IPOIB_CM_DISCONNECTED );\r
+ cl_obj_destroy( &p_endpt->obj );\r
+ }\r
+ }\r
+\r
+ p_port->endpt_mgr.thread_is_done++;\r
+ NdisFreeSpinLock( &p_port->endpt_mgr.conn_lock );\r
+ \r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, \r
+ (" Port [%d] Endpt thread is done\n", p_port->port_num ) );\r
+}\r
+#endif\r
+\r
+static void\r
+__endpt_mgr_destroy(\r
+ IN ipoib_port_t* const p_port )\r
+{\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+ CL_ASSERT( cl_is_qmap_empty( &p_port->endpt_mgr.mac_endpts ) );\r
+ CL_ASSERT( cl_is_qmap_empty( &p_port->endpt_mgr.lid_endpts ) );\r
+ CL_ASSERT( cl_is_fmap_empty( &p_port->endpt_mgr.gid_endpts ) );\r
+ UNUSED_PARAM(p_port);\r
+#if 0\r
+ if( p_port->p_adapter->params.cm_enabled )\r
+ {\r
+ CL_ASSERT( cl_is_fmap_empty( &p_port->endpt_mgr.conn_endpts ) );\r
+ }\r
+#endif\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static void\r
+__endpt_mgr_remove_all(\r
+ IN ipoib_port_t* const p_port )\r
+{\r
+ IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+ \r
+ cl_obj_lock( &p_port->obj );\r
+ /* Wait for all readers to complete. */\r
+ while( p_port->endpt_rdr )\r
+ ;\r
+ /*\r
+ * We don't need to initiate destruction - this is called only\r
+ * from the __port_destroying function, and destruction cascades\r
+ * to all child objects. Just clear all the maps.\r
+ */\r
+ cl_qmap_remove_all( &p_port->endpt_mgr.mac_endpts );\r
+ cl_qmap_remove_all( &p_port->endpt_mgr.lid_endpts );\r
+ cl_fmap_remove_all( &p_port->endpt_mgr.gid_endpts );\r
+ cl_obj_unlock( &p_port->obj );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+}\r
+\r
+\r
+static void\r
+__endpt_mgr_reset_all(\r
+ IN ipoib_port_t* const p_port )\r
+{\r
+ cl_map_item_t *p_item;\r
+ cl_fmap_item_t *p_fmap_item;\r
+ ipoib_endpt_t *p_endpt;\r
+ cl_qlist_t mc_list;\r
+ cl_qlist_t conn_list;\r
+ uint32_t local_exist = 0;\r
+ NDIS_LINK_STATE link_state;\r
+ NDIS_STATUS_INDICATION status_indication;\r
+\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+ cl_qlist_init( &mc_list );\r
+ cl_qlist_init( &conn_list );\r
+//??? cl_obj_lock( &p_port->obj );\r
+ /* Wait for all readers to complete. */\r
+ while( p_port->endpt_rdr )\r
+ ;\r
+\r
+#if 0\r
+ __endpt_mgr_remove_all(p_port);\r
+#else\r
+ link_state.Header.Revision = NDIS_LINK_STATE_REVISION_1;\r
+ link_state.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;\r
+ link_state.Header.Size = sizeof(NDIS_LINK_STATE);\r
+ link_state.MediaConnectState = MediaConnectStateDisconnected;\r
+ link_state.MediaDuplexState = MediaDuplexStateFull;\r
+ link_state.XmitLinkSpeed = link_state.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED;\r
+\r
+ IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication,\r
+ p_port->p_adapter->h_adapter,\r
+ NDIS_STATUS_LINK_STATE,\r
+ (PVOID)&link_state,\r
+ sizeof(link_state));\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, ("Indicate DISCONNECT!\n") );\r
+ NdisMIndicateStatusEx(p_port->p_adapter->h_adapter,&status_indication);\r
+ \r
+ link_state.MediaConnectState = MediaConnectStateConnected;\r
+ IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication,\r
+ p_port->p_adapter->h_adapter,\r
+ NDIS_STATUS_LINK_STATE,\r
+ (PVOID)&link_state,\r
+ sizeof(link_state));\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, ("Indicate Connect\n") );\r
+ NdisMIndicateStatusEx(p_port->p_adapter->h_adapter,&status_indication);\r
+\r
+ \r
+ // IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+ // ("Link DOWN!\n") );\r
+\r
+ if( p_port->p_local_endpt )\r
+ {\r
+ //TODO: CM RESTORE\r
+ //ipoib_port_cancel_listen( p_port, p_port->p_local_endpt );\r
+\r
+ cl_fmap_remove_item( &p_port->endpt_mgr.gid_endpts,\r
+ &p_port->p_local_endpt->gid_item );\r
+ cl_qmap_remove_item( &p_port->endpt_mgr.mac_endpts,\r
+ &p_port->p_local_endpt->mac_item );\r
+ cl_qmap_remove_item( &p_port->endpt_mgr.lid_endpts,\r
+ &p_port->p_local_endpt->lid_item );\r
+ \r
+ cl_qlist_insert_head(\r
+ &mc_list, &p_port->p_local_endpt->mac_item.pool_item.list_item );\r
+ local_exist = 1;\r
+\r
+ p_port->p_local_endpt = NULL;\r
+ }\r
+\r
+ p_item = cl_qmap_head( &p_port->endpt_mgr.mac_endpts );\r
+ while( p_item != cl_qmap_end( &p_port->endpt_mgr.mac_endpts ) )\r
+ {\r
+ p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item );\r
+ p_item = cl_qmap_next( p_item );\r
+ if( p_endpt->h_mcast )\r
+ {\r
+ /*\r
+ * We destroy MC endpoints since they will get recreated\r
+ * when the port comes back up and we rejoin the MC groups.\r
+ */\r
+ cl_qmap_remove_item( &p_port->endpt_mgr.mac_endpts,\r
+ &p_endpt->mac_item );\r
+ cl_fmap_remove_item( &p_port->endpt_mgr.gid_endpts,\r
+ &p_endpt->gid_item );\r
+\r
+ cl_qlist_insert_tail(\r
+ &mc_list, &p_endpt->mac_item.pool_item.list_item );\r
+ }\r
+ /* destroy connected endpoints if any */\r
+ else if( p_port->p_adapter->params.cm_enabled &&\r
+ endpt_cm_get_state( p_endpt ) != IPOIB_CM_DISCONNECTED )\r
+ {\r
+ p_fmap_item = cl_fmap_get( &p_port->endpt_mgr.conn_endpts, &p_endpt->dgid );\r
+ if( p_fmap_item != cl_fmap_end( &p_port->endpt_mgr.conn_endpts ) )\r
+ {\r
+ cl_fmap_remove_item( &p_port->endpt_mgr.conn_endpts, \r
+ &p_endpt->conn_item );\r
+ }\r
+ cl_qmap_remove_item( &p_port->endpt_mgr.mac_endpts,\r
+ &p_endpt->mac_item );\r
+ cl_fmap_remove_item( &p_port->endpt_mgr.gid_endpts,\r
+ &p_endpt->gid_item );\r
+\r
+ cl_qlist_insert_tail(\r
+ &conn_list, &p_endpt->mac_item.pool_item.list_item );\r
+ }\r
+ if( p_endpt->h_av )\r
+ {\r
+ /* Destroy the AV for all other endpoints. */\r
+ p_port->p_adapter->p_ifc->destroy_av( p_endpt->h_av );\r
+ p_endpt->h_av = NULL;\r
+ }\r
+ \r
+ if( p_endpt->dlid )\r
+ {\r
+ cl_qmap_remove_item( &p_port->endpt_mgr.lid_endpts,\r
+ &p_endpt->lid_item );\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
+ ("<__endptr_mgr_reset_all: setting p_endpt->dlid to 0\n"));\r
+ p_endpt->dlid = 0;\r
+ }\r
+ \r
+ }\r
+#endif\r
+//??? cl_obj_unlock( &p_port->obj );\r
+\r
+ //TODO CM\r
+ /*while( cl_qlist_count( &conn_list ) )\r
+ {\r
+ endpt_cm_destroy_conn( p_port,\r
+ PARENT_STRUCT( cl_qlist_remove_head( &conn_list ),\r
+ ipoib_endpt_t, mac_item.pool_item.list_item ) );\r
+ }*/\r
+\r
+ if(cl_qlist_count( &mc_list ) - local_exist)\r
+ {\r
+ p_port->mcast_cnt = (uint32_t)cl_qlist_count( &mc_list ) - local_exist;\r
+ }\r
+ else\r
+ {\r
+ p_port->mcast_cnt = 0;\r
+ KeSetEvent( &p_port->leave_mcast_event, EVENT_INCREMENT, FALSE );\r
+ } \r
+\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,("p_port->mcast_cnt = %d\n", p_port->mcast_cnt - local_exist));\r
+\r
+ /* Destroy all multicast endpoints now that we have released the lock. */\r
+ while( cl_qlist_count( &mc_list ) )\r
+ {\r
+ cl_list_item_t *p_item;\r
+ p_item = cl_qlist_remove_head( &mc_list );\r
+ p_endpt = PARENT_STRUCT(p_item, ipoib_endpt_t, mac_item.pool_item.list_item);\r
+ cl_obj_destroy( &p_endpt->obj);\r
+ }\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+}\r
+\r
+\r
+/*\r
+ * Called when updating an endpoint entry in response to an ARP.\r
+ * Because receive processing is serialized, and holds a reference\r
+ * on the endpoint reader, we wait for all *other* readers to exit before\r
+ * removing the item.\r
+ */\r
+static void\r
+__endpt_mgr_remove(\r
+ IN ipoib_port_t* const p_port,\r
+ IN ipoib_endpt_t* const p_endpt )\r
+{\r
+#if 0 //CM\r
+ cl_fmap_item_t* p_fmap_item;\r
+#endif \r
+ IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+ /* This function must be called from the receive path */\r
+ CL_ASSERT(p_port->endpt_rdr > 0);\r
+\r
+ cl_obj_lock( &p_port->obj );\r
+ /* Wait for all readers to complete. */ \r
+ while( p_port->endpt_rdr > 1 )\r
+ ;\r
+\r
+ /* Remove the endpoint from the maps so further requests don't find it. */\r
+ cl_qmap_remove_item( &p_port->endpt_mgr.mac_endpts, &p_endpt->mac_item );\r
+ /*\r
+ * The enpoints are *ALWAYS* in both the MAC and GID maps. They are only\r
+ * in the LID map if the GID has the same subnet prefix as us.\r
+ */\r
+ cl_fmap_remove_item( &p_port->endpt_mgr.gid_endpts, &p_endpt->gid_item );\r
+#if 0\r
+\r
+ if( p_port->p_adapter->params.cm_enabled )\r
+ {\r
+ p_fmap_item = cl_fmap_get( &p_port->endpt_mgr.conn_endpts, &p_endpt->dgid );\r
+ \r
+ if( p_fmap_item != cl_fmap_end( &p_port->endpt_mgr.conn_endpts ) )\r
+ {\r
+ cl_fmap_remove_item( &p_port->endpt_mgr.conn_endpts, \r
+ &p_endpt->conn_item );\r
+ }\r
+ }\r
+#endif \r
+ if( p_endpt->dlid )\r
+ {\r
+ cl_qmap_remove_item( &p_port->endpt_mgr.lid_endpts,\r
+ &p_endpt->lid_item );\r
+ }\r
+\r
+ cl_obj_unlock( &p_port->obj );\r
+\r
+ //TODO CM\r
+ //endpt_cm_destroy_conn( p_port, p_endpt );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+}\r
+\r
+\r
+NTSTATUS\r
+ipoib_mac_to_gid(\r
+ IN ipoib_port_t* const p_port,\r
+ IN const mac_addr_t mac,\r
+ OUT ib_gid_t* p_gid )\r
+{\r
+ ipoib_endpt_t* p_endpt;\r
+ cl_map_item_t *p_item;\r
+ uint64_t key = 0;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+ cl_memcpy( &key, &mac, sizeof(mac_addr_t) );\r
+\r
+ cl_obj_lock( &p_port->obj );\r
+\r
+ p_item = cl_qmap_get( &p_port->endpt_mgr.mac_endpts, key );\r
+ if( p_item == cl_qmap_end( &p_port->endpt_mgr.mac_endpts ) )\r
+ {\r
+ cl_obj_unlock( &p_port->obj );\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed endpoint lookup.\n") );\r
+ return STATUS_INVALID_PARAMETER;\r
+ }\r
+\r
+ p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item );\r
+ *p_gid = p_endpt->dgid;\r
+\r
+ cl_obj_unlock( &p_port->obj );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+ return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+NTSTATUS\r
+ipoib_mac_to_path(\r
+ IN ipoib_port_t* const p_port,\r
+ IN const mac_addr_t mac,\r
+ OUT ib_path_rec_t* p_path )\r
+{\r
+ ipoib_endpt_t* p_endpt;\r
+ cl_map_item_t *p_item;\r
+ uint64_t key = 0;\r
+ uint8_t sl;\r
+ net32_t flow_lbl;\r
+ uint8_t hop_limit;\r
+ uint8_t pkt_life;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+ cl_memcpy( &key, &mac, sizeof(mac_addr_t) );\r
+\r
+ cl_obj_lock( &p_port->obj );\r
+\r
+ if( p_port->p_local_endpt == NULL )\r
+ {\r
+ cl_obj_unlock( &p_port->obj );\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("No local endpoint.\n") );\r
+ return STATUS_INVALID_PARAMETER;\r
+ }\r
+\r
+ if( mac.addr[0] == 0 && mac.addr[1] == 0 && mac.addr[2] == 0 &&\r
+ mac.addr[3] == 0 && mac.addr[4] == 0 && mac.addr[5] == 0 )\r
+ {\r
+ p_endpt = p_port->p_local_endpt;\r
+ }\r
+ else\r
+ {\r
+ p_item = cl_qmap_get( &p_port->endpt_mgr.mac_endpts, key );\r
+ if( p_item == cl_qmap_end( &p_port->endpt_mgr.mac_endpts ) )\r
+ {\r
+ cl_obj_unlock( &p_port->obj );\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed endpoint lookup.\n") );\r
+ return STATUS_INVALID_PARAMETER;\r
+ }\r
+\r
+ p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item );\r
+ }\r
+\r
+ p_path->service_id = 0;\r
+ p_path->dgid = p_endpt->dgid;\r
+ p_path->sgid = p_port->p_local_endpt->dgid;\r
+ p_path->dlid = p_endpt->dlid;\r
+ p_path->slid = p_port->p_local_endpt->dlid;\r
+\r
+ ib_member_get_sl_flow_hop(\r
+ p_port->ib_mgr.bcast_rec.sl_flow_hop,\r
+ &sl,\r
+ &flow_lbl,\r
+ &hop_limit\r
+ );\r
+ \r
+ if( p_path->slid == p_path->dlid )\r
+ pkt_life = 0;\r
+ else\r
+ pkt_life = p_port->ib_mgr.bcast_rec.pkt_life;\r
+\r
+ ib_path_rec_init_local(\r
+ p_path,\r
+ &p_endpt->dgid,\r
+ &p_port->p_local_endpt->dgid,\r
+ p_endpt->dlid,\r
+ p_port->p_local_endpt->dlid,\r
+ 1,\r
+ p_port->ib_mgr.bcast_rec.pkey,\r
+ sl, 0,\r
+ IB_PATH_SELECTOR_EXACTLY, p_port->ib_mgr.bcast_rec.mtu,\r
+ IB_PATH_SELECTOR_EXACTLY, p_port->ib_mgr.bcast_rec.rate,\r
+ IB_PATH_SELECTOR_EXACTLY, pkt_life,\r
+ 0 );\r
+\r
+ /* Set global routing information. */\r
+ ib_path_rec_set_hop_flow_raw( p_path, hop_limit, flow_lbl, FALSE );\r
+ p_path->tclass = p_port->ib_mgr.bcast_rec.tclass;\r
+ \r
+ cl_obj_unlock( &p_port->obj );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+ return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static inline NDIS_STATUS\r
+__endpt_mgr_ref(\r
+ IN ipoib_port_t* const p_port,\r
+ IN const mac_addr_t mac,\r
+ OUT ipoib_endpt_t** const pp_endpt )\r
+{\r
+ NDIS_STATUS status;\r
+ cl_map_item_t *p_item;\r
+ uint64_t key;\r
+\r
+ PERF_DECLARE( EndptQueue );\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+ if( !cl_memcmp( &mac, &p_port->p_adapter->params.conf_mac, sizeof(mac) ) )\r
+ {\r
+ /* Discard loopback traffic. */\r
+ IPOIB_PRINT(TRACE_LEVEL_WARNING, IPOIB_DBG_ENDPT,\r
+ ("Discarding loopback traffic\n") );\r
+ IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+ return NDIS_STATUS_NO_ROUTE_TO_DESTINATION;\r
+ }\r
+\r
+ key = 0;\r
+ cl_memcpy( &key, &mac, sizeof(mac_addr_t) );\r
+\r
+ cl_obj_lock( &p_port->obj );\r
+\r
+ IPOIB_PRINT( TRACE_LEVEL_VERBOSE, IPOIB_DBG_ENDPT,\r
+ ("Look for :\t MAC: %02X-%02X-%02X-%02X-%02X-%02X\n",\r
+ mac.addr[0], mac.addr[1], mac.addr[2],\r
+ mac.addr[3], mac.addr[4], mac.addr[5]) );\r
+\r
+ p_item = cl_qmap_get( &p_port->endpt_mgr.mac_endpts, key );\r
+ if( p_item == cl_qmap_end( &p_port->endpt_mgr.mac_endpts ) )\r
+ {\r
+ cl_obj_unlock( &p_port->obj );\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
+ ("Failed endpoint lookup.\n") );\r
+ return NDIS_STATUS_NO_ROUTE_TO_DESTINATION;\r
+ }\r
+\r
+ *pp_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item );\r
+ ipoib_endpt_ref( *pp_endpt );\r
+\r
+ cl_obj_unlock( &p_port->obj );\r
+\r
+ cl_perf_start( EndptQueue );\r
+ status = ipoib_endpt_queue( *pp_endpt );\r
+ cl_perf_stop( &p_port->p_adapter->perf, EndptQueue );\r
+ if( status != NDIS_STATUS_SUCCESS )\r
+ *pp_endpt = NULL;\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+ return status;\r
+}\r
+\r
+\r
+static inline NDIS_STATUS\r
+__endpt_mgr_get_gid_qpn(\r
+ IN ipoib_port_t* const p_port,\r
+ IN const mac_addr_t mac,\r
+ OUT ib_gid_t* const p_gid,\r
+ OUT UNALIGNED net32_t* const p_qpn )\r
+{\r
+ UNALIGNED\r
+ cl_map_item_t *p_item;\r
+ ipoib_endpt_t *p_endpt;\r
+ uint64_t key;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+ cl_obj_lock( &p_port->obj );\r
+\r
+ key = 0;\r
+ cl_memcpy( &key, &mac, sizeof(mac_addr_t) );\r
+ p_item = cl_qmap_get( &p_port->endpt_mgr.mac_endpts, key );\r
+ if( p_item == cl_qmap_end( &p_port->endpt_mgr.mac_endpts ) )\r
+ {\r
+ cl_obj_unlock( &p_port->obj );\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
+ ("Failed endpoint lookup.\n") );\r
+ return NDIS_STATUS_FAILURE;\r
+ }\r
+\r
+ p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item );\r
+\r
+ *p_gid = p_endpt->dgid;\r
+ *p_qpn = p_endpt->qpn;\r
+\r
+ cl_obj_unlock( &p_port->obj );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+ return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static inline ipoib_endpt_t*\r
+__endpt_mgr_get_by_gid(\r
+ IN ipoib_port_t* const p_port,\r
+ IN const ib_gid_t* const p_gid )\r
+{\r
+ cl_fmap_item_t *p_item;\r
+ ipoib_endpt_t *p_endpt;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+ p_item = cl_fmap_get( &p_port->endpt_mgr.gid_endpts, p_gid );\r
+ if( p_item == cl_fmap_end( &p_port->endpt_mgr.gid_endpts ) )\r
+ p_endpt = NULL;\r
+ else\r
+ p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, gid_item );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+ return p_endpt;\r
+}\r
+\r
+\r
+static ipoib_endpt_t*\r
+__endpt_mgr_get_by_lid(\r
+ IN ipoib_port_t* const p_port,\r
+ IN const net16_t lid )\r
+{\r
+ cl_map_item_t *p_item;\r
+ ipoib_endpt_t *p_endpt;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+ p_item = cl_qmap_get( &p_port->endpt_mgr.lid_endpts, lid );\r
+ if( p_item == cl_qmap_end( &p_port->endpt_mgr.lid_endpts ) )\r
+ p_endpt = NULL;\r
+ else\r
+ p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, lid_item );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+ return p_endpt;\r
+}\r
+\r
+\r
+inline ib_api_status_t\r
+__endpt_mgr_insert_locked(\r
+ IN ipoib_port_t* const p_port,\r
+ IN const mac_addr_t mac,\r
+ IN ipoib_endpt_t* const p_endpt )\r
+{\r
+ ib_api_status_t status;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
+ ("insert :\t MAC: %02X-%02X-%02X-%02X-%02X-%02X\n",\r
+ mac.addr[0], mac.addr[1], mac.addr[2],\r
+ mac.addr[3], mac.addr[4], mac.addr[5]) );\r
+\r
+ cl_obj_lock( &p_port->obj );\r
+ while( p_port->endpt_rdr )\r
+ {\r
+ cl_obj_unlock( &p_port->obj );\r
+ cl_obj_lock( &p_port->obj );\r
+ }\r
+ /* __endpt_mgr_insert expects *one* reference to be held when being called. */\r
+ cl_atomic_inc( &p_port->endpt_rdr );\r
+ status= __endpt_mgr_insert( p_port, mac, p_endpt );\r
+ cl_atomic_dec( &p_port->endpt_rdr );\r
+ cl_obj_unlock( &p_port->obj );\r
+\r
+ return status;\r
+}\r
+\r
+\r
+inline ib_api_status_t\r
+__endpt_mgr_insert(\r
+ IN ipoib_port_t* const p_port,\r
+ IN const mac_addr_t mac,\r
+ IN ipoib_endpt_t* const p_endpt )\r
+{\r
+ uint64_t key;\r
+ cl_status_t cl_status;\r
+ cl_map_item_t *p_qitem;\r
+ cl_fmap_item_t *p_fitem;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+ /* Wait for all accesses to the map to complete. */\r
+ while( p_port->endpt_rdr > 1 )\r
+ ;\r
+\r
+ /* Link the endpoint to the port. */\r
+ cl_status = cl_obj_insert_rel_parent_locked(\r
+ &p_endpt->rel, &p_port->obj, &p_endpt->obj );\r
+\r
+ if( cl_status != CL_SUCCESS )\r
+ {\r
+ cl_obj_destroy( &p_endpt->obj );\r
+ return IB_INVALID_STATE;\r
+ }\r
+\r
+#if DBG\r
+ cl_atomic_inc( &p_port->ref[ref_endpt_track] );\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OBJ,\r
+ ("ref type %d ref_cnt %d\n", ref_endpt_track, p_port->obj.ref_cnt) );\r
+#endif\r
+\r
+ p_endpt->mac = mac;\r
+ key = 0;\r
+ cl_memcpy( &key, &mac, sizeof(mac_addr_t) );\r
+ p_qitem = cl_qmap_insert(\r
+ &p_port->endpt_mgr.mac_endpts, key, &p_endpt->mac_item );\r
+ CL_ASSERT( p_qitem == &p_endpt->mac_item );\r
+ p_fitem = cl_fmap_insert(\r
+ &p_port->endpt_mgr.gid_endpts, &p_endpt->dgid, &p_endpt->gid_item );\r
+ CL_ASSERT( p_fitem == &p_endpt->gid_item );\r
+ if( p_endpt->dlid )\r
+ {\r
+ p_qitem = cl_qmap_insert(\r
+ &p_port->endpt_mgr.lid_endpts, p_endpt->dlid, &p_endpt->lid_item );\r
+ CL_ASSERT( p_qitem == &p_endpt->lid_item );\r
+ if (p_qitem != &p_endpt->lid_item) {\r
+ // Since we failed to insert into the list, make sure it is not removed\r
+ p_endpt->dlid =0;\r
+ }\r
+ }\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+ return IB_SUCCESS;\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__endpt_mgr_add_bcast(\r
+ IN ipoib_port_t* const p_port,\r
+ IN ib_mcast_rec_t *p_mcast_rec )\r
+{\r
+ ib_api_status_t status;\r
+ ipoib_endpt_t *p_endpt;\r
+ mac_addr_t bcast_mac;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+ /*\r
+ * Cache the broadcast group properties for creating future mcast groups.\r
+ */\r
+ p_port->ib_mgr.bcast_rec = *p_mcast_rec->p_member_rec;\r
+\r
+ /* Allocate the broadcast endpoint. */\r
+ p_endpt = ipoib_endpt_create( &p_mcast_rec->p_member_rec->mgid,\r
+ 0 , CL_HTON32(0x00FFFFFF) );\r
+ if( !p_endpt )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ipoib_endpt_create failed.\n") );\r
+ return IB_INSUFFICIENT_RESOURCES;\r
+ }\r
+ /* set reference to transport to be used while is not attached to the port */\r
+ p_endpt->is_mcast_listener = TRUE;\r
+ p_endpt->p_ifc = p_port->p_adapter->p_ifc;\r
+ status = ipoib_endpt_set_mcast( p_endpt, p_port->ib_mgr.h_pd,\r
+ p_port->port_num, p_mcast_rec );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ cl_obj_destroy( &p_endpt->obj );\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ipoib_create_mcast_endpt returned %s\n",\r
+ p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+ return status;\r
+ }\r
+\r
+ /* Add the broadcast endpoint to the endpoint map. */\r
+ cl_memset( &bcast_mac, 0xFF, sizeof(bcast_mac) );\r
+ status = __endpt_mgr_insert_locked( p_port, bcast_mac, p_endpt );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+ return status;\r
+}\r
+\r
+\r
+void\r
+ipoib_port_remove_endpt(\r
+ IN ipoib_port_t* const p_port,\r
+ IN const mac_addr_t mac )\r
+{\r
+ cl_map_item_t *p_item;\r
+ //TODO CM\r
+// cl_fmap_item_t *p_fmap_item;\r
+ ipoib_endpt_t *p_endpt;\r
+ uint64_t key;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+ key = 0;\r
+ cl_memcpy( &key, &mac, sizeof(mac_addr_t) );\r
+\r
+ /* Remove the endpoint from the maps so further requests don't find it. */\r
+ cl_obj_lock( &p_port->obj );\r
+ /* Wait for all readers to finish */\r
+ while( p_port->endpt_rdr )\r
+ ;\r
+ p_item = cl_qmap_remove( &p_port->endpt_mgr.mac_endpts, key );\r
+ /*\r
+ * Dereference the endpoint. If the ref count goes to zero, it\r
+ * will get freed.\r
+ */\r
+ if( p_item != cl_qmap_end( &p_port->endpt_mgr.mac_endpts ) )\r
+ {\r
+ p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item );\r
+ /*\r
+ * The enpoints are *ALWAYS* in both the MAC and GID maps. They are only\r
+ * in the LID map if the GID has the same subnet prefix as us.\r
+ */\r
+ cl_fmap_remove_item(\r
+ &p_port->endpt_mgr.gid_endpts, &p_endpt->gid_item );\r
+#if 0\r
+ if( p_port->p_adapter->params.cm_enabled )\r
+ {\r
+ p_fmap_item = cl_fmap_get( &p_port->endpt_mgr.conn_endpts, &p_endpt->dgid );\r
+ \r
+ if( p_fmap_item != cl_fmap_end( &p_port->endpt_mgr.conn_endpts ) )\r
+ {\r
+ cl_fmap_remove_item( &p_port->endpt_mgr.conn_endpts, \r
+ &p_endpt->conn_item );\r
+ }\r
+ }\r
+#endif\r
+\r
+ if( p_endpt->dlid )\r
+ {\r
+ cl_qmap_remove_item(\r
+ &p_port->endpt_mgr.lid_endpts, &p_endpt->lid_item );\r
+ }\r
+\r
+ cl_obj_unlock( &p_port->obj );\r
+ //TODO CM\r
+ //endpt_cm_destroy_conn( p_port, p_endpt );\r
+\r
+#if DBG\r
+ cl_atomic_dec( &p_port->ref[ref_endpt_track] );\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
+ ("ref type %d ref_cnt %d\n", ref_endpt_track, p_port->obj.ref_cnt) );\r
+#endif\r
+\r
+ }\r
+ else\r
+ {\r
+ cl_obj_unlock( &p_port->obj );\r
+ }\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+}\r
+\r
+/*\r
+ * The sequence for port up is as follows:\r
+ * 1. The port goes active. This allows the adapter to send SA queries\r
+ * and join the broadcast group (and other groups).\r
+ *\r
+ * 2. The adapter sends an SA query for the broadcast group.\r
+ *\r
+ * 3. Upon completion of the query, the adapter joins the broadcast group.\r
+ */\r
+\r
+\r
+/*\r
+ * Query the SA for the broadcast group.\r
+ */\r
+void\r
+ipoib_port_up(\r
+ IN ipoib_port_t* const p_port,\r
+ IN const ib_pnp_port_rec_t* const p_pnp_rec )\r
+{\r
+ ib_port_info_t *p_port_info;\r
+ ib_mad_t *mad_in = NULL;\r
+ ib_mad_t *mad_out = NULL;\r
+ ib_api_status_t status = IB_INSUFFICIENT_MEMORY;\r
+ static int cnt = 0;\r
+ \r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_INIT,\r
+ ("[%d] Entering port_up.\n", ++cnt) ); \r
+ \r
+ cl_obj_lock( &p_port->obj );\r
+ if ( p_port->state == IB_QPS_INIT ) \r
+ {\r
+ cl_obj_unlock( &p_port->obj );\r
+ status = IB_SUCCESS;\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+ ("p_port->state = %d - Aborting.\n", p_port->state) ); \r
+ goto up_done;\r
+ }\r
+ else if ( p_port->state == IB_QPS_RTS )\r
+ {\r
+ cl_obj_unlock( &p_port->obj );\r
+ cl_obj_lock( &p_port->p_adapter->obj );\r
+ if( p_port->p_adapter->state == IB_PNP_PORT_INIT )\r
+ {\r
+ p_port->p_adapter->state = IB_PNP_PORT_ACTIVE;\r
+ }\r
+ cl_obj_unlock( &p_port->p_adapter->obj );\r
+ status = IB_SUCCESS;\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+ ("Port init is done. p_port->state = %d.\n", p_port->state ) );\r
+ goto up_done;\r
+ }\r
+ p_port->state = IB_QPS_INIT;\r
+ cl_obj_unlock( &p_port->obj ); \r
+\r
+\r
+ /* Wait for all work requests to get flushed. */\r
+ while( p_port->recv_mgr.depth || p_port->send_mgr.depth )\r
+ cl_thread_suspend( 0 );\r
+\r
+ KeResetEvent( &p_port->sa_event );\r
+\r
+ mad_out = (ib_mad_t *) (ib_mad_t*)cl_zalloc(256);\r
+ if(! mad_out)\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("failed to allocate mad mad_out\n")); \r
+ goto up_done;\r
+ }\r
+ mad_in = (ib_mad_t *) cl_zalloc(256);\r
+ if(! mad_in)\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("failed to allocate mad mad_in\n")); \r
+ goto up_done;\r
+ }\r
+\r
+ mad_in->attr_id = IB_MAD_ATTR_PORT_INFO;\r
+ mad_in->method = IB_MAD_METHOD_GET;\r
+ mad_in->base_ver = 1;\r
+ mad_in->class_ver =1;\r
+ mad_in->mgmt_class = IB_MCLASS_SUBN_LID;\r
+ \r
+ status = p_port->p_adapter->p_ifc->local_mad(\r
+ p_port->ib_mgr.h_ca ,p_port->port_num ,mad_in ,mad_out);\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ ipoib_set_inactive( p_port->p_adapter );\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ib_local_mad returned %s\n", \r
+ p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+ goto up_done;\r
+ }\r
+\r
+ p_port_info = (ib_port_info_t*)(((ib_smp_t*)mad_out)->data);\r
+ p_port->base_lid = p_pnp_rec->p_port_attr->lid;\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+ ("Received port info: link width = %d.\n",\r
+ p_port_info->link_width_active) );\r
+ p_port->ib_mgr.rate =\r
+ ib_port_info_compute_rate( p_port_info );\r
+ \r
+ ipoib_set_rate( p_port->p_adapter,\r
+ p_port_info->link_width_active,\r
+ ib_port_info_get_link_speed_active( p_port_info ) );\r
+\r
+ status = __port_get_bcast( p_port );\r
+ if (status != IB_SUCCESS)\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ (" __port_get_bcast returned %s\n",p_port->p_adapter->p_ifc->get_err_str( status )));\r
+\r
+up_done:\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ if( status != IB_CANCELED )\r
+ {\r
+ ipoib_set_inactive( p_port->p_adapter );\r
+ __endpt_mgr_reset_all( p_port );\r
+ }\r
+ ASSERT(p_port->state == IB_QPS_INIT || p_port->state == IB_QPS_ERROR);\r
+ p_port->state = IB_QPS_ERROR;\r
+ KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE );\r
+ }\r
+\r
+ if(mad_out)\r
+ cl_free(mad_out);\r
+ if(mad_in)\r
+ cl_free(mad_in);\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__endpt_mgr_add_local(\r
+ IN ipoib_port_t* const p_port,\r
+ IN ib_port_info_t* const p_port_info )\r
+{\r
+ ib_api_status_t status;\r
+ ib_gid_t gid;\r
+ ipoib_endpt_t *p_endpt;\r
+ ib_av_attr_t av_attr;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+ ib_gid_set_default( &gid, p_port->p_adapter->guids.port_guid.guid );\r
+ p_endpt = ipoib_endpt_create(\r
+ &gid, p_port_info->base_lid, p_port->ib_mgr.qpn );\r
+ if( !p_endpt )\r
+ {\r
+ p_port->p_adapter->hung = TRUE;\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed to create local endpt\n") );\r
+ return IB_INSUFFICIENT_MEMORY;\r
+ }\r
+\r
+ cl_memclr( &av_attr, sizeof(ib_av_attr_t) );\r
+ av_attr.port_num = p_port->port_num;\r
+ av_attr.sl = 0;\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
+ (" av_attr.dlid = p_port_info->base_lid = %d\n", cl_ntoh16( p_port_info->base_lid ) ));\r
+ av_attr.dlid = p_port_info->base_lid;\r
+ av_attr.static_rate = p_port->ib_mgr.rate;\r
+ av_attr.path_bits = 0;\r
+ status = p_port->p_adapter->p_ifc->create_av(\r
+ p_port->ib_mgr.h_pd, &av_attr, &p_endpt->h_av );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ cl_obj_destroy( &p_endpt->obj );\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ib_create_av for local endpoint returned %s\n",\r
+ p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+ return status;\r
+ }\r
+\r
+ /* __endpt_mgr_insert expects *one* reference to be held. */\r
+ cl_atomic_inc( &p_port->endpt_rdr );\r
+ status = __endpt_mgr_insert( p_port, p_port->p_adapter->params.conf_mac, p_endpt );\r
+ cl_atomic_dec( &p_port->endpt_rdr );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("__endpt_mgr_insert for local endpoint returned %s\n",\r
+ p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+ return status;\r
+ }\r
+\r
+ p_port->p_local_endpt = p_endpt;\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+ return status;\r
+}\r
+\r
+\r
+\r
+\r
+static ib_api_status_t\r
+__port_get_bcast(\r
+ IN ipoib_port_t* const p_port )\r
+{\r
+ ib_api_status_t status;\r
+ ib_query_req_t query;\r
+ ib_user_query_t info;\r
+ ib_member_rec_t member_rec;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+ info.method = IB_MAD_METHOD_GETTABLE;\r
+ info.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD;\r
+ info.attr_size = sizeof(ib_member_rec_t);\r
+ info.comp_mask = IB_MCR_COMPMASK_MGID;\r
+ info.p_attr = &member_rec;\r
+\r
+ /* Query requires only the MGID. */\r
+ cl_memclr( &member_rec, sizeof(ib_member_rec_t) );\r
+ member_rec.mgid = bcast_mgid_template;\r
+\r
+ member_rec.mgid.raw[4] = (uint8_t) (p_port->p_adapter->guids.port_guid.pkey >> 8) ;\r
+ member_rec.mgid.raw[5] = (uint8_t) p_port->p_adapter->guids.port_guid.pkey;\r
+ member_rec.pkey = cl_hton16(p_port->p_adapter->guids.port_guid.pkey);\r
+ cl_memclr( &query, sizeof(ib_query_req_t) );\r
+ query.query_type = IB_QUERY_USER_DEFINED;\r
+ query.p_query_input = &info;\r
+ query.port_guid = p_port->p_adapter->guids.port_guid.guid;\r
+ query.timeout_ms = p_port->p_adapter->params.sa_timeout;\r
+ query.retry_cnt = p_port->p_adapter->params.sa_retry_cnt;\r
+ query.query_context = p_port;\r
+ query.pfn_query_cb = __bcast_get_cb;\r
+\r
+ /* reference the object for the multicast query. */\r
+ ipoib_port_ref( p_port, ref_get_bcast );\r
+\r
+ status = p_port->p_adapter->p_ifc->query(\r
+ p_port->p_adapter->h_al, &query, &p_port->ib_mgr.h_query );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ ipoib_port_deref( p_port, ref_get_bcast );\r
+ ASSERT(FALSE);\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ib_query returned %s\n", \r
+ p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+ }\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ib_query returned SUCCESS\n"));\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+ return status;\r
+}\r
+\r
+\r
+/* Callback for the MCMemberRecord Get query for the IPv4 broadcast group. */\r
+static void\r
+__bcast_get_cb(\r
+ IN ib_query_rec_t *p_query_rec )\r
+{\r
+ ipoib_port_t *p_port;\r
+ ib_member_rec_t *p_mc_req;\r
+ ib_api_status_t status;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+ p_port = (ipoib_port_t*)p_query_rec->query_context;\r
+\r
+ cl_obj_lock( &p_port->obj );\r
+ p_port->ib_mgr.h_query = NULL;\r
+\r
+ CL_ASSERT(p_port->state == IB_QPS_INIT || p_port->state == IB_QPS_ERROR);\r
+ if( p_port->state != IB_QPS_INIT )\r
+ {\r
+ status = IB_CANCELED;\r
+ goto done;\r
+ }\r
+ \r
+ status = p_query_rec->status;\r
+\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+ ("status of request %s\n", \r
+ p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+\r
+ switch( status )\r
+ {\r
+ case IB_SUCCESS:\r
+ if( p_query_rec->result_cnt )\r
+ {\r
+ p_mc_req = (ib_member_rec_t*)\r
+ ib_get_query_result( p_query_rec->p_result_mad, 0 );\r
+\r
+ /* Join the broadcast group. */\r
+ status = __port_join_bcast( p_port, p_mc_req );\r
+ break;\r
+ }\r
+ /* Fall through. */\r
+\r
+ case IB_REMOTE_ERROR:\r
+ /* SA failed the query. Broadcast group doesn't exist, create it. */\r
+ status = __port_create_bcast( p_port );\r
+ break;\r
+\r
+ case IB_CANCELED:\r
+ IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+ ("Instance destroying - Aborting.\n") );\r
+ break;\r
+\r
+ default:\r
+ NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+ EVENT_IPOIB_BCAST_GET, 1, p_query_rec->status );\r
+ }\r
+done:\r
+ cl_obj_unlock( &p_port->obj );\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ if( status != IB_CANCELED )\r
+ {\r
+ ipoib_set_inactive( p_port->p_adapter );\r
+ __endpt_mgr_reset_all( p_port );\r
+ }\r
+ p_port->state = IB_QPS_ERROR;\r
+ KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE );\r
+ }\r
+\r
+ /* Return the response MAD to AL. */\r
+ if( p_query_rec->p_result_mad )\r
+ p_port->p_adapter->p_ifc->put_mad( p_query_rec->p_result_mad );\r
+\r
+ /* Release the reference taken when issuing the member record query. */\r
+ ipoib_port_deref( p_port, ref_bcast_get_cb );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__port_join_bcast(\r
+ IN ipoib_port_t* const p_port,\r
+ IN ib_member_rec_t* const p_member_rec )\r
+{\r
+ ib_api_status_t status;\r
+ ib_mcast_req_t mcast_req;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+ /* Check that the rate is realizable for our port. */\r
+ if( p_port->ib_mgr.rate < (p_member_rec->rate & 0x3F) &&\r
+ (g_ipoib.bypass_check_bcast_rate == 0))\r
+ {\r
+ /*\r
+ * The MC group rate is higher than our port's rate. Log an error\r
+ * and stop. A port transition will drive the retry.\r
+ */\r
+ IPOIB_PRINT(TRACE_LEVEL_WARNING, IPOIB_DBG_INIT,\r
+ ("Unrealizable join due to rate mismatch.\n") );\r
+ NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+ EVENT_IPOIB_BCAST_RATE, 2,\r
+ (uint32_t)(p_member_rec->rate & 0x3F),\r
+ (uint32_t)p_port->ib_mgr.rate );\r
+ return IB_ERROR;\r
+ }\r
+\r
+ /* Join the broadcast group. */\r
+ cl_memclr( &mcast_req, sizeof(mcast_req) );\r
+ /* Copy the results of the Get to use as parameters. */\r
+ mcast_req.member_rec = *p_member_rec;\r
+ /* We specify our port GID for the join operation. */\r
+ mcast_req.member_rec.port_gid.unicast.prefix = IB_DEFAULT_SUBNET_PREFIX;\r
+ mcast_req.member_rec.port_gid.unicast.interface_id =\r
+ p_port->p_adapter->guids.port_guid.guid;\r
+\r
+ mcast_req.mcast_context = p_port;\r
+ mcast_req.pfn_mcast_cb = __bcast_cb;\r
+ mcast_req.timeout_ms = p_port->p_adapter->params.sa_timeout;\r
+ mcast_req.retry_cnt = p_port->p_adapter->params.sa_retry_cnt;\r
+ mcast_req.port_guid = p_port->p_adapter->guids.port_guid.guid;\r
+ mcast_req.pkey_index = p_port->pkey_index;\r
+\r
+ if( ib_member_get_state( mcast_req.member_rec.scope_state ) !=\r
+ IB_MC_REC_STATE_FULL_MEMBER )\r
+ {\r
+ IPOIB_PRINT(TRACE_LEVEL_WARNING, IPOIB_DBG_INIT,\r
+ ("Incorrect MC member rec join state in query response.\n") );\r
+ ib_member_set_state( &mcast_req.member_rec.scope_state,\r
+ IB_MC_REC_STATE_FULL_MEMBER );\r
+ }\r
+\r
+ /* reference the object for the multicast join request. */\r
+ ipoib_port_ref( p_port, ref_join_bcast );\r
+\r
+ status = p_port->p_adapter->p_ifc->join_mcast(\r
+ p_port->ib_mgr.h_qp, &mcast_req );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ ipoib_port_deref( p_port, ref_bcast_join_failed );\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ib_join_mcast returned %s\n", \r
+ p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+ }\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+ return status;\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__port_create_bcast(\r
+ IN ipoib_port_t* const p_port )\r
+{\r
+ ib_api_status_t status;\r
+ ib_mcast_req_t mcast_req;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+ /* Join the broadcast group. */\r
+ cl_memclr( &mcast_req, sizeof(mcast_req) );\r
+ mcast_req.create = TRUE;\r
+ /*\r
+ * Create requires pkey, qkey, SL, flow label, traffic class, joing state\r
+ * and port GID.\r
+ *\r
+ * We specify the MGID since we don't want the SA to generate it for us.\r
+ */\r
+ mcast_req.member_rec.mgid = bcast_mgid_template;\r
+ mcast_req.member_rec.mgid.raw[4] = (uint8_t) (p_port->p_adapter->guids.port_guid.pkey >> 8); \r
+ mcast_req.member_rec.mgid.raw[5] = (uint8_t) p_port->p_adapter->guids.port_guid.pkey;\r
+ ib_gid_set_default( &mcast_req.member_rec.port_gid,\r
+ p_port->p_adapter->guids.port_guid.guid );\r
+ /*\r
+ * IPOIB spec requires that the QKEY have the MSb set so that the QKEY\r
+ * from the QP is used rather than the QKEY in the send WR.\r
+ */\r
+ mcast_req.member_rec.qkey =\r
+ (uint32_t)(uintn_t)p_port | IB_QP_PRIVILEGED_Q_KEY;\r
+ mcast_req.member_rec.mtu =\r
+ (IB_PATH_SELECTOR_EXACTLY << 6) | IB_MTU_LEN_2048;\r
+\r
+ mcast_req.member_rec.pkey = cl_hton16(p_port->p_adapter->guids.port_guid.pkey);\r
+\r
+ mcast_req.member_rec.sl_flow_hop = ib_member_set_sl_flow_hop( 0, 0, 0 );\r
+ mcast_req.member_rec.scope_state =\r
+ ib_member_set_scope_state( 2, IB_MC_REC_STATE_FULL_MEMBER );\r
+\r
+ mcast_req.mcast_context = p_port;\r
+ mcast_req.pfn_mcast_cb = __bcast_cb;\r
+ mcast_req.timeout_ms = p_port->p_adapter->params.sa_timeout;\r
+ mcast_req.retry_cnt = p_port->p_adapter->params.sa_retry_cnt;\r
+ mcast_req.port_guid = p_port->p_adapter->guids.port_guid.guid;\r
+ mcast_req.pkey_index = p_port->pkey_index;\r
+\r
+ /* reference the object for the multicast join request. */\r
+ ipoib_port_ref( p_port, ref_join_bcast );\r
+\r
+ status = p_port->p_adapter->p_ifc->join_mcast( p_port->ib_mgr.h_qp, &mcast_req );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ ipoib_port_deref( p_port, ref_bcast_create_failed );\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ib_join_mcast returned %s\n", \r
+ p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+ }\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+ return status;\r
+}\r
+\r
+\r
+void\r
+ipoib_port_down(\r
+ IN ipoib_port_t* const p_port )\r
+{\r
+ ib_api_status_t status;\r
+ ib_qp_mod_t qp_mod;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+ /*\r
+ * Mark our state. This causes all callbacks to abort.\r
+ * Note that we hold the receive lock so that we synchronize\r
+ * with reposting. We must take the receive lock before the\r
+ * object lock since that is the order taken when reposting.\r
+ */\r
+ cl_spinlock_acquire( &p_port->recv_lock );\r
+ cl_obj_lock( &p_port->obj );\r
+ p_port->state = IB_QPS_ERROR;\r
+\r
+ NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+ EVENT_IPOIB_PORT_DOWN, 0 );\r
+\r
+ if( p_port->ib_mgr.h_query )\r
+ {\r
+ p_port->p_adapter->p_ifc->cancel_query(\r
+ p_port->p_adapter->h_al, p_port->ib_mgr.h_query );\r
+ p_port->ib_mgr.h_query = NULL;\r
+ }\r
+ cl_obj_unlock( &p_port->obj );\r
+ cl_spinlock_release( &p_port->recv_lock );\r
+\r
+ KeWaitForSingleObject(\r
+ &p_port->sa_event, Executive, KernelMode, FALSE, NULL );\r
+\r
+ /* garbage collector timer is not needed when link is down */\r
+ KeCancelTimer(&p_port->gc_timer);\r
+ KeFlushQueuedDpcs();\r
+\r
+ /*\r
+ * Put the QP in the error state. This removes the need to\r
+ * synchronize with send/receive callbacks.\r
+ */\r
+ CL_ASSERT( p_port->ib_mgr.h_qp );\r
+ cl_memclr( &qp_mod, sizeof(ib_qp_mod_t) );\r
+ qp_mod.req_state = IB_QPS_ERROR;\r
+ status = p_port->p_adapter->p_ifc->modify_qp( p_port->ib_mgr.h_qp, &qp_mod );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ib_modify_qp to error state returned %s.\n",\r
+ p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+ p_port->p_adapter->hung = TRUE;\r
+ return;\r
+ }\r
+\r
+ KeResetEvent(&p_port->leave_mcast_event);\r
+\r
+ /* Reset all endpoints so we don't flush our ARP cache. */\r
+ __endpt_mgr_reset_all( p_port );\r
+\r
+ KeWaitForSingleObject(\r
+ &p_port->leave_mcast_event, Executive, KernelMode, FALSE, NULL );\r
+\r
+ __pending_list_destroy(p_port);\r
+ \r
+ cl_obj_lock( &p_port->p_adapter->obj );\r
+ ipoib_dereg_addrs( p_port->p_adapter );\r
+ cl_obj_unlock( &p_port->p_adapter->obj );\r
+ \r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static void\r
+__bcast_cb(\r
+ IN ib_mcast_rec_t *p_mcast_rec )\r
+{\r
+ ipoib_port_t *p_port;\r
+ ib_api_status_t status;\r
+ LARGE_INTEGER gc_due_time;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+ p_port = (ipoib_port_t*)p_mcast_rec->mcast_context;\r
+\r
+ cl_obj_lock( &p_port->obj );\r
+\r
+ ASSERT(p_port->state == IB_QPS_INIT || p_port->state == IB_QPS_ERROR);\r
+ if( p_port->state != IB_QPS_INIT )\r
+ {\r
+ cl_obj_unlock( &p_port->obj );\r
+ if( p_mcast_rec->status == IB_SUCCESS )\r
+ {\r
+ ipoib_port_ref(p_port, ref_leave_mcast);\r
+ p_port->p_adapter->p_ifc->leave_mcast( p_mcast_rec->h_mcast, __leave_error_mcast_cb );\r
+ }\r
+ KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE );\r
+ ipoib_port_deref( p_port, ref_bcast_inv_state );\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+ ("Invalid state - Aborting.\n") );\r
+ return;\r
+ }\r
+ status = p_mcast_rec->status;\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Multicast join for broadcast group returned %s.\n",\r
+ p_port->p_adapter->p_ifc->get_err_str( p_mcast_rec->status )) );\r
+ if( status == IB_REMOTE_ERROR )\r
+ {\r
+ /*\r
+ * Either:\r
+ * - the join failed because the group no longer exists\r
+ * - the create failed because the group already exists\r
+ *\r
+ * Kick off a new Get query to the SA to restart the join process\r
+ * from the top. Note that as an optimization, it would be\r
+ * possible to distinguish between the join and the create.\r
+ * If the join fails, try the create. If the create fails, start\r
+ * over with the Get.\r
+ */\r
+ /* TODO: Assert is a place holder. Can we ever get here if the\r
+ state isn't IB_PNP_PORT_ADD or PORT_DOWN or PORT_INIT? */\r
+ CL_ASSERT( p_port->p_adapter->state == IB_PNP_PORT_ADD ||\r
+ p_port->p_adapter->state == IB_PNP_PORT_DOWN ||\r
+ p_port->p_adapter->state == IB_PNP_PORT_INIT );\r
+ if(++p_port->bc_join_retry_cnt < p_port->p_adapter->params.bc_join_retry)\r
+ {\r
+ status = __port_get_bcast( p_port );\r
+ }\r
+ else\r
+ {\r
+ NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+ EVENT_IPOIB_BCAST_JOIN, 1, p_mcast_rec->status );\r
+ p_port->bc_join_retry_cnt = 0;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+ EVENT_IPOIB_BCAST_JOIN, 1, p_mcast_rec->status );\r
+ }\r
+\r
+ cl_obj_unlock( &p_port->obj );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ ipoib_set_inactive( p_port->p_adapter );\r
+ __endpt_mgr_reset_all( p_port );\r
+ ASSERT(p_port->state == IB_QPS_INIT || p_port->state == IB_QPS_ERROR);\r
+ p_port->state = IB_QPS_ERROR;\r
+ KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE );\r
+ }\r
+ ipoib_port_deref( p_port, ref_bcast_req_failed );\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+ return;\r
+ }\r
+ p_port->bc_join_retry_cnt = 0;\r
+\r
+ while( p_port->endpt_rdr )\r
+ {\r
+ cl_obj_unlock( &p_port->obj );\r
+ cl_obj_lock( &p_port->obj );\r
+ }\r
+\r
+ if( !p_port->p_local_endpt )\r
+ {\r
+ ib_port_info_t port_info;\r
+ cl_memclr(&port_info, sizeof(port_info));\r
+ port_info.base_lid = p_port->base_lid;\r
+ status = __endpt_mgr_add_local( p_port, &port_info );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("__endpt_mgr_add_local returned %s\n",\r
+ p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+ cl_obj_unlock( &p_port->obj );\r
+ goto err;\r
+ }\r
+ }\r
+\r
+ cl_obj_unlock( &p_port->obj );\r
+\r
+ status = __endpt_mgr_add_bcast( p_port, p_mcast_rec );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("__endpt_mgr_add_bcast returned %s\n",\r
+ p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+ ipoib_port_ref(p_port, ref_leave_mcast);\r
+ status = p_port->p_adapter->p_ifc->leave_mcast( p_mcast_rec->h_mcast, __leave_error_mcast_cb );\r
+ CL_ASSERT( status == IB_SUCCESS );\r
+ goto err;\r
+ }\r
+\r
+ /* Get the QP ready for action. */\r
+ status = __ib_mgr_activate( p_port );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("__ib_mgr_activate returned %s\n", \r
+ p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+\r
+err:\r
+ /* Flag the adapter as hung. */\r
+ p_port->p_adapter->hung = TRUE;\r
+ ASSERT(p_port->state == IB_QPS_INIT || p_port->state == IB_QPS_ERROR);\r
+ p_port->state = IB_QPS_ERROR; \r
+ KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE );\r
+ ipoib_port_deref( p_port, ref_bcast_error );\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+ return;\r
+ }\r
+\r
+ cl_obj_lock( &p_port->obj );\r
+ /* Only change the state if we're still in INIT. */\r
+ ASSERT( p_port->state == IB_QPS_INIT || p_port->state == IB_QPS_ERROR);\r
+ if (p_port->state == IB_QPS_INIT) {\r
+ p_port->state = IB_QPS_RTS;\r
+ }\r
+ cl_obj_unlock( &p_port->obj );\r
+\r
+ /* Prepost receives. */\r
+ cl_spinlock_acquire( &p_port->recv_lock );\r
+ __recv_mgr_repost( p_port );\r
+ cl_spinlock_release( &p_port->recv_lock );\r
+\r
+ /* Notify the adapter that we now have an active connection. */\r
+ status = ipoib_set_active( p_port->p_adapter );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ ib_qp_mod_t qp_mod;\r
+ ipoib_set_inactive( p_port->p_adapter );\r
+ KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE );\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+ ("ipoib_set_active returned %s.\n",p_port->p_adapter->p_ifc->get_err_str( status )));\r
+ cl_spinlock_acquire( &p_port->recv_lock );\r
+ cl_obj_lock( &p_port->obj );\r
+ p_port->state = IB_QPS_ERROR;\r
+ if( p_port->ib_mgr.h_query )\r
+ {\r
+ p_port->p_adapter->p_ifc->cancel_query(\r
+ p_port->p_adapter->h_al, p_port->ib_mgr.h_query );\r
+ p_port->ib_mgr.h_query = NULL;\r
+ }\r
+ cl_obj_unlock( &p_port->obj );\r
+ cl_spinlock_release( &p_port->recv_lock );\r
+\r
+ CL_ASSERT( p_port->ib_mgr.h_qp );\r
+ cl_memclr( &qp_mod, sizeof(ib_qp_mod_t) );\r
+ qp_mod.req_state = IB_QPS_ERROR;\r
+ status = p_port->p_adapter->p_ifc->modify_qp( p_port->ib_mgr.h_qp, &qp_mod );\r
+ __endpt_mgr_reset_all( p_port );\r
+\r
+ ipoib_port_deref( p_port, ref_join_bcast );\r
+ return;\r
+ }\r
+#if 0 //CM\r
+ if( p_port->p_adapter->params.cm_enabled &&\r
+ !p_port->p_local_endpt->conn.h_cm_listen )\r
+ {\r
+ if( ipoib_port_listen( p_port ) != IB_SUCCESS )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Port CM Listen failed\n" ) );\r
+ /*keep going with UD only */\r
+ p_port->p_adapter->params.cm_enabled = FALSE;\r
+\r
+ NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+ EVENT_IPOIB_CONNECTED_MODE_ERR, 1, 0xbadc0de3 );\r
+ }\r
+ }\r
+#endif\r
+ /* garbage collector timer is needed when link is active */\r
+ gc_due_time.QuadPart = -(int64_t)(((uint64_t)p_port->p_adapter->params.mc_leave_rescan * 2000000) * 10);\r
+ KeSetTimerEx(&p_port->gc_timer,gc_due_time,\r
+ (LONG)p_port->p_adapter->params.mc_leave_rescan*1000,&p_port->gc_dpc);\r
+\r
+ KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE );\r
+ ipoib_port_deref( p_port, ref_join_bcast );\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static void\r
+__qp_event(\r
+ IN ib_async_event_rec_t *p_event_rec )\r
+{\r
+ UNUSED_PARAM( p_event_rec );\r
+ CL_ASSERT( p_event_rec->context );\r
+ ((ipoib_port_t*)p_event_rec->context)->p_adapter->hung = TRUE;\r
+}\r
+\r
+\r
+static void\r
+__cq_event(\r
+ IN ib_async_event_rec_t *p_event_rec )\r
+{\r
+ UNUSED_PARAM( p_event_rec );\r
+ CL_ASSERT( p_event_rec->context );\r
+ ((ipoib_port_t*)p_event_rec->context)->p_adapter->hung = TRUE;\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__ib_mgr_activate(\r
+ IN ipoib_port_t* const p_port )\r
+{\r
+ ib_api_status_t status;\r
+ ib_dgrm_info_t dgrm_info;\r
+ ib_qp_mod_t qp_mod;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+ /*\r
+ * Move the QP to RESET. This allows us to reclaim any\r
+ * unflushed receives.\r
+ */\r
+ cl_memclr( &qp_mod, sizeof(ib_qp_mod_t) );\r
+ qp_mod.req_state = IB_QPS_RESET;\r
+ status = p_port->p_adapter->p_ifc->modify_qp( p_port->ib_mgr.h_qp, &qp_mod );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ib_modify_qp returned %s\n", \r
+ p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+ return status;\r
+ }\r
+\r
+ /* Move the QP to RTS. */\r
+ dgrm_info.port_guid = p_port->p_adapter->guids.port_guid.guid;\r
+ dgrm_info.qkey = p_port->ib_mgr.bcast_rec.qkey;\r
+ dgrm_info.pkey_index = p_port->pkey_index;\r
+ status = p_port->p_adapter->p_ifc->init_dgrm_svc( p_port->ib_mgr.h_qp, &dgrm_info );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ib_init_dgrm_svc returned %s\n", \r
+ p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+ return status;\r
+ }\r
+\r
+ /* Rearm the CQs. */\r
+ status = p_port->p_adapter->p_ifc->rearm_cq( p_port->ib_mgr.h_recv_cq, FALSE );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ib_rearm_cq for recv returned %s\n", \r
+ p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+ return status;\r
+ }\r
+ status = p_port->p_adapter->p_ifc->rearm_cq( p_port->ib_mgr.h_send_cq, FALSE );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ib_rearm_cq for send returned %s\n", \r
+ p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+ return status;\r
+ }\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+ return IB_SUCCESS;\r
+}\r
+\r
+\r
+/* Transition to a passive level thread. */\r
+ib_api_status_t\r
+ipoib_port_join_mcast(\r
+ IN ipoib_port_t* const p_port,\r
+ IN const mac_addr_t mac,\r
+ IN const uint8_t state)\r
+{\r
+ ib_api_status_t status;\r
+ ib_mcast_req_t mcast_req;\r
+ ipoib_endpt_t *p_endpt;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_MCAST );\r
+\r
+ switch( __endpt_mgr_ref( p_port, mac, &p_endpt ) )\r
+ {\r
+ case NDIS_STATUS_NO_ROUTE_TO_DESTINATION:\r
+ break;\r
+\r
+ case NDIS_STATUS_SUCCESS:\r
+ ipoib_endpt_deref( p_endpt );\r
+ /* Fall through */\r
+\r
+ case NDIS_STATUS_PENDING:\r
+ return IB_SUCCESS;\r
+ }\r
+\r
+ /*\r
+ * Issue the mcast request, using the parameters of the broadcast group.\r
+ * This allows us to do a create request that should always succeed since\r
+ * the required parameters are known.\r
+ */\r
+ cl_memclr( &mcast_req, sizeof(mcast_req) );\r
+ mcast_req.create = TRUE;\r
+\r
+ /* Copy the settings from the broadcast group. */\r
+ mcast_req.member_rec = p_port->ib_mgr.bcast_rec;\r
+ /* Clear fields that aren't specified in the join */\r
+ mcast_req.member_rec.mlid = 0;\r
+ ib_member_set_state( &mcast_req.member_rec.scope_state,state);\r
+\r
+ if( (mac.addr[0] == 1) && (mac.addr[2] == 0x5E ))\r
+ {\r
+ /*\r
+ * Update the address portion of the MGID with the 28 lower bits of the\r
+ * IP address. Since we're given a MAC address, we are using \r
+ * 24 lower bits of that network-byte-ordered value (assuming MSb\r
+ * is zero) and 4 lsb bits of the first byte of IP address.\r
+ */\r
+ mcast_req.member_rec.mgid.raw[12] = mac.addr[1];\r
+ mcast_req.member_rec.mgid.raw[13] = mac.addr[3];\r
+ mcast_req.member_rec.mgid.raw[14] = mac.addr[4];\r
+ mcast_req.member_rec.mgid.raw[15] = mac.addr[5];\r
+ }\r
+ else\r
+ {\r
+ /* Handle non IP mutlicast MAC addresses. */\r
+ /* Update the signature to use the lower 2 bytes of the OpenIB OUI. */\r
+ mcast_req.member_rec.mgid.raw[2] = 0x14;\r
+ mcast_req.member_rec.mgid.raw[3] = 0x05;\r
+ /* Now copy the MAC address into the last 6 bytes of the GID. */\r
+ cl_memcpy( &mcast_req.member_rec.mgid.raw[10], mac.addr, 6 );\r
+ }\r
+\r
+ mcast_req.mcast_context = p_port;\r
+ mcast_req.pfn_mcast_cb = __mcast_cb;\r
+ mcast_req.timeout_ms = p_port->p_adapter->params.sa_timeout;\r
+ mcast_req.retry_cnt = p_port->p_adapter->params.sa_retry_cnt;\r
+ mcast_req.port_guid = p_port->p_adapter->guids.port_guid.guid;\r
+ mcast_req.pkey_index = p_port->pkey_index;\r
+ mcast_req.member_rec.pkey = cl_hton16(p_port->p_adapter->guids.port_guid.pkey);\r
+ /*\r
+ * Create the endpoint and insert it in the port. Since we don't wait for\r
+ * the mcast SA operations to complete before returning from the multicast\r
+ * list set OID asynchronously, it is possible for the mcast entry to be\r
+ * cleared before the SA interaction completes. In this case, when the\r
+ * mcast callback is invoked, it would not find the corresponding endpoint\r
+ * and would be undone.\r
+ */\r
+ p_endpt = ipoib_endpt_create(\r
+ &mcast_req.member_rec.mgid, 0, CL_HTON32(0x00FFFFFF) );\r
+ if( !p_endpt )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ipoib_endpt_create failed.\n") );\r
+ return IB_INSUFFICIENT_MEMORY;\r
+ }\r
+\r
+ status = __endpt_mgr_insert_locked( p_port, mac, p_endpt );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("__endpt_mgr_insert_locked returned %s\n", \r
+ p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+ return status;\r
+ }\r
+\r
+ /* reference the object for the multicast join request. */\r
+ ipoib_port_ref( p_port, ref_join_mcast );\r
+\r
+ status = p_port->p_adapter->p_ifc->join_mcast( p_port->ib_mgr.h_qp, &mcast_req );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ ipoib_port_deref( p_port, ref_mcast_join_failed );\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("ib_join_mcast returned %s\n", \r
+ p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+ }\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_MCAST );\r
+ return status;\r
+}\r
+\r
+\r
+static void\r
+__mcast_cb(\r
+ IN ib_mcast_rec_t *p_mcast_rec )\r
+{\r
+ ib_api_status_t status;\r
+ ipoib_port_t *p_port;\r
+ cl_fmap_item_t *p_item;\r
+ ipoib_endpt_t *p_endpt;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_MCAST );\r
+\r
+ p_port = (ipoib_port_t*)p_mcast_rec->mcast_context;\r
+\r
+ cl_obj_lock( &p_port->obj );\r
+ while( p_port->endpt_rdr )\r
+ {\r
+ cl_obj_unlock( &p_port->obj );\r
+ cl_obj_lock( &p_port->obj );\r
+ }\r
+ if( p_port->state != IB_QPS_RTS )\r
+ {\r
+ cl_obj_unlock( &p_port->obj );\r
+ if( p_mcast_rec->status == IB_SUCCESS )\r
+\r
+ {\r
+ ipoib_port_ref(p_port, ref_leave_mcast);\r
+ p_port->p_adapter->p_ifc->leave_mcast( p_mcast_rec->h_mcast, __leave_error_mcast_cb );\r
+ }\r
+ ipoib_port_deref( p_port, ref_mcast_inv_state );\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+ ("Invalid state - Aborting.\n") );\r
+ return;\r
+ }\r
+\r
+ if( p_mcast_rec->status != IB_SUCCESS )\r
+ {\r
+ cl_obj_unlock( &p_port->obj );\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Multicast join request failed with status %s.\n",\r
+ p_port->p_adapter->p_ifc->get_err_str( p_mcast_rec->status )) );\r
+ /* Flag the adapter as hung. */\r
+ p_port->p_adapter->hung =TRUE;\r
+ ipoib_port_deref( p_port, ref_mcast_req_failed );\r
+ IPOIB_EXIT( IPOIB_DBG_MCAST );\r
+ return;\r
+ }\r
+\r
+ p_item = cl_fmap_get(\r
+ &p_port->endpt_mgr.gid_endpts, &p_mcast_rec->p_member_rec->mgid );\r
+ if( p_item == cl_fmap_end( &p_port->endpt_mgr.gid_endpts ) )\r
+ {\r
+ /*\r
+ * The endpoint must have been flushed while the join request\r
+ * was outstanding. Just leave the group and return. This\r
+ * is not an error.\r
+ */\r
+ cl_obj_unlock( &p_port->obj );\r
+ IPOIB_PRINT(TRACE_LEVEL_WARNING, IPOIB_DBG_ERROR,\r
+ ("Failed to find endpoint for update.\n") );\r
+\r
+ ipoib_port_ref(p_port, ref_leave_mcast);\r
+ p_port->p_adapter->p_ifc->leave_mcast( p_mcast_rec->h_mcast, __leave_error_mcast_cb );\r
+ ipoib_port_deref( p_port, ref_mcast_no_endpt );\r
+ IPOIB_EXIT( IPOIB_DBG_MCAST );\r
+ return;\r
+ }\r
+\r
+ p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, gid_item );\r
+ p_endpt->p_ifc = p_port->p_adapter->p_ifc;\r
+\r
+ /* Setup the endpoint for use. */\r
+ status = ipoib_endpt_set_mcast(\r
+ p_endpt, p_port->ib_mgr.h_pd, p_port->port_num, p_mcast_rec );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ cl_obj_unlock( &p_port->obj );\r
+ IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_MCAST,\r
+ ("ipoib_endpt_set_mcast returned %s.\n",\r
+ p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+ /* Flag the adapter as hung. */\r
+ p_port->p_adapter->hung = TRUE;\r
+ ipoib_port_deref( p_port, ref_mcast_av_failed );\r
+ IPOIB_EXIT( IPOIB_DBG_MCAST );\r
+ return;\r
+ }\r
+\r
+ /*\r
+ * The endpoint is already in the GID and MAC maps.\r
+ * mast endpoint are not used in the LID map.\r
+ */\r
+ CL_ASSERT(p_endpt->dlid == 0);\r
+ /* set flag that endpoint is use */\r
+ p_endpt->is_in_use = TRUE;\r
+ cl_obj_unlock( &p_port->obj );\r
+ \r
+ /* Try to send all pending sends. */\r
+ ipoib_port_resume( p_port , FALSE);\r
+\r
+ ipoib_port_deref( p_port, ref_join_mcast );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_MCAST );\r
+}\r
+\r
+\r
+void\r
+ipoib_leave_mcast_cb(\r
+ IN void *context )\r
+{\r
+ ipoib_port_t *p_port;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_MCAST );\r
+\r
+ p_port = (ipoib_port_t*)context;\r
+\r
+ IPOIB_PRINT( TRACE_LEVEL_VERBOSE, IPOIB_DBG_MCAST,("p_port->mcast_cnt = %d\n", p_port->mcast_cnt));\r
+ \r
+ ipoib_port_deref( p_port, ref_leave_mcast);\r
+ cl_atomic_dec( &p_port->mcast_cnt);\r
+ \r
+ if(0 == p_port->mcast_cnt)\r
+ {\r
+ KeSetEvent( &p_port->leave_mcast_event, EVENT_INCREMENT, FALSE );\r
+ }\r
+ \r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_MCAST,\r
+ ("Leave mcast callback deref ipoib_port \n") );\r
+ \r
+ IPOIB_EXIT( IPOIB_DBG_MCAST );\r
+}\r
+\r
+\r
+\r
+void\r
+__leave_error_mcast_cb(\r
+ IN void *context )\r
+{\r
+ ipoib_port_t *p_port;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_MCAST );\r
+\r
+ p_port = (ipoib_port_t*)context;\r
+\r
+ ipoib_port_deref( p_port, ref_leave_mcast);\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_MCAST,\r
+ ("Leave mcast callback deref ipoib_port \n") );\r
+ \r
+ IPOIB_EXIT( IPOIB_DBG_MCAST );\r
+}\r
+\r
+/*++\r
+Routine Description:\r
+ The routine process the packet and returns LSO information\r
+ \r
+Arguments:\r
+ pNetBuffer - a pointer to the first net buffer object of the packet\r
+ TcpHeaderOffset - offset to the begining of the TCP header in the packet\r
+ pLsoData - pointer to LsoData object in which the routine returns the LSO information\r
+ pHeaderSize - pointer to ULONG object in which the header size is returned\r
+ IndexOfData - \r
+ \r
+Return Value:\r
+ NDIS_STATUS \r
+\r
+NOTE:\r
+ called at DISPATCH level\r
+--*/\r
+\r
+NDIS_STATUS GetLsoHeaderSize(\r
+ IN PNET_BUFFER pNetBuffer,\r
+ IN LsoData *pLsoData,\r
+ OUT UINT *IndexOfData,\r
+ IN ipoib_hdr_t *ipoib_hdr\r
+ )\r
+{\r
+ UINT CurrLength;\r
+ PUCHAR pSrc;\r
+ PUCHAR pCopiedData = pLsoData->coppied_data;\r
+ ip_hdr_t UNALIGNED *IpHdr;\r
+ tcp_hdr_t UNALIGNED *TcpHdr;\r
+ uint16_t TcpHeaderLen;\r
+ uint16_t IpHeaderLen;\r
+ uint16_t IpOffset;\r
+ INT FullBuffers = 0;\r
+ PMDL pMDL;\r
+ NDIS_STATUS status = NDIS_STATUS_INVALID_PACKET;\r
+ \r
+ \r
+#define IP_OFFSET 14;\r
+ //\r
+ // This Flag indicates the way we gets the headers\r
+ // RegularFlow = we get the headers (ETH+IP+TCP) in the same Buffer \r
+ // in sequence.\r
+ //\r
+ boolean_t IsRegularFlow = TRUE;\r
+\r
+ const uint16_t ETH_OFFSET = IP_OFFSET; \r
+ \r
+ pLsoData->LsoHeaderSize = 0;\r
+ IpOffset = IP_OFFSET; //(uint16_t)pPort->EncapsulationFormat.EncapsulationHeaderSize;\r
+ *IndexOfData = 0;\r
+\r
+ pMDL = NET_BUFFER_CURRENT_MDL(pNetBuffer);\r
+ NdisQueryMdl(pMDL, &pSrc, &CurrLength, NormalPagePriority);\r
+ //NdisQueryBufferSafe( CurrBuffer, &pSrc, &CurrLength, NormalPagePriority );\r
+ if (pSrc == NULL) {\r
+ IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, ("Error processing packets\n"));\r
+ return status;\r
+ }\r
+ // We start by looking for the ethernet and the IP\r
+ if (CurrLength < ETH_OFFSET) {\r
+ IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, ("Error porcessing packets\n"));\r
+ return status;\r
+ }\r
+ //pLsoData->LsoHeaderSize = pLsoData->LsoHeaderSize + ETH_OFFSET;\r
+ if (CurrLength == ETH_OFFSET) { \r
+ ASSERT(FALSE);\r
+ IsRegularFlow = FALSE; \r
+ memcpy(pCopiedData, pSrc, ETH_OFFSET);\r
+ pCopiedData += ETH_OFFSET; \r
+ FullBuffers++;\r
+ // First buffer was only ethernet\r
+ pNetBuffer = NET_BUFFER_NEXT_NB(pNetBuffer);\r
+ NdisQueryMdl(NET_BUFFER_CURRENT_MDL(pNetBuffer), &pSrc, &CurrLength, NormalPagePriority);\r
+ if (pSrc == NULL) {\r
+ IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, ("Error porcessing packets\n"));\r
+ return status;\r
+ }\r
+ } else {\r
+ // This is ETH + IP together (at least)\r
+ pLsoData->LsoBuffers[0].pData = pSrc + (ETH_OFFSET - sizeof (ipoib_hdr_t));\r
+ memcpy (pLsoData->LsoBuffers[0].pData, ipoib_hdr, sizeof (ipoib_hdr_t));\r
+ CurrLength -= ETH_OFFSET;\r
+ pSrc = pSrc + ETH_OFFSET;\r
+ pLsoData->LsoHeaderSize = pLsoData->LsoHeaderSize + sizeof (ipoib_hdr_t);\r
+ }\r
+ // we should now be having at least the size of ethernet data\r
+ if (CurrLength < sizeof (ip_hdr_t)) {\r
+ IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, ("Error porcessing packets\n"));\r
+ return status;\r
+ }\r
+ IpHdr = (ip_hdr_t UNALIGNED*)pSrc;\r
+ IpHeaderLen = (uint16_t)IP_HEADER_LENGTH(IpHdr);\r
+ ASSERT(IpHdr->prot == IP_PROT_TCP);\r
+ if (CurrLength < IpHeaderLen) {\r
+ IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, ("Error processing packets\n"));\r
+ return status;\r
+ }\r
+ pLsoData->LsoHeaderSize = pLsoData->LsoHeaderSize + IpHeaderLen;\r
+ // We now start to find where the TCP header starts\r
+ if (CurrLength == IpHeaderLen) {\r
+ ASSERT(FALSE);\r
+ // two options : \r
+ // if(IsRegularFlow = FALSE) ==> ETH and IP seperated in two buffers\r
+ // if(IsRegularFlow = TRUE ) ==> ETH and IP in the same buffer \r
+ // TCP will start at next buffer\r
+ if(IsRegularFlow){\r
+ memcpy(pCopiedData, pSrc-ETH_OFFSET ,ETH_OFFSET+IpHeaderLen);\r
+ pCopiedData += (ETH_OFFSET + IpHeaderLen);\r
+ } else {\r
+ memcpy(pCopiedData, pSrc,IpHeaderLen);\r
+ pCopiedData += IpHeaderLen;\r
+ }\r
+\r
+ FullBuffers++;\r
+ IsRegularFlow = FALSE;\r
+ //NdisGetNextBuffer( CurrBuffer, &CurrBuffer);\r
+ //NdisQueryBufferSafe( CurrBuffer, &pSrc, &CurrLength, NormalPagePriority );\r
+ pNetBuffer = NET_BUFFER_NEXT_NB(pNetBuffer);\r
+ NdisQueryMdl(NET_BUFFER_CURRENT_MDL(pNetBuffer), &pSrc, &CurrLength, NormalPagePriority);\r
+ if (pSrc == NULL) {\r
+ IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, ("Error porcessing packets\n"));\r
+ return status;\r
+ }\r
+ } else {\r
+ // if(IsRegularFlow = TRUE ) ==> the ETH and IP and TCP in the same buffer \r
+ // if(IsRegularFlow = FLASE ) ==> ETH in one buffer , IP+TCP together in the same buffer\r
+ if (IsRegularFlow) { \r
+ pLsoData->LsoBuffers[0].Len += IpHeaderLen;\r
+ } else { \r
+ memcpy(pCopiedData, pSrc, IpHeaderLen);\r
+ pCopiedData += IpHeaderLen;\r
+ }\r
+\r
+ CurrLength -= IpHeaderLen;\r
+ pSrc = pSrc + IpHeaderLen;\r
+ }\r
+ if (CurrLength < sizeof (tcp_hdr_t)) {\r
+ IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, ("Error porcessing packets\n"));\r
+ return status;\r
+ }\r
+ // We have finaly found the TCP header\r
+ TcpHdr = (tcp_hdr_t UNALIGNED *)pSrc;\r
+ TcpHeaderLen = TCP_HEADER_LENGTH(TcpHdr);\r
+\r
+ //ASSERT(TcpHeaderLen == 20);\r
+ \r
+ if (CurrLength < TcpHeaderLen) {\r
+ //IPOIB_PRINT(TRACE_LEVEL_VERBOSE, ETH, ("Error porcessing packets\n"));\r
+ return status;\r
+ }\r
+ pLsoData->LsoHeaderSize = pLsoData->LsoHeaderSize + TcpHeaderLen;\r
+ if(IsRegularFlow){\r
+ pLsoData->LsoBuffers[0].Len += TcpHeaderLen;\r
+ }\r
+ else{\r
+ memcpy(pCopiedData, pSrc, TcpHeaderLen);\r
+ pCopiedData += TcpHeaderLen;\r
+ }\r
+ if (CurrLength == TcpHeaderLen) {\r
+ FullBuffers++;\r
+ pLsoData->UsedBuffers = FullBuffers;\r
+ *IndexOfData = FullBuffers ;\r
+ } else {\r
+ pLsoData->UsedBuffers = FullBuffers + 1;\r
+ *IndexOfData = FullBuffers - 1;\r
+ }\r
+ pLsoData->FullBuffers = FullBuffers; \r
+ if (!IsRegularFlow){\r
+ pLsoData->LsoBuffers[0].pData = pLsoData->coppied_data;\r
+ pLsoData->LsoBuffers[0].Len = ETH_OFFSET + IpHeaderLen + TcpHeaderLen;\r
+ ASSERT(pLsoData->LsoBuffers[0].Len <= LSO_MAX_HEADER);\r
+ }\r
+ return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+static void __port_do_mcast_garbage(ipoib_port_t* const p_port)\r
+{\r
+ const mac_addr_t DEFAULT_MCAST_GROUP = {0x01, 0x00, 0x5E, 0x00, 0x00, 0x01};\r
+ /* Do garbage collecting... */\r
+\r
+ cl_map_item_t *p_item;\r
+ ipoib_endpt_t *p_endpt;\r
+ cl_qlist_t destroy_mc_list;\r
+ uint8_t cnt;\r
+ const static GC_MAX_LEAVE_NUM = 80;\r
+\r
+ cl_qlist_init( &destroy_mc_list );\r
+\r
+ cl_obj_lock( &p_port->obj );\r
+ /* Wait for all readers to finish */\r
+ while( p_port->endpt_rdr )\r
+ {\r
+ cl_obj_unlock( &p_port->obj );\r
+ cl_obj_lock( &p_port->obj );\r
+ }\r
+ cnt = 0;\r
+ p_item = cl_qmap_head( &p_port->endpt_mgr.mac_endpts );\r
+ while( (p_item != cl_qmap_end( &p_port->endpt_mgr.mac_endpts )) && (cnt < GC_MAX_LEAVE_NUM))\r
+ {\r
+ p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item );\r
+ p_item = cl_qmap_next( p_item );\r
+\r
+ /* Check if the current endpoint is not a multicast listener */\r
+\r
+ if( p_endpt->h_mcast && \r
+ (!p_endpt->is_mcast_listener) &&\r
+ ( cl_memcmp( &p_endpt->mac, &DEFAULT_MCAST_GROUP, sizeof(mac_addr_t) ) &&\r
+ (!p_endpt->is_in_use) ))\r
+ {\r
+ cl_qmap_remove_item( &p_port->endpt_mgr.mac_endpts,\r
+ &p_endpt->mac_item );\r
+ cl_fmap_remove_item( &p_port->endpt_mgr.gid_endpts,\r
+ &p_endpt->gid_item );\r
+\r
+ if( p_endpt->dlid )\r
+ {\r
+ cl_qmap_remove_item( &p_port->endpt_mgr.lid_endpts,\r
+ &p_endpt->lid_item );\r
+ p_endpt->dlid = 0;\r
+ }\r
+\r
+ cl_qlist_insert_tail(\r
+ &destroy_mc_list, &p_endpt->mac_item.pool_item.list_item );\r
+ cnt++;\r
+ }\r
+ else\r
+ p_endpt->is_in_use = FALSE;\r
+ }\r
+ cl_obj_unlock( &p_port->obj );\r
+\r
+ /* Destroy all multicast endpoints now that we have released the lock. */\r
+ while( cl_qlist_count( &destroy_mc_list ) )\r
+ {\r
+ p_endpt = PARENT_STRUCT( cl_qlist_remove_head( &destroy_mc_list ),\r
+ ipoib_endpt_t, mac_item.pool_item.list_item );\r
+ IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
+ ("mcast garbage collector: destroying endpoint %02x:%02x:%02x:%02x:%02x:%02x \n", \r
+ p_endpt->mac.addr[0],\r
+ p_endpt->mac.addr[1],\r
+ p_endpt->mac.addr[2],\r
+ p_endpt->mac.addr[3],\r
+ p_endpt->mac.addr[4],\r
+ p_endpt->mac.addr[5]) );\r
+ cl_obj_destroy( &p_endpt->obj );\r
+ }\r
+}\r
+\r
+static void __port_mcast_garbage_dpc(KDPC *p_gc_dpc,void *context,void *s_arg1, void *s_arg2)\r
+{\r
+ ipoib_port_t *p_port = (ipoib_port_t *) context;\r
+\r
+ UNREFERENCED_PARAMETER(p_gc_dpc);\r
+ UNREFERENCED_PARAMETER(s_arg1);\r
+ UNREFERENCED_PARAMETER(s_arg2);\r
+\r
+ __port_do_mcast_garbage(p_port);\r
+}\r
+\r
+ipoib_endpt_t*\r
+ipoib_endpt_get_by_gid(\r
+ IN ipoib_port_t* const p_port,\r
+ IN const ib_gid_t* const p_gid )\r
+{\r
+ return __endpt_mgr_get_by_gid( p_port, p_gid );\r
+}\r
+\r
+ipoib_endpt_t*\r
+ipoib_endpt_get_by_lid(\r
+ IN ipoib_port_t* const p_port,\r
+ IN const net16_t lid )\r
+{\r
+ return __endpt_mgr_get_by_lid( p_port, lid );\r
+}\r
+\r
+ib_api_status_t\r
+ipoib_recv_dhcp(\r
+ IN ipoib_port_t* const p_port,\r
+ IN const ipoib_pkt_t* const p_ipoib,\r
+ OUT eth_pkt_t* const p_eth,\r
+ IN ipoib_endpt_t* const p_src,\r
+ IN ipoib_endpt_t* const p_dst )\r
+{\r
+ return __recv_dhcp(\r
+ p_port, p_ipoib, p_eth, p_src,p_dst );\r
+}\r
+\r
+\r
+void\r
+ipoib_port_cancel_xmit(\r
+ IN ipoib_port_t* const p_port,\r
+ IN PVOID cancel_id )\r
+{\r
+ cl_list_item_t *p_item;\r
+ PNET_BUFFER_LIST p_nbl;\r
+ PVOID nbl_id;\r
+ cl_qlist_t cancel_list;\r
+ ULONG send_complete_flags = 0;\r
+ IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+ cl_qlist_init( &cancel_list );\r
+\r
+ cl_spinlock_acquire( &p_port->send_lock );\r
+\r
+ for( p_item = cl_qlist_head( &p_port->send_mgr.pending_list );\r
+ p_item != cl_qlist_end( &p_port->send_mgr.pending_list );\r
+ p_item = cl_qlist_next( p_item ) )\r
+ {\r
+ p_nbl = IPOIB_PACKET_FROM_LIST_ITEM( p_item );\r
+ nbl_id = NDIS_GET_NET_BUFFER_LIST_CANCEL_ID( p_nbl );\r
+ if( nbl_id == cancel_id )\r
+ {\r
+ cl_qlist_remove_item( &p_port->send_mgr.pending_list, p_item );\r
+ NET_BUFFER_LIST_STATUS( p_nbl) = NDIS_STATUS_REQUEST_ABORTED ;\r
+ cl_qlist_insert_tail( &cancel_list, IPOIB_LIST_ITEM_FROM_PACKET( p_nbl ) );\r
+ }\r
+ }\r
+ cl_spinlock_release( &p_port->send_lock );\r
+\r
+ if( cl_qlist_count( &cancel_list ) )\r
+ {\r
+ while( ( p_item = cl_qlist_remove_head( &cancel_list )) \r
+ != cl_qlist_end( &cancel_list ))\r
+ {\r
+ p_nbl = IPOIB_PACKET_FROM_LIST_ITEM( p_item );\r
+ NET_BUFFER_LIST_STATUS( p_nbl) = NDIS_STATUS_SEND_ABORTED;\r
+ send_complete_flags = 0;\r
+ if (NDIS_CURRENT_IRQL() == DISPATCH_LEVEL)\r
+ {\r
+ NDIS_SET_SEND_COMPLETE_FLAG(send_complete_flags, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL);\r
+ }\r
+ NdisMSendNetBufferListsComplete( p_port->p_adapter->h_adapter,\r
+ p_nbl, send_complete_flags );\r
+ }\r
+ }\r
+ IPOIB_EXIT( IPOIB_DBG_SEND );\r
+}\r
+\r
+/* \r
+* Put all fragments into separate WR and chain together.\r
+* The last WR will be set to generate CQ Event.\r
+* lookaside buffer is used for ipoib and ip headers attached to each WR.\r
+* Buffer will be released on last WR send completion.\r
+*/\r
+#if 0\r
+static NDIS_STATUS\r
+__send_fragments(\r
+IN ipoib_port_t* const p_port,\r
+IN ipoib_send_desc_t* const p_desc,\r
+IN eth_hdr_t* const p_eth_hdr,\r
+IN ip_hdr_t* const p_ip_hdr,\r
+IN uint32_t buf_len,\r
+IN NDIS_BUFFER* p_ndis_buf )\r
+{\r
+ uint32_t ds_idx = 1;\r
+ uint32_t wr_idx = 0;\r
+ uint32_t sgl_idx = 2; //skip eth hdr, ip hdr\r
+ uint32_t options_len = 0;\r
+ uint8_t* p_options = NULL;\r
+ uint8_t* p_buf;\r
+ uint32_t frag_offset = 0;\r
+ uint32_t next_sge;\r
+ uint32_t wr_size = 0;\r
+ uint32_t ip_hdr_len = IP_HEADER_LENGTH( p_ip_hdr );\r
+ uint32_t total_ip_len = cl_ntoh16( p_ip_hdr->length );\r
+\r
+ SCATTER_GATHER_LIST *p_sgl;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+ if( IP_DONT_FRAGMENT(p_ip_hdr) )\r
+ return NDIS_STATUS_INVALID_PACKET;\r
+ \r
+ p_sgl = NDIS_PER_PACKET_INFO_FROM_PACKET( p_desc->p_pkt, ScatterGatherListPacketInfo );\r
+ if( !p_sgl )\r
+ {\r
+ ASSERT( p_sgl );\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed to get SGL from packet.\n") );\r
+ return NDIS_STATUS_FAILURE;\r
+ }\r
+ if( ( p_sgl->NumberOfElements > MAX_SEND_SGE ||\r
+ p_sgl->Elements[0].Length < sizeof(eth_hdr_t)) )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Too many SG Elements in packet.\n") );\r
+ return NDIS_STATUS_FAILURE;\r
+ }\r
+ p_buf = (uint8_t *)\r
+ ExAllocateFromNPagedLookasideList( &p_port->buf_mgr.send_buf_list );\r
+ if( !p_buf )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed to allocate lookaside buffer.\n") );\r
+ return NDIS_STATUS_RESOURCES;\r
+ }\r
+ p_desc->p_buf = (send_buf_t*)p_buf;\r
+\r
+ if( buf_len < ip_hdr_len )\r
+ { /* ip options in a separate buffer */\r
+ CL_ASSERT( buf_len == sizeof( ip_hdr_t ) );\r
+ NdisGetNextBuffer( p_ndis_buf, &p_ndis_buf );\r
+ if( !p_ndis_buf )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed to get IP options buffer.\n") );\r
+ return NDIS_STATUS_FAILURE;\r
+ }\r
+ NdisQueryBufferSafe( p_ndis_buf, &p_options, &options_len, NormalPagePriority );\r
+ if( !p_options )\r
+ {\r
+ IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+ ("Failed to query IP options buffer address.\n") );\r
+ return NDIS_STATUS_FAILURE;\r
+ }\r
+ cl_memcpy( p_buf, p_ip_hdr, sizeof( ip_hdr_t ) );\r
+ if( p_options && options_len )\r
+ { \r
+ __copy_ip_options( &p_buf[sizeof(ip_hdr_t)], \r
+ p_options, options_len, TRUE );\r
+ }\r
+ wr_size = buf_len + options_len;\r
+ sgl_idx++;\r
+ }\r
+ else\r
+ { /*options probably in the same buffer */\r
+ cl_memcpy( p_buf, p_ip_hdr, buf_len );\r
+ options_len = ip_hdr_len - sizeof( ip_hdr_t );\r
+ if( options_len )\r
+ {\r
+ p_options = p_buf + sizeof( ip_hdr_t );\r
+ }\r
+ frag_offset += ( buf_len - ip_hdr_len );\r
+ wr_size = buf_len;\r
+ }\r
+\r
+ p_desc->send_wr[wr_idx].local_ds[ds_idx].vaddr = cl_get_physaddr( p_buf );\r
+ p_desc->send_wr[wr_idx].local_ds[ds_idx].lkey = p_port->ib_mgr.lkey;\r
+ p_desc->send_wr[wr_idx].local_ds[ds_idx].length = wr_size;\r
+ \r
+ /* count how much data can be put into the first WR beside IP header.\r
+ * other protocols headers possibly supplied in subsequent buffers.\r
+ */\r
+ for( sgl_idx; sgl_idx < p_sgl->NumberOfElements; sgl_idx++ )\r
+ {\r
+ next_sge = p_sgl->Elements[sgl_idx].Length;\r
+\r
+ /* add sgl if it can fit into the same WR \r
+ * Note: so far not going to split large SGE between WRs,\r
+ * so first fragment could be a smaller size.\r
+ */\r
+ if( next_sge <= ( p_port->p_adapter->params.payload_mtu - wr_size ) )\r
+ {\r
+ ++ds_idx;\r
+ wr_size += next_sge;\r
+ frag_offset += next_sge;\r
+ p_desc->send_wr[wr_idx].local_ds[ds_idx].vaddr = \r
+ p_sgl->Elements[sgl_idx].Address.QuadPart;\r
+ p_desc->send_wr[wr_idx].local_ds[ds_idx].length = next_sge;\r
+ p_desc->send_wr[wr_idx].local_ds[ds_idx].lkey = p_port->ib_mgr.lkey;\r
+ }\r
+ else\r
+ {\r
+ /* fix ip hdr for the first fragment and move on */\r
+ __update_fragment_ip_hdr( (ip_hdr_t* const)p_buf,\r
+ (uint16_t)wr_size, IP_FRAGMENT_OFFSET(p_ip_hdr), TRUE );\r
+\r
+ p_desc->send_wr[wr_idx].wr.num_ds = ds_idx + 1;\r
+ p_buf += ip_hdr_len;\r
+ p_buf += (( buf_len > ip_hdr_len ) ? ( buf_len - ip_hdr_len ): 0);\r
+ frag_offset += ( (IP_FRAGMENT_OFFSET(p_ip_hdr)) << 3 );\r
+ ++wr_idx;\r
+ ds_idx = 0;\r
+ break;\r
+ }\r
+ }\r
+ total_ip_len -= wr_size;\r
+ wr_size = 0;\r
+\r
+ for( sgl_idx, wr_idx; sgl_idx < p_sgl->NumberOfElements; sgl_idx++ )\r
+ {\r
+ uint32_t seg_len;\r
+ uint64_t next_sgl_addr;\r
+ \r
+ if( wr_idx >= ( MAX_WRS_PER_MSG - 1 ) )\r
+ return NDIS_STATUS_RESOURCES;\r
+ \r
+ next_sge = p_sgl->Elements[sgl_idx].Length;\r
+ next_sgl_addr = p_sgl->Elements[sgl_idx].Address.QuadPart;\r
+\r
+ while( next_sge )\r
+ {\r
+ if( ds_idx == 0 )\r
+ { /* new ipoib + ip header */\r
+ ((ipoib_hdr_t*)p_buf)->type = p_eth_hdr->type;\r
+ ((ipoib_hdr_t*)p_buf)->resv = 0;\r
+ p_desc->send_wr[wr_idx].local_ds[ds_idx].vaddr = cl_get_physaddr( p_buf );\r
+ p_desc->send_wr[wr_idx].local_ds[ds_idx].lkey = p_port->ib_mgr.lkey;\r
+ p_desc->send_wr[wr_idx].local_ds[ds_idx].length = sizeof( ipoib_hdr_t );\r
+ p_buf += sizeof( ipoib_hdr_t );\r
+ ++ds_idx;\r
+\r
+ cl_memcpy( p_buf, p_ip_hdr, sizeof( ip_hdr_t ) );\r
+ if( p_options && options_len )\r
+ {\r
+ /* copy ip options if needed */\r
+ __copy_ip_options( &p_buf[sizeof(ip_hdr_t)], \r
+ p_options, options_len, FALSE );\r
+ }\r
+ wr_size = ip_hdr_len;\r
+ }\r
+ if( ds_idx == 1 )\r
+ {\r
+ p_desc->send_wr[wr_idx].local_ds[ds_idx].length = ip_hdr_len;\r
+ p_desc->send_wr[wr_idx].local_ds[ds_idx].vaddr = cl_get_physaddr( p_buf );\r
+ p_desc->send_wr[wr_idx].local_ds[ds_idx].lkey = p_port->ib_mgr.lkey;\r
+ ++ds_idx;\r
+ }\r
+\r
+ seg_len = ( next_sge > ( p_port->p_adapter->params.payload_mtu - wr_size ) )?\r
+ ( p_port->p_adapter->params.payload_mtu - wr_size ) : next_sge;\r
+\r
+ p_desc->send_wr[wr_idx].local_ds[ds_idx].vaddr = next_sgl_addr;\r
+ p_desc->send_wr[wr_idx].local_ds[ds_idx].length = seg_len;\r
+ p_desc->send_wr[wr_idx].local_ds[ds_idx].lkey = p_port->ib_mgr.lkey;\r
+ ++ds_idx;\r
+ \r
+ wr_size += seg_len;\r
+ total_ip_len -= seg_len;\r
+\r
+ if( wr_size >= p_port->p_adapter->params.payload_mtu || total_ip_len == 0 )\r
+ { /* fix ip hdr for that fragment */\r
+ __update_fragment_ip_hdr( (ip_hdr_t* const)p_buf, (uint16_t)wr_size,\r
+ ((uint16_t)(frag_offset >> 3 )), \r
+ (BOOLEAN)(( total_ip_len > 0 ) || IP_MORE_FRAGMENTS( p_ip_hdr)) );\r
+ p_desc->send_wr[wr_idx].wr.num_ds = ds_idx;\r
+ if( total_ip_len > 0 )\r
+ {\r
+ ++wr_idx;\r
+ frag_offset += (wr_size - ip_hdr_len);\r
+ wr_size = 0;\r
+ ds_idx = 0;\r
+ p_buf += ip_hdr_len;\r
+ }\r
+ }\r
+ next_sge -= seg_len;\r
+ if( next_sge > 0 )\r
+ {\r
+ next_sgl_addr += seg_len;\r
+ }\r
+ }\r
+ }\r
+ p_desc->num_wrs += wr_idx;\r
+ \r
+ IPOIB_EXIT( IPOIB_DBG_SEND );\r
+ return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static void\r
+__update_fragment_ip_hdr(\r
+IN ip_hdr_t* const p_ip_hdr,\r
+IN uint16_t fragment_size, \r
+IN uint16_t fragment_offset, \r
+IN BOOLEAN more_fragments )\r
+{\r
+ uint16_t* p_hdr = (uint16_t*)p_ip_hdr;\r
+ p_ip_hdr->length = cl_hton16( fragment_size ); // bytes\r
+ p_ip_hdr->offset = cl_hton16( fragment_offset ); // 8-byte units\r
+ if( more_fragments )\r
+ {\r
+ IP_SET_MORE_FRAGMENTS( p_ip_hdr );\r
+ }\r
+ else\r
+ {\r
+ IP_SET_LAST_FRAGMENT( p_ip_hdr );\r
+ }\r
+ p_ip_hdr->chksum = 0;\r
+ p_ip_hdr->chksum = ipchksum( p_hdr, IP_HEADER_LENGTH(p_ip_hdr) );\r
+}\r
+\r
+static void\r
+__copy_ip_options(\r
+IN uint8_t* p_buf,\r
+IN uint8_t* p_options,\r
+IN uint32_t options_len,\r
+IN BOOLEAN copy_all )\r
+{\r
+ uint32_t option_length;\r
+ uint32_t total_length = 0;\r
+ uint32_t copied_length = 0;\r
+ uint8_t* p_src = p_options;\r
+ uint8_t* p_dst = p_buf;\r
+\r
+ if( p_options == NULL || options_len == 0 )\r
+ return;\r
+ if( copy_all )\r
+ {\r
+ cl_memcpy( p_dst, p_src, options_len );\r
+ return;\r
+ }\r
+ do\r
+ {\r
+ if( ( *p_src ) == 0 ) // end of options list\r
+ {\r
+ total_length++;\r
+ break;\r
+ }\r
+ if( ( *p_src ) == 0x1 ) // no op\r
+ {\r
+ p_src++;\r
+ total_length++;\r
+ continue;\r
+ }\r
+ /*from RFC791: \r
+ * This option may be used between options, for example, to align\r
+ * the beginning of a subsequent option on a 32 bit boundary.\r
+ */\r
+ if( copied_length && (copied_length % 4) )\r
+ {\r
+ uint32_t align = 4 - (copied_length % 4);\r
+ cl_memset( p_dst, 0x1, (size_t)align );\r
+ p_dst += align;\r
+ copied_length += align;\r
+ }\r
+ option_length = *(p_src + 1);\r
+\r
+ if( *p_src & 0x80 )\r
+ {\r
+ cl_memcpy( p_dst, p_src, option_length );\r
+ p_dst += option_length;\r
+ copied_length += option_length;\r
+ }\r
+ total_length += option_length;\r
+ p_src += option_length;\r
+\r
+ }while( total_length < options_len );\r
+\r
+ CL_ASSERT( total_length == options_len );\r
+ CL_ASSERT( copied_length <= 40 );\r
+\r
+ /* padding the rest */\r
+ if( options_len > copied_length )\r
+ {\r
+ cl_memclr( p_dst, ( options_len - copied_length ) );\r
+ }\r
+ return;\r
+}\r
+#endif\r
(((send_buf_t**)NET_BUFFER_MINIPORT_RESERVED(P))[2])\r
\r
\r
-#define IPOIB_GET_NET_BUFFER_LIST_REF_COUNT(_NetBufferList) ((_NetBufferList->FirstNetBuffer)->MiniportReserved[3])\r
-#define IPOIB_DEC_NET_BUFFER_LIST_REF_COUNT(_NetBufferList) (*(PULONG)&(_NetBufferList->FirstNetBuffer)->MiniportReserved[3])--\r
+#define IPOIB_GET_NET_BUFFER_LIST_REF_COUNT(_NetBufferList) ((NET_BUFFER_LIST_FIRST_NB(_NetBufferList))->MiniportReserved[3])\r
+#define IPOIB_DEC_NET_BUFFER_LIST_REF_COUNT(_NetBufferList) (*(PULONG)&(NET_BUFFER_LIST_FIRST_NB(_NetBufferList))->MiniportReserved[3])--\r
\r
\r
typedef struct _ipoib_ib_mgr\r
* Map of connected endpts, keyed by remote gid.\r
*********/\r
\r
-\r
+#pragma warning(disable:4324) // structure padded due to align()\r
typedef struct _ipoib_port\r
{\r
cl_obj_t obj;\r
ipoib_hdr_t hdr[1]; /* Must be last! */\r
\r
} ipoib_port_t;\r
+#pragma warning(default:4324)\r
+\r
/*\r
* FIELDS\r
* obj\r
+++ /dev/null
-/*\r
- * Copyright (c) 2008 Mellanox Technologies. All rights reserved.\r
- *\r
- * This software is available to you under the OpenIB.org BSD license\r
- * below:\r
- *\r
- * Redistribution and use in source and binary forms, with or\r
- * without modification, are permitted provided that the following\r
- * conditions are met:\r
- *\r
- * - Redistributions of source code must retain the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer.\r
- *\r
- * - Redistributions in binary form must reproduce the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer in the documentation and/or other materials\r
- * provided with the distribution.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- * SOFTWARE.\r
- *\r
- * $Id: ipoib_xfr_mgr.c 3459 2008-11-12 16:48:21Z tzachid $\r
- */\r
-\r
-\r
-#include "ipoib_xfr_mgr.h"\r
-#if defined(EVENT_TRACING)\r
-#ifdef offsetof\r
-#undef offsetof\r
-#endif\r
-#include "ipoib_xfr_mgr.tmh"\r
-#endif\r
-\r
-\r
-const ipoib_guid2mac_translation_t guid2mac_table[] = {\r
- {0x30, 0x48, 0xE7},\r
- {0x05, 0xAD, 0xE7},\r
- {0x18, 0x8B, 0xE7},\r
- {0x1A, 0x4B, 0xE7},\r
- {0x17, 0x08, 0xE7},\r
- {0x1E, 0x0B, 0xE7},\r
-\r
- {0x03, 0xBA, 0xE7},\r
- {0x05, 0xAD, 0xE7},\r
- {0x0D, 0x9D, 0xE7},\r
- {0x11, 0x0A, 0xE7},\r
- {0x11, 0x85, 0xE7},\r
- {0x12, 0x79, 0xE7},\r
- {0x13, 0x21, 0xE7},\r
- {0x14, 0x38, 0xE7},\r
- {0x16, 0x35, 0xE7},\r
- {0x17, 0x08, 0xE7},\r
- {0x17, 0xA4, 0xE7},\r
- {0x18, 0x8B, 0xE7},\r
- {0x18, 0xFE, 0xE7},\r
- {0x19, 0xBB, 0xE7},\r
- {0x1A, 0x4B, 0xE7},\r
- {0x1B, 0x78, 0xE7},\r
- {0x1E, 0x0B, 0xE7},\r
- {0x22, 0x64, 0xE7},\r
- {0x23, 0x7D, 0xE7},\r
- {0x30, 0x48, 0xE7},\r
- {0x80, 0x5F, 0xE7},\r
-\r
- {0x00, 0x00, 0x00},\r
-};\r
-\r
--- /dev/null
+/*\r
+ * Copyright (c) 2008 Mellanox Technologies. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ * - Redistributions of source code must retain the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer.\r
+ *\r
+ * - Redistributions in binary form must reproduce the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer in the documentation and/or other materials\r
+ * provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id: ipoib_xfr_mgr.c 3459 2008-11-12 16:48:21Z tzachid $\r
+ */\r
+\r
+\r
+#include "ipoib_xfr_mgr.h"\r
+#if defined(EVENT_TRACING)\r
+#ifdef offsetof\r
+#undef offsetof\r
+#endif\r
+#include "ipoib_xfr_mgr.tmh"\r
+#endif\r
+\r
+\r
+const ipoib_guid2mac_translation_t guid2mac_table[] = {\r
+ {0x30, 0x48, 0xE7},\r
+ {0x05, 0xAD, 0xE7},\r
+ {0x18, 0x8B, 0xE7},\r
+ {0x1A, 0x4B, 0xE7},\r
+ {0x17, 0x08, 0xE7},\r
+ {0x1E, 0x0B, 0xE7},\r
+\r
+ {0x03, 0xBA, 0xE7},\r
+ {0x05, 0xAD, 0xE7},\r
+ {0x0D, 0x9D, 0xE7},\r
+ {0x11, 0x0A, 0xE7},\r
+ {0x11, 0x85, 0xE7},\r
+ {0x12, 0x79, 0xE7},\r
+ {0x13, 0x21, 0xE7},\r
+ {0x14, 0x38, 0xE7},\r
+ {0x16, 0x35, 0xE7},\r
+ {0x17, 0x08, 0xE7},\r
+ {0x17, 0xA4, 0xE7},\r
+ {0x18, 0x8B, 0xE7},\r
+ {0x18, 0xFE, 0xE7},\r
+ {0x19, 0xBB, 0xE7},\r
+ {0x1A, 0x4B, 0xE7},\r
+ {0x1B, 0x78, 0xE7},\r
+ {0x1E, 0x0B, 0xE7},\r
+ {0x22, 0x64, 0xE7},\r
+ {0x23, 0x7D, 0xE7},\r
+ {0x30, 0x48, 0xE7},\r
+ {0x80, 0x5F, 0xE7},\r
+\r
+ {0x00, 0x00, 0x00},\r
+};\r
+\r