__destroying_ca(\r
IN struct _al_obj *p_obj );\r
\r
-void\r
-cleanup_ca(\r
+static void\r
+__cleanup_ca(\r
IN struct _al_obj *p_obj );\r
\r
-void\r
-free_ca(\r
+static void\r
+__free_ca(\r
IN struct _al_obj *p_obj );\r
\r
\r
h_ca->pfn_event_cb = pfn_ca_event_cb;\r
\r
status = init_al_obj( &h_ca->obj, ca_context, TRUE,\r
- __destroying_ca, cleanup_ca, free_ca );\r
+ NULL, __cleanup_ca, __free_ca );\r
if( status != IB_SUCCESS )\r
{\r
- free_ca( &h_ca->obj );\r
+ __free_ca( &h_ca->obj );\r
CL_EXIT( AL_DBG_CA, g_al_dbg_lvl );\r
return status;\r
}\r
}\r
\r
\r
+/*\r
+ * Release all resources associated with the CA.\r
+ */\r
static void\r
-__destroying_ca(\r
+__cleanup_ca(\r
IN struct _al_obj *p_obj )\r
{\r
#if defined(CL_KERNEL)\r
h_ca->obj.p_ci_ca->verbs.um_close_ca(\r
h_ca->obj.p_ci_ca->h_ci_ca, h_ca->h_um_ca );\r
}\r
-#else\r
- UNUSED_PARAM( p_obj );\r
#endif\r
-}\r
\r
-\r
-/*\r
- * Release all resources associated with the CA.\r
- */\r
-void\r
-cleanup_ca(\r
- IN struct _al_obj *p_obj )\r
-{\r
/* It is now safe to release the CI CA. */\r
if( p_obj->p_ci_ca )\r
release_ci_ca( PARENT_STRUCT( p_obj, ib_ca_t, obj ) );\r
\r
\r
\r
-void\r
-free_ca(\r
+static void\r
+__free_ca(\r
IN struct _al_obj *p_obj )\r
{\r
ib_ca_handle_t h_ca;\r
ib_api_status_t status;\r
ib_ca_attr_t *p_ca_attr;\r
uint32_t attr_size;\r
- uintn_t i;\r
+ uint8_t i;\r
\r
CL_ENTER( AL_DBG_CA, g_al_dbg_lvl );\r
\r
for( i = 0; i < p_ca_attr->num_ports; i++ )\r
{\r
p_ci_ca->port_array[i] = p_ca_attr->p_port_attr[i].port_guid;\r
+\r
+#ifdef CL_KERNEL\r
+ /* Set the port's client reregister bit. */\r
+ {\r
+ ib_port_attr_mod_t attr;\r
+\r
+ attr.cap.client_reregister = TRUE;\r
+ ib_modify_ca( p_ci_ca->h_ca, i + 1,\r
+ IB_CA_MOD_IS_CLIENT_REREGISTER_SUPPORTED, &attr );\r
+ }\r
+#endif\r
}\r
\r
cl_free( p_ca_attr );\r
\r
status = al_cep_rtu( h_cm_rep.h_al, h_cm_rep.cid,\r
p_cm_rtu->p_rtu_pdata, p_cm_rtu->rtu_length );\r
- if( status != IB_SUCCESS )\r
+ if( status != IB_SUCCESS && status != IB_INVALID_STATE )\r
{\r
err:\r
/* Reject and abort the connection. */\r
cid = cl_atomic_xchg(\r
&((al_conn_qp_t*)h_cm_rep.h_qp)->cid, AL_INVALID_CID );\r
\r
- CL_ASSERT( cid == h_cm_rep.cid );\r
-\r
- ref_al_obj( &h_cm_rep.h_qp->obj );\r
- if( al_destroy_cep(\r
- h_cm_rep.h_al, h_cm_rep.cid, deref_al_obj ) != IB_SUCCESS )\r
+ if( cid != AL_INVALID_CID )\r
{\r
- deref_al_obj( &h_cm_rep.h_qp->obj );\r
+ CL_ASSERT( cid == h_cm_rep.cid );\r
+\r
+ ref_al_obj( &h_cm_rep.h_qp->obj );\r
+ if( al_destroy_cep(\r
+ h_cm_rep.h_al, h_cm_rep.cid, deref_al_obj ) != IB_SUCCESS )\r
+ {\r
+ deref_al_obj( &h_cm_rep.h_qp->obj );\r
+ }\r
}\r
\r
AL_TRACE_EXIT( AL_DBG_ERROR,\r
* Since the MAD service is being destroyed, the user cannot be issuing\r
* sends.\r
*/\r
+ if( h_mad_svc->h_mad_reg )\r
+ {\r
#ifdef CL_KERNEL\r
- old_irql = KeRaiseIrqlToDpcLevel();\r
+ old_irql = KeRaiseIrqlToDpcLevel();\r
#endif\r
- __check_send_queue( h_mad_svc );\r
+ __check_send_queue( h_mad_svc );\r
#ifdef CL_KERNEL\r
- KeLowerIrql( old_irql );\r
+ KeLowerIrql( old_irql );\r
#endif\r
+ }\r
\r
cl_timer_destroy( &h_mad_svc->send_timer );\r
\r
CL_ASSERT( p_mad_response );\r
p_sa_mad = (ib_sa_mad_t*)p_mad_response->p_mad_buf;\r
\r
- query_rec.result_cnt =\r
- ( ( p_mad_response->size - IB_SA_MAD_HDR_SIZE ) /\r
- ib_get_attr_size( p_sa_mad->attr_offset ) );\r
+ if (ib_get_attr_size( p_sa_mad->attr_offset ) != 0)\r
+ {\r
+ query_rec.result_cnt =\r
+ ( ( p_mad_response->size - IB_SA_MAD_HDR_SIZE ) /\r
+ ib_get_attr_size( p_sa_mad->attr_offset ) );\r
+ }\r
+ else\r
+ {\r
+ query_rec.result_cnt = 0;\r
+ }\r
+\r
query_rec.p_result_mad = p_mad_response;\r
}\r
else\r
-; SilverStorm Technologies InfiniBand Bus Driver.\r
+; OpenIB InfiniBand Bus Driver.\r
; Copyright 2005 SilverStorm Technologies all Rights Reserved.\r
\r
[Version]\r
Signature="$Windows NT$"\r
Class=System\r
ClassGuid={4D36E97D-E325-11CE-BFC1-08002BE10318}\r
-Provider=%SST%\r
-CatalogFile=ibbus.cat\r
-DriverVer=09/01/2005,3.0.0036.0\r
+Provider=%OPENIB%\r
+DriverVer=01/12/2006,1.0.0000.213\r
\r
\r
; ================= Device Install section =====================\r
dapl32.dll=1\r
\r
[Manufacturer]\r
-%SST% = Ibbus.DeviceSection,ntx86,ntamd64,ntia64\r
+%OPENIB% = Ibbus.DeviceSection,ntx86,ntamd64,ntia64\r
\r
[Ibbus.DeviceSection]\r
; empty since we don't support W9x/Me\r
HKR,"Parameters","DebugFlags",%REG_DWORD%,0x80000000\r
\r
[Strings]\r
-SST = "SilverStorm Technologies"\r
+OPENIB = "OpenIB Alliance"\r
Ibbus.DeviceDesc = "InfiniBand Fabric"\r
VFx.DeviceDesc = "SilverStorm VFx"\r
VEx.DeviceDesc = "SilverStorm VEx"\r
Iou.DeviceDesc = "InfiniBand I/O Unit"\r
-Ibbus.ServiceDesc = "SilverStorm InfiniBand Bus Driver"\r
-Ibal.ServiceDesc = "SilverStorm InfiniBand Access Layer"\r
-Iou.ServiceDesc = "SilverStorm InfiniBand I/O Unit Driver"\r
-DiskId = "SilverStorm InfiniBand Access Layer installation disk"\r
+Ibbus.ServiceDesc = "OpenIB InfiniBand Bus Driver"\r
+Ibal.ServiceDesc = "OpenIB InfiniBand Access Layer"\r
+Iou.ServiceDesc = "OpenIB InfiniBand I/O Unit Driver"\r
+DiskId = "OpenIB InfiniBand Access Layer installation disk"\r
SPSVCINST_NULL = 0x0\r
SPSVCINST_ASSOCSERVICE = 0x00000002\r
SERVICE_KERNEL_DRIVER = 1\r
__cl_free_priv( gp_mem_tracker );\r
return;\r
}\r
-\r
- cl_msg_out( "\n\n\n*** Memory tracker object address = %p ***\n\n\n",\r
- gp_mem_tracker );\r
}\r
\r
\r
DIRS=\\r
- mt23108\r
+ mthca\r
#define IB_PORT_MPB_SHIFT 6\r
#define IB_PORT_LINK_SPEED_SHIFT 4\r
#define IB_PORT_LINK_SPEED_SUPPORTED_MASK 0xF0\r
-\r
+#define IB_PORT_LINK_SPEED_ACTIVE_MASK 0xF0\r
+#define IB_PORT_LINK_SPEED_ENABLED_MASK 0x0F\r
\r
#define IB_PORT_CAP_RESV0 (CL_NTOH32(0x00000001))\r
#define IB_PORT_CAP_IS_SM (CL_NTOH32(0x00000002))\r
* SEE ALSO\r
*********/\r
\r
+/****f* IBA Base: Types/ib_port_info_get_link_speed_active\r
+* NAME\r
+* ib_port_info_get_link_speed_active\r
+*\r
+* DESCRIPTION\r
+* Returns the Link Speed Active value assigned to this port.\r
+*\r
+* SYNOPSIS\r
+*/\r
+AL_INLINE uint8_t AL_API\r
+ib_port_info_get_link_speed_active(\r
+ IN const ib_port_info_t* const p_pi )\r
+{\r
+ return( (uint8_t)((p_pi->link_speed & IB_PORT_LINK_SPEED_ACTIVE_MASK) >>\r
+ IB_PORT_LINK_SPEED_SHIFT) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_pi\r
+* [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+* Returns the link speed active value assigned to this port.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+\r
#define IB_LINK_WIDTH_ACTIVE_1X 1\r
#define IB_LINK_WIDTH_ACTIVE_4X 2\r
#define IB_LINK_WIDTH_ACTIVE_12X 8\r
\r
+#define IB_LINK_SPEED_ACTIVE_2_5 1\r
+#define IB_LINK_SPEED_ACTIVE_5 2\r
+#define IB_LINK_SPEED_ACTIVE_10 4\r
+\r
#define IB_PATH_RECORD_RATE_2_5_GBS 2\r
#define IB_PATH_RECORD_RATE_10_GBS 3\r
#define IB_PATH_RECORD_RATE_30_GBS 4\r
+#define IB_PATH_RECORD_RATE_5_GBS 5\r
+#define IB_PATH_RECORD_RATE_20_GBS 6\r
+#define IB_PATH_RECORD_RATE_40_GBS 7\r
+#define IB_PATH_RECORD_RATE_60_GBS 8\r
+#define IB_PATH_RECORD_RATE_80_GBS 9\r
+#define IB_PATH_RECORD_RATE_120_GBS 10\r
+\r
\r
/****f* IBA Base: Types/ib_port_info_compute_rate\r
* NAME\r
*\r
* SYNOPSIS\r
*/\r
-\r
AL_INLINE uint8_t AL_API\r
ib_port_info_compute_rate(\r
IN const ib_port_info_t* const p_pi )\r
{\r
- switch(p_pi->link_width_active)\r
+ switch( p_pi->link_width_active * p_pi->link_width_active *\r
+ ib_port_info_get_link_speed_active( p_pi ) )\r
{\r
- case IB_LINK_WIDTH_ACTIVE_1X:\r
- return IB_PATH_RECORD_RATE_2_5_GBS;\r
+ case 1:\r
+ return IB_PATH_RECORD_RATE_2_5_GBS;\r
\r
- case IB_LINK_WIDTH_ACTIVE_4X:\r
- return IB_PATH_RECORD_RATE_10_GBS;\r
+ case 2:\r
+ return IB_PATH_RECORD_RATE_5_GBS;\r
\r
- case IB_LINK_WIDTH_ACTIVE_12X:\r
- return IB_PATH_RECORD_RATE_30_GBS;\r
+ case 4:\r
+ return IB_PATH_RECORD_RATE_10_GBS;\r
\r
- default:\r
- return IB_PATH_RECORD_RATE_2_5_GBS;\r
+ case 8:\r
+ return IB_PATH_RECORD_RATE_20_GBS;\r
+\r
+ case 16:\r
+ return IB_PATH_RECORD_RATE_40_GBS;\r
+\r
+ case 64:\r
+ return IB_PATH_RECORD_RATE_30_GBS;\r
+\r
+ case 128:\r
+ return IB_PATH_RECORD_RATE_60_GBS;\r
+\r
+ case 256:\r
+ return IB_PATH_RECORD_RATE_120_GBS;\r
+\r
+ default:\r
+ return IB_PATH_RECORD_RATE_2_5_GBS;\r
}\r
}\r
-\r
/*\r
* PARAMETERS\r
* p_pi\r
uint32_t vend_id;\r
uint16_t dev_id;\r
uint16_t revision;\r
+ uint64_t fw_ver;\r
\r
/*\r
* Total size of the ca attributes in bytes\r
* revision\r
* Revision ID of this adapter\r
*\r
+* fw_ver\r
+* Device Firmware version.\r
+*\r
* size\r
* Total size in bytes for the HCA attributes. This size includes total\r
* size required for all the variable members of the structure. If a\r
*********/\r
\r
\r
-#define IPOIB_INTERFACE_DATA_VERSION (4)\r
+#define IPOIB_INTERFACE_DATA_VERSION (5)\r
\r
\r
/* Interface definitions */\r
/* HCA and Port GUID */\r
net64_t ca_guid;\r
net64_t port_guid;\r
+ uint8_t port_num;\r
\r
} ipoib_ifc_data_t;\r
\r
#include <windows.h>\r
#include <ntverp.h>\r
\r
-#ifndef VER_FILEMAJORVERSION\r
-#define VER_FILEMAJORVERSION 1\r
-#endif\r
-\r
-#ifndef VER_FILEMINORVERSION\r
-#define VER_FILEMINORVERSION 0\r
-#endif\r
-\r
-#ifndef VER_FILEBUILD\r
-#define VER_FILEBUILD VER_OPENIB\r
-#endif\r
-\r
-#ifndef VER_FILEREV\r
-#define VER_FILEREV 0\r
-#endif\r
-\r
#if (VER_FILEBUILD < 10)\r
#define VER_FILEBPAD "000"\r
#elif (VER_FILEBUILD < 100)\r
#ifdef VER_COMPANYNAME_STR\r
#undef VER_COMPANYNAME_STR\r
#endif\r
-#define VER_COMPANYNAME_STR "OpenIB Alliance"\r
+#define VER_COMPANYNAME_STR IB_COMPANYNAME\r
\r
#ifdef VER_PRODUCTNAME_STR\r
#undef VER_PRODUCTNAME_STR\r
#endif\r
-#define VER_PRODUCTNAME_STR "OpenIB Windows"\r
+#define VER_PRODUCTNAME_STR IB_PRODUCTNAME\r
\r
#define VER_LEGALCOPYRIGHT_STR "Copyright\xa9 2005 OpenIB Alliance"\r
!INCLUDE $(NTMAKEENV)\makefile.def\r
\r
-C_DEFINES=$(C_DEFINES) -DVER_OPENIB="$(VER_OPENIB)"\r
+# Allow overriding the company name.\r
+!IF !DEFINED(IB_COMPANYNAME)\r
+IB_COMPANYNAME="""OpenIB\x20Alliance"""\r
+!ENDIF\r
+\r
+# Allow overriding the product name.\r
+!IF !DEFINED(IB_PRODUCTNAME)\r
+IB_PRODUCTNAME="""OpenIB\x20Windows"""\r
+!ENDIF\r
+\r
+!IF !DEFINED(IB_MAJORVERSION)\r
+IB_MAJORVERSION=1\r
+!endif\r
+\r
+!IF !DEFINED(IB_MINORVERSION)\r
+IB_MINORVERSION=0\r
+!endif\r
+\r
+!IF !DEFINED(IB_FILEBUILD)\r
+IB_FILEBUILD=0\r
+!endif\r
+\r
+!IF !DEFINED(IB_FILEREV)\r
+IB_FILEREV=$(OPENIB_REV)\r
+!endif\r
+\r
+C_DEFINES=$(C_DEFINES) -DIB_COMPANYNAME=$(IB_COMPANYNAME) \\r
+ -DIB_PRODUCTNAME=$(IB_PRODUCTNAME) \\r
+ -DVER_FILEMAJORVERSION=$(IB_MAJORVERSION) \\r
+ -DVER_FILEMINORVERSION=$(IB_MINORVERSION) \\r
+ -DVER_FILEBUILD=$(IB_FILEBUILD) \\r
+ -DVER_FILEREV=$(IB_FILEREV)\r
DIRS=\\r
alts \\r
cmtest \\r
- wsd\r
+ wsd \\r
+ ibat \\r
+ limits\r
#endif\r
\r
\r
+#define VEND_ID_MELLNOX 0x02c9\r
\r
\r
/*******************************************************************\r
if(fullPrint){\r
printf("\t\tmax_msg_sz=0x%x (Max message size)\n", portPtr->max_msg_size);\r
printf("\t\tcapability_mask=TBD\n");\r
- printf("\t\tmax_vl_num=0x%x (Maximum number of VL supported by this port)\n", portPtr->max_vls);\r
+ printf("\t\tmax_vl_num=0x%x (Maximum number of VL supported by this port)\n", portPtr->max_vls);\r
printf("\t\tbad_pkey_counter=0x%x (Bad PKey counter)\n", portPtr->pkey_ctr);\r
printf("\t\tqkey_viol_counter=0x%x (QKey violation counter)\n", portPtr->qkey_ctr);\r
- printf("\t\tsm_sl=0x%x (IB_SL to be used in communication with subnet manager)\n", portPtr->sm_sl);\r
+ printf("\t\tsm_sl=0x%x (IB_SL to be used in communication with subnet manager)\n", portPtr->sm_sl);\r
printf("\t\tpkey_tbl_len=0x%x (Current size of pkey table)\n", portPtr->num_pkeys);\r
printf("\t\tgid_tbl_len=0x%x (Current size of GID table)\n", portPtr->num_gids);\r
printf("\t\tsubnet_timeout=0x%x (Subnet Timeout for this port (see PortInfo))\n", portPtr->subnet_timeout);\r
\r
\r
\r
-void vstat_print_ca_attr(ib_ca_attr_t* ca_attr, BOOLEAN fullPrint){\r
+void vstat_print_ca_attr(int idx, ib_ca_attr_t* ca_attr, BOOLEAN fullPrint){\r
int i;\r
\r
- printf("\thca_id=%s\n", ca_attr->dev_id==0x5a44?"InfiniHost0":"TBD"); //TODO: all HCAs and hadle multi HCAs \r
- printf("\tpci_location={BUS=TBD,DEV/FUNC=TBD}\n");\r
+ printf("\thca_idx=%d\n",idx);\r
+ printf("\tpci_location={BUS=NA,DEV/FUNC=NA}\n");\r
printf("\tvendor_id=0x%04x\n", ca_attr->vend_id);\r
printf("\tvendor_part_id=0x%04x\n", ca_attr->dev_id);\r
printf("\thw_ver=0x%x\n", ca_attr->revision); //TODO: ???\r
- printf("\tfw_ver=TBD\n");\r
- printf("\tPSID=TBD\n");\r
+ if(ca_attr->vend_id == VEND_ID_MELLNOX){\r
+ printf("\tfw_ver=%d.%.2d.%.4d\n",\r
+ (uint16_t )(ca_attr->fw_ver>>32),\r
+ (uint16_t)(ca_attr->fw_ver>>16),\r
+ (uint16_t )(ca_attr->fw_ver));\r
+ }else{\r
+ printf("\tfw_ver=0x%I64x\n",ca_attr->fw_ver);\r
+ }\r
+ printf("\tPSID=NA\n");\r
if(fullPrint){\r
- printf("\tnum_phys_ports = TBD\n");\r
+ printf("\tnum_phys_ports = %d\n",ca_attr->num_ports);\r
printf("\tmax_num_qp = 0x%x (Maximum Number of QPs supported)\n", ca_attr->max_qps);\r
- printf("\tmax_qp_ous_wr = 0x%x (Maximum Number of oustanding WR on any WQ)\n", ca_attr->max_wrs);\r
- printf("\tflags== TBD\n");\r
+ printf("\tmax_qp_ous_wr = 0x%x (Maximum Number of oustanding WR on any WQ)\n", ca_attr->max_wrs);\r
printf("\tmax_num_sg_ent = 0x%x (Max num of scatter/gather entries for WQE other than RD)\n", ca_attr->max_sges);\r
- printf("\tmax_num_sg_ent_rd = 0x%x (Max num of scatter/gather entries for RD WQE)\n", ca_attr->max_rd_sges);\r
- printf("\tmax_num_srq = TBD (Maximum Number of SRQs supported)\n");\r
- printf("\tmax_wqe_per_srq = TBD (Maximum Number of oustanding WR on any SRQ)\n");\r
- printf("\tmax_srq_sentries = TBD (Maximum Number of scatter entries for SRQ WQE)\n");\r
- printf("\tsrq_resize_supported = TBD (SRQ resize supported)\n");\r
- printf("\tmax_num_cq = 0x%x (Max num of supported CQs)\n", ca_attr->max_cqs);\r
+ printf("\tmax_num_sg_ent_rd = 0x%x (Max num of scatter/gather entries for RD WQE)\n", ca_attr->max_rd_sges);\r
+ printf("\tmax_num_srq = 0 (Maximum Number of SRQs supported)\n");\r
+ printf("\tmax_wqe_per_srq = 0 (Maximum Number of oustanding WR on any SRQ)\n");\r
+ printf("\tmax_srq_sentries = 0 (Maximum Number of scatter entries for SRQ WQE)\n");\r
+ printf("\tsrq_resize_supported = 0 (SRQ resize supported)\n");\r
+ printf("\tmax_num_cq = 0x%x (Max num of supported CQs)\n", ca_attr->max_cqs);\r
printf("\tmax_num_ent_cq = 0x%x (Max num of supported entries per CQ)\n", ca_attr->max_cqes);\r
- printf("\tmax_num_mr = 0x%x (Maximum number of memory region supported)\n", ca_attr->init_regions);\r
+ printf("\tmax_num_mr = 0x%x (Maximum number of memory region supported)\n", ca_attr->init_regions);\r
printf("\tmax_mr_size = 0x%x (Largest contigous block of memory region in bytes)\n", ca_attr->init_region_size);\r
- printf("\tmax_pd_num = 0x%x (Maximum number of protection domains supported)\n", ca_attr->max_pds);\r
- printf("\tpage_size_cap = TBD (Largest page size supported by this HCA)\n");\r
- printf("\tmax_pkeys = TBD (Maximum number of partitions supported)\n");\r
+ printf("\tmax_pd_num = 0x%x (Maximum number of protection domains supported)\n", ca_attr->max_pds);\r
+ printf("\tpage_size_cap = 0x%x (Largest page size supported by this HCA)\n",ca_attr->p_page_size[ca_attr->num_page_sizes-1]);\r
printGUID(ca_attr->ca_guid);\r
- printf("\tlocal_ca_ack_delay = 0x%x (Log2 4.096usec Max. RX to ACK or NAK delay)\n", ca_attr->local_ack_delay);\r
- printf("\tmax_qp_ous_rd_atom = TBD (Maximum number of oust. RDMA read/atomic as target)\n");\r
- printf("\tmax_ee_ous_rd_atom = TBD (EE Maximum number of outs. RDMA read/atomic as target)\n");\r
- printf("\tmax_res_rd_atom = TBD (Max. Num. of resources used for RDMA read/atomic as target)\n");\r
- printf("\tmax_qp_init_rd_atom = TBD (Max. Num. of outs. RDMA read/atomic as initiator)\n");\r
- printf("\tmax_ee_init_rd_atom = TBD (EE Max. Num. of outs. RDMA read/atomic as initiator)\n");\r
- printf("\tatomic_cap = TBD (Level of Atomicity supported)\n");\r
+ printf("\tlocal_ca_ack_delay = 0x%x (Log2 4.096usec Max. RX to ACK or NAK delay)\n", ca_attr->local_ack_delay);\r
+ printf("\tmax_qp_ous_rd_atom = 0x%x (Maximum number of oust. RDMA read/atomic as target)\n",ca_attr->max_qp_resp_res);\r
+ printf("\tmax_ee_ous_rd_atom = 0 (EE Maximum number of outs. RDMA read/atomic as target)\n");\r
+ printf("\tmax_res_rd_atom = 0x%x (Max. Num. of resources used for RDMA read/atomic as target)\n",ca_attr->max_resp_res);\r
+ printf("\tmax_qp_init_rd_atom = 0x%x (Max. Num. of outs. RDMA read/atomic as initiator)\n",ca_attr->max_qp_init_depth);\r
+ printf("\tmax_ee_init_rd_atom = 0 (EE Max. Num. of outs. RDMA read/atomic as initiator)\n");\r
+ printf("\tatomic_cap = %s (Level of Atomicity supported)\n",ca_attr->atomicity == IB_ATOMIC_GLOBAL?"GLOBAL":\r
+ ca_attr->atomicity == IB_ATOMIC_LOCAL?"LOCAL":"NORMAL");\r
printf("\tmax_ee_num = 0x0 (Maximum number of EEC supported)\n");\r
printf("\tmax_rdd_num = 0x0 (Maximum number of IB_RDD supported)\n");\r
- printf("\tmax_mw_num = 0x%x (Maximum Number of memory windows supported)\n", ca_attr->init_windows);\r
- printf("\tmax_raw_ipv6_qp = 0x%x (Maximum number of Raw IPV6 QPs supported)\n", ca_attr->max_ipv6_qps);\r
- printf("\tmax_raw_ethy_qp = 0x%x (Maximum number of Raw Ethertypes QPs supported)\n", ca_attr->max_ether_qps);\r
+ printf("\tmax_mw_num = 0x%x (Maximum Number of memory windows supported)\n", ca_attr->init_windows);\r
+ printf("\tmax_raw_ipv6_qp = 0x%x (Maximum number of Raw IPV6 QPs supported)\n", ca_attr->max_ipv6_qps);\r
+ printf("\tmax_raw_ethy_qp = 0x%x (Maximum number of Raw Ethertypes QPs supported)\n", ca_attr->max_ether_qps);\r
printf("\tmax_mcast_grp_num = 0x%x (Maximum Number of multicast groups)\n", ca_attr->max_mcast_grps);\r
- printf("\tmax_mcast_qp_attach_num = 0x%x(Maximum number of QP per multicast group)\n", ca_attr->max_qps_per_mcast_grp);\r
- printf("\tmax_total_mcast_qp_attach_num = 0x%x(Maximum number of QPs which can be attached to a mcast grp)\n", ca_attr->max_mcast_qps);\r
- printf("\tmax_ah_num = 0x%x (Maximum number of address handles)\n", ca_attr->max_addr_handles);\r
- printf("\tmax_num_fmr = TBD (maximum number FMRs)\n");\r
- printf("\tmax_num_map_per_fmr = TBD (Maximum number of (re)maps per FMR before an unmap operation in required)\n");\r
+ printf("\tmax_mcast_qp_attach_num = 0x%x (Maximum number of QP per multicast group)\n", ca_attr->max_qps_per_mcast_grp);\r
+ printf("\tmax_ah_num = 0x%x (Maximum number of address handles)\n", ca_attr->max_addr_handles);\r
+ printf("\tmax_num_fmr = 0 (Maximum number FMRs)\n");\r
+ printf("\tmax_num_map_per_fmr = 0 (Maximum number of (re)maps per FMR before an unmap operation in required)\n");\r
}else{\r
printf("\tnum_phys_ports=%d\n", ca_attr->num_ports);\r
}\r
size_t guid_count;\r
ib_net64_t *ca_guid_array;\r
ib_ca_attr_t *vstat_ca_attr;\r
- uintn_t i;\r
+ size_t i;\r
ib_ca_handle_t h_ca = NULL;\r
uint32_t bsize;\r
ib_port_attr_mod_t port_attr_mod;\r
\r
/* Print_ca_attributes */\r
\r
- vstat_print_ca_attr(vstat_ca_attr, fullPrint);\r
+ vstat_print_ca_attr((int)i, vstat_ca_attr, fullPrint);\r
\r
\r
/* Free the memory */\r
TARGETPATH=..\..\..\bin\kernel\obj$(BUILD_ALT_DIR)\r
TARGETTYPE=DRIVER\r
\r
-SOURCES= ipoib.rc \\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_port.c \\r
+ ipoib_ibat.c\r
\r
INCLUDES=..;..\..\..\inc;..\..\..\inc\kernel;\r
\r
ipoib_adapter_t *p_adapter;\r
ib_api_status_t status;\r
cl_status_t cl_status;\r
- uint8_t port_num;\r
- KLOCK_QUEUE_HANDLE hdl;\r
\r
IPOIB_ENTER( IPOIB_DBG_INIT );\r
\r
return status;\r
}\r
\r
- port_num = IPOIB_GET_PORT_NUM_FROM_GUID(p_adapter->guids.port_guid);\r
-\r
- IPOIB_TRACE( IPOIB_DBG_INFO, \r
- ("Port %d initializing\n", port_num) );\r
+ IPOIB_TRACE( IPOIB_DBG_INIT | IPOIB_DBG_INFO,\r
+ ("Port %016I64x (CA %016I64x port %d) initializing\n",\r
+ p_adapter->guids.port_guid, p_adapter->guids.ca_guid,\r
+ p_adapter->guids.port_num) );\r
\r
/* Read configuration parameters. */\r
status = ipoib_get_adapter_params( wrapper_config_context,\r
return IB_ERROR;\r
}\r
\r
- KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
- InsertHeadList( &g_ipoib.adapter_list, &p_adapter->entry );\r
- KeReleaseInStackQueuedSpinLock( &hdl );\r
-\r
status = adapter_init( p_adapter );\r
if( status != IB_SUCCESS )\r
{\r
cl_mutex_acquire( &p_adapter->mutex );\r
cl_obj_lock( &p_adapter->obj );\r
p_adapter->state = IB_PNP_PORT_REMOVE;\r
- cl_obj_unlock( &p_adapter->obj );\r
\r
/*\r
* Clear the pointer to the port object since the object destruction\r
*/\r
p_adapter->p_port = NULL;\r
\r
+ cl_obj_unlock( &p_adapter->obj );\r
+\r
cl_mutex_release( &p_adapter->mutex );\r
\r
cl_obj_destroy( &p_adapter->obj );\r
p_adapter->h_pnp = NULL;\r
}\r
\r
- KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
- ASSERT( !IsListEmpty( &g_ipoib.adapter_list ) );\r
- RemoveEntryList( &p_adapter->entry );\r
- KeReleaseInStackQueuedSpinLock( &hdl );\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
ib_api_status_t status;\r
ipoib_adapter_t *p_adapter;\r
+ ipoib_port_t *p_port;\r
ib_pnp_event_t old_state;\r
\r
IPOIB_ENTER( IPOIB_DBG_PNP );\r
p_adapter->state = IB_PNP_PORT_ADD;\r
cl_obj_unlock( &p_adapter->obj );\r
status = ipoib_create_port( p_adapter,\r
- (ib_pnp_port_rec_t*)p_pnp_rec, &p_adapter->p_port );\r
+ (ib_pnp_port_rec_t*)p_pnp_rec, &p_port );\r
+ cl_obj_lock( &p_adapter->obj );\r
if( status != IB_SUCCESS )\r
{\r
- cl_obj_lock( &p_adapter->obj );\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_adapter->p_port;\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
\r
cl_obj_lock( &p_adapter->obj );\r
p_adapter->state = IB_PNP_PORT_REMOVE;\r
- cl_obj_unlock( &p_adapter->obj );\r
- ipoib_port_destroy( p_adapter->p_port );\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
case IB_PNP_SM_CHANGE:\r
case IB_PNP_GID_CHANGE:\r
case IB_PNP_LID_CHANGE:\r
- p_adapter->hung = TRUE;\r
+ cl_obj_lock( &p_adapter->obj );\r
+ if( p_adapter->state == IB_PNP_PORT_ACTIVE )\r
+ p_adapter->hung = TRUE;\r
+ cl_obj_unlock( &p_adapter->obj );\r
status = IB_SUCCESS;\r
break;\r
}\r
IN void* context )\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
\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
- /* Destroy the current port instance if it still exists. */\r
- if( p_adapter->p_port )\r
- {\r
- ipoib_port_destroy( p_adapter->p_port );\r
- p_adapter->p_port = NULL;\r
- }\r
+ if( p_port )\r
+ ipoib_port_destroy( p_port );\r
+\r
/* Complete any pending OIDs. */\r
ipoib_resume_oids( p_adapter );\r
+ ipoib_dereg_addrs( p_adapter );\r
\r
if( state != IB_PNP_PORT_REMOVE )\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_width, \r
+ IN const uint8_t link_speed )\r
{\r
IPOIB_ENTER( IPOIB_DBG_INIT );\r
\r
cl_obj_lock( &p_adapter->obj );\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_TRACE( IPOIB_DBG_INIT | IPOIB_DBG_INFO,\r
+ ("Link speed is 2.5Gs\n") );\r
+ p_adapter->rate = IB_LINK_SPEED_ACTIVE_2_5;\r
+ break;\r
+\r
+ case IB_LINK_SPEED_ACTIVE_5:\r
+ IPOIB_TRACE( IPOIB_DBG_INIT | IPOIB_DBG_INFO,\r
+ ("Link speed is 5G\n") );\r
+ p_adapter->rate = IB_LINK_SPEED_ACTIVE_5;\r
+ break;\r
+\r
+ case IB_LINK_SPEED_ACTIVE_10:\r
+ IPOIB_TRACE( IPOIB_DBG_INIT | IPOIB_DBG_INFO,\r
+ ("Link speed is 10G\n") );\r
+ p_adapter->rate = IB_LINK_SPEED_ACTIVE_10;\r
+ break;\r
+\r
+ default:\r
+ IPOIB_TRACE( IPOIB_DBG_ERROR,\r
+ ("Invalid link speed %d.\n", link_speed) );\r
+ p_adapter->rate = 0;\r
+ }\r
+\r
switch( link_width )\r
{\r
case IB_LINK_WIDTH_ACTIVE_1X:\r
- IPOIB_TRACE( IPOIB_DBG_INFO, ("Link speed is 2.5Gbps\n") );\r
- p_adapter->rate = ONE_X_IN_100BPS;\r
+ IPOIB_TRACE( IPOIB_DBG_INIT | IPOIB_DBG_INFO,\r
+ ("Link width is 1X\n") );\r
+ p_adapter->rate *= ONE_X_IN_100BPS;\r
break;\r
\r
case IB_LINK_WIDTH_ACTIVE_4X:\r
- IPOIB_TRACE( IPOIB_DBG_INFO, ("Link speed is 10Gbps\n") );\r
- p_adapter->rate = FOUR_X_IN_100BPS;\r
+ IPOIB_TRACE( IPOIB_DBG_INIT | IPOIB_DBG_INFO,\r
+ ("Link width is 4X\n") );\r
+ p_adapter->rate *= FOUR_X_IN_100BPS;\r
break;\r
\r
case IB_LINK_WIDTH_ACTIVE_12X:\r
- IPOIB_TRACE( IPOIB_DBG_INFO, ("Link speed is 30Gbps\n") );\r
- p_adapter->rate = TWELVE_X_IN_100BPS;\r
+ IPOIB_TRACE( IPOIB_DBG_INIT | IPOIB_DBG_INFO,\r
+ ("Link width is 12X\n") );\r
+ p_adapter->rate *= TWELVE_X_IN_100BPS;\r
break;\r
\r
default:\r
- IPOIB_TRACE( IPOIB_DBG_INFO, ("Invalid rate.\n") );\r
+ IPOIB_TRACE( IPOIB_DBG_ERROR,\r
+ ("Invalid link rate (%d).\n", link_width) );\r
p_adapter->rate = 0;\r
}\r
cl_obj_unlock( &p_adapter->obj );\r
-\r
IPOIB_EXIT( IPOIB_DBG_INIT );\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( p_adapter->p_port, p_adapter->mcast_array[i] );\r
+ ipoib_port_join_mcast(\r
+ p_adapter->p_port, p_adapter->mcast_array[i] );\r
}\r
\r
/* Register all existing addresses. */\r
ipoib_reg_addrs( p_adapter );\r
\r
- /* Now that we're in the broadcast group, notify that we have a link. */\r
+ /*\r
+ * Now that we're in the broadcast group, notify that\r
+ * we have a link.\r
+ */\r
IPOIB_TRACE( IPOIB_DBG_INFO, ("Link UP!\n") );\r
+ NdisWriteErrorLogEntry( p_adapter->h_adapter,\r
+ EVENT_IPOIB_PORT_UP + (p_adapter->rate/ONE_X_IN_100BPS),\r
+ 1, p_adapter->rate );\r
+\r
NdisMIndicateStatus( p_adapter->h_adapter, NDIS_STATUS_MEDIA_CONNECT,\r
NULL, 0 );\r
NdisMIndicateStatusComplete( p_adapter->h_adapter );\r
/*\r
* Macros\r
*/\r
-#define IPOIB_GET_PORT_NUM_FROM_GUID( __guid__ ) ( ((uint8_t *)&(__guid__))[PORT_NUM_INDEX_IN_GUID] + 1 )\r
-#define IPOIB_ADAPTER_GET_PORT_NUM(__p_adapter__) ( IPOIB_GET_PORT_NUM_FROM_GUID( (__p_adapter__)->guids.port_guid ) )\r
\r
\r
typedef struct _ipoib_params\r
NDIS_HANDLE h_adapter;\r
ipoib_ifc_data_t guids;\r
\r
- LIST_ENTRY entry;\r
+ cl_list_item_t entry;\r
\r
ib_al_handle_t h_al;\r
ib_pnp_handle_t h_pnp;\r
* guids\r
* CA and port GUIDs returned by the bus driver.\r
*\r
+* entry\r
+* List item for storing all adapters in a list for address translation.\r
+* We add adapters when their packet filter is set to a non-zero value,\r
+* and remove them when their packet filter is cleared. This is needed\r
+* since user-mode removal events are generated after the packet filter\r
+* is cleared, but before the adapter is destroyed.\r
+*\r
* h_al\r
* AL handle for all IB resources.\r
*\r
void\r
ipoib_set_rate(\r
IN ipoib_adapter_t* const p_adapter,\r
- IN const uint8_t rate );\r
+ IN const uint8_t link_width,\r
+ IN const uint8_t link_speed );\r
\r
\r
void\r
ipoib_reg_addrs(\r
IN ipoib_adapter_t* const p_adapter );\r
\r
+void\r
+ipoib_dereg_addrs(\r
+ IN ipoib_adapter_t* const p_adapter );\r
+\r
#endif /* _IPOIB_ADAPTER_H_ */\r
#include "ipoib_driver.h"\r
#include "ipoib_debug.h"\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
\r
#define IB_INFINITE_SERVICE_LEASE 0xFFFFFFFF\r
\r
-#define DEFAULT_SA_TIMEOUT 250\r
-#define DEFAULT_SA_RETRIES 3\r
-\r
\r
/* Global driver debug level */\r
uint32_t g_ipoib_dbg_lvl = IPOIB_DBG_ERROR;\r
__ipoib_ats_dereg_cb(\r
IN void *context );\r
\r
-static void\r
-__ipoib_dereg_addrs(\r
- IN ipoib_adapter_t* const p_adapter );\r
+static NTSTATUS\r
+__ipoib_read_registry(\r
+ IN UNICODE_STRING* const p_registry_path );\r
\r
\r
//! Standard Windows Device Driver Entry Point\r
status = NDIS_STATUS_SUCCESS;\r
ndis_handle = NULL;\r
\r
+ __ipoib_read_registry(p_registry_path);\r
+ \r
KeInitializeSpinLock( &g_ipoib.lock );\r
- InitializeListHead( &g_ipoib.adapter_list );\r
+ cl_qlist_init( &g_ipoib.adapter_list );\r
\r
- NdisMInitializeWrapper( &ndis_handle, p_drv_obj, p_registry_path, NULL );\r
+ NdisMInitializeWrapper(\r
+ &g_ipoib.h_ndis_wrapper, p_drv_obj, p_registry_path, NULL );\r
\r
memset(&characteristics, 0, sizeof(characteristics));\r
characteristics.MajorNdisVersion = MAJOR_NDIS_VERSION;\r
#endif\r
\r
status = NdisMRegisterMiniport(\r
- ndis_handle, &characteristics, sizeof(characteristics) );\r
+ g_ipoib.h_ndis_wrapper, &characteristics, sizeof(characteristics) );\r
if( status != NDIS_STATUS_SUCCESS )\r
{\r
IPOIB_TRACE( IPOIB_DBG_ERROR, \r
("NdisMRegisterMiniport failed with status of %d\n", status) );\r
- NdisTerminateWrapper( ndis_handle, NULL );\r
+ NdisTerminateWrapper( g_ipoib.h_ndis_wrapper, NULL );\r
CL_DEINIT;\r
+ return status;\r
}\r
- else\r
+\r
+ NdisMRegisterUnloadHandler( g_ipoib.h_ndis_wrapper, ipoib_unload );\r
+\r
+ IPOIB_EXIT( IPOIB_DBG_INIT );\r
+ return status;\r
+}\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[2];\r
+ UNICODE_STRING param_path;\r
+\r
+ IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\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
- NdisMRegisterUnloadHandler( ndis_handle, ipoib_unload );\r
+ IPOIB_TRACE_EXIT( 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"DebugFlags";\r
+ table[0].EntryContext = &g_ipoib_dbg_lvl;\r
+ table[0].DefaultType = REG_DWORD;\r
+ table[0].DefaultData = &g_ipoib_dbg_lvl;\r
+ table[0].DefaultLength = sizeof(ULONG);\r
+\r
+ /* Have at it! */\r
+ status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE, \r
+ param_path.Buffer, table, NULL, NULL );\r
+\r
+ cl_free( param_path.Buffer );\r
IPOIB_EXIT( IPOIB_DBG_INIT );\r
return status;\r
}\r
{\r
NTSTATUS status;\r
ib_al_ifc_data_t data;\r
- IO_STACK_LOCATION io_stack;\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
io_stack.Parameters.QueryInterface.InterfaceType = \r
&GUID_IB_AL_INTERFACE;\r
\r
- status = cl_fwd_query_ifc( p_pdo, &io_stack );\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_TRACE_EXIT( 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_TRACE_EXIT( IPOIB_DBG_ERROR,\r
ib_status = ipoib_start_adapter( p_adapter );\r
if( ib_status != IB_SUCCESS )\r
{\r
+ NdisWriteErrorLogEntry( h_adapter,\r
+ NDIS_ERROR_CODE_HARDWARE_FAILURE, 0 );\r
ipoib_destroy_adapter( p_adapter );\r
IPOIB_TRACE_EXIT( 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
IPOIB_ENTER( IPOIB_DBG_INIT );\r
\r
+ ipoib_deref_ibat();\r
+\r
CL_ASSERT( adapter_context );\r
p_adapter = (ipoib_adapter_t*)adapter_context;\r
\r
- IPOIB_TRACE( IPOIB_DBG_INFO,\r
- ("Port %d halting\n", IPOIB_ADAPTER_GET_PORT_NUM(p_adapter)) );\r
+ IPOIB_TRACE( IPOIB_DBG_INIT | IPOIB_DBG_INFO,\r
+ ("Port %016I64x (CA %016I64x port %d) halting\n",\r
+ p_adapter->guids.port_guid, p_adapter->guids.ca_guid,\r
+ p_adapter->guids.port_num) );\r
\r
ipoib_destroy_adapter( p_adapter );\r
\r
src_buf = &info;\r
buf_len = sizeof(info);\r
\r
- port_num = IPOIB_ADAPTER_GET_PORT_NUM(p_adapter);\r
+ port_num = p_adapter->guids.port_num;\r
\r
switch( oid )\r
{\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
- uint8_t port_num;\r
ULONG buf_len;\r
\r
- port_num = IPOIB_ADAPTER_GET_PORT_NUM(p_adapter);\r
-\r
IPOIB_TRACE( IPOIB_DBG_OID | IPOIB_DBG_INFO,\r
- ("Port %d received query for OID_TCP_TASK_OFFLOAD\n", port_num) );\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
sizeof(NDIS_TASK_OFFLOAD) +\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
*p_bytes_needed = 0;\r
buf_len = sizeof(ULONG);\r
\r
- port_num = IPOIB_ADAPTER_GET_PORT_NUM(p_adapter);\r
+ port_num = p_adapter->guids.port_num;\r
\r
switch( oid )\r
{\r
}\r
else\r
{\r
+ KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
cl_obj_lock( &p_adapter->obj );\r
switch( p_adapter->state )\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
* Filter was non-zero, now zero. Deregister IP addresses.\r
*/\r
- __ipoib_dereg_addrs( p_adapter );\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
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
+ 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
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
+ * 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
- /*\r
- * Filter was non-zero, now zero. Deregister IP addresses.\r
- */\r
- __ipoib_dereg_addrs( p_adapter );\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
\r
- p_adapter->packet_filter = *(PULONG)set_oid.p_buf;\r
NdisMSetInformationComplete( p_adapter->h_adapter, status );\r
break;\r
\r
IPOIB_ENTER( IPOIB_DBG_OID );\r
\r
status = NDIS_STATUS_SUCCESS;\r
- port_num = IPOIB_ADAPTER_GET_PORT_NUM(p_adapter);\r
+ port_num = p_adapter->guids.port_num;\r
\r
IPOIB_TRACE( IPOIB_DBG_OID | IPOIB_DBG_INFO,\r
("Port %d received set for OID_GEN_NETWORK_LAYER_ADDRESSES\n",\r
\r
IPOIB_ENTER( IPOIB_DBG_OID );\r
\r
- port_num = IPOIB_ADAPTER_GET_PORT_NUM( p_adapter );\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
/* IP Address in question will be put in below */\r
ib_service.port_guid = p_adapter->guids.port_guid;\r
- ib_service.timeout_ms = DEFAULT_SA_TIMEOUT;\r
- ib_service.retry_cnt = DEFAULT_SA_RETRIES;\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
\r
/* Object lock is held when this function is called. */\r
-static void\r
-__ipoib_dereg_addrs(\r
+void\r
+ipoib_dereg_addrs(\r
IN ipoib_adapter_t* const p_adapter )\r
{\r
net_address_item_t *p_addr_item;\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
+ cl_vector_get_ptr( &p_adapter->ip_vector, idx );\r
\r
if( !p_addr_item->p_reg )\r
continue;\r
CL_ASSERT( p_reg_svc_rec->svc_context );\r
\r
p_reg = (ats_reg_t* __ptr64)p_reg_svc_rec->svc_context;\r
- port_num = IPOIB_ADAPTER_GET_PORT_NUM( p_reg->p_adapter );\r
+ port_num = p_reg->p_adapter->guids.port_num;\r
\r
cl_obj_lock( &p_reg->p_adapter->obj );\r
\r
#define _IPOIB_DRIVER_H_\r
\r
\r
+#include "ipoib_log.h"\r
#include "ipoib_adapter.h"\r
#include <complib/cl_spinlock.h>\r
#include <complib/cl_qlist.h>\r
typedef struct _ipoib_globals\r
{\r
KSPIN_LOCK lock;\r
- LIST_ENTRY adapter_list;\r
+ cl_qlist_t adapter_list;\r
cl_qlist_t bundle_list;\r
\r
atomic32_t laa_idx;\r
\r
+ NDIS_HANDLE h_ndis_wrapper;\r
+ NDIS_HANDLE h_ibat_dev;\r
+ volatile LONG ibat_ref;\r
+\r
} ipoib_globals_t;\r
/*\r
* FIELDS\r
*\r
* laa_idx\r
* Global counter for generating LAA MACs\r
+*\r
+* h_ibat_dev\r
+* Device handle returned by NdisMRegisterDevice.\r
*********/\r
\r
extern ipoib_globals_t g_ipoib;\r
\r
IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
\r
+ IPOIB_TRACE( (IPOIB_DBG_ENDPT | IPOIB_DBG_INFO),\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
return NDIS_STATUS_SUCCESS;\r
}\r
\r
- if( p_endpt->h_query )\r
+ if( p_endpt->h_query ||\r
+ p_endpt->qpn == CL_HTON32(0x00FFFFFF) )\r
{\r
ipoib_endpt_deref( p_endpt );\r
IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
av_attr.sl = ib_path_rec_sl( p_path );\r
av_attr.dlid = p_path->dlid;\r
\r
- if( p_path->dgid.unicast.prefix != IB_DEFAULT_SUBNET_PREFIX )\r
- {\r
- flow_lbl = ib_path_rec_flow_lbl( p_path );\r
- /* Not on the same subnet, need GRH. */\r
- av_attr.grh_valid = TRUE;\r
- av_attr.grh.ver_class_flow = ib_grh_set_ver_class_flow(\r
- 6, p_path->tclass, flow_lbl );\r
- av_attr.grh.resv1 = 0;\r
- av_attr.grh.resv2 = 0;\r
- av_attr.grh.hop_limit = ib_path_rec_hop_limit( p_path );\r
- av_attr.grh.src_gid = p_path->sgid;\r
- av_attr.grh.dest_gid = p_path->dgid;\r
- }\r
- else if( !p_endpt->dlid )\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
+ flow_lbl = ib_path_rec_flow_lbl( p_path );\r
+ av_attr.grh_valid = TRUE;\r
+ av_attr.grh.ver_class_flow = ib_grh_set_ver_class_flow(\r
+ 6, p_path->tclass, flow_lbl );\r
+ av_attr.grh.resv1 = 0;\r
+ av_attr.grh.resv2 = 0;\r
+ av_attr.grh.hop_limit = ib_path_rec_hop_limit( p_path );\r
+ av_attr.grh.src_gid = p_path->sgid;\r
+ av_attr.grh.dest_gid = p_path->dgid;\r
+ \r
+ if( !p_endpt->dlid )\r
{\r
/* This is a subnet local endpoint that does not have its LID set. */\r
p_endpt->dlid = p_path->dlid;\r
* request that specifies an MGID. The ESM returns every McMemberRecord\r
* instead.\r
*/\r
-#define PR_102801\r
+//#define PR_102801\r
\r
\r
/* Amount of physical memory to register. */\r
\r
CL_ASSERT( p_port );\r
CL_ASSERT( p_port->p_adapter );\r
- CL_ASSERT( p_port->p_adapter->p_port == p_port );\r
+ CL_ASSERT( !p_port->p_adapter->p_port );\r
\r
cl_obj_destroy( &p_port->obj );\r
\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_TRACE_EXIT( IPOIB_DBG_ERROR,\r
("ib_open_ca returned %s\n", \r
p_port->p_adapter->p_ifc->get_err_str( status )) );\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_TRACE_EXIT( IPOIB_DBG_ERROR,\r
("ib_alloc_pd returned %s\n", \r
p_port->p_adapter->p_ifc->get_err_str( status )) );\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_TRACE_EXIT( IPOIB_DBG_ERROR,\r
("ib_create_cq returned %s.\n", \r
p_port->p_adapter->p_ifc->get_err_str( status )) );\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_TRACE_EXIT( IPOIB_DBG_ERROR,\r
("ib_create_cq returned %s.\n", \r
p_port->p_adapter->p_ifc->get_err_str( status )) );\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_TRACE_EXIT( IPOIB_DBG_ERROR,\r
("ib_create_qp returned %s\n", \r
p_port->p_adapter->p_ifc->get_err_str( status )) );\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_TRACE_EXIT( IPOIB_DBG_ERROR,\r
("ib_query_qp returned %s\n", \r
p_port->p_adapter->p_ifc->get_err_str( status )) );\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_TRACE_EXIT( IPOIB_DBG_ERROR,\r
("ib_reg_phys returned %s\n", \r
p_port->p_adapter->p_ifc->get_err_str( status )) );\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_TRACE_EXIT( IPOIB_DBG_ERROR,\r
("cl_qpool_init for recvs returned %s\n",\r
cl_status_text[cl_status]) );\r
p_params->rq_depth, 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
IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,\r
("NdisAllocatePacketPool returned %08X\n", ndis_status) );\r
return IB_INSUFFICIENT_RESOURCES;\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_TRACE_EXIT( IPOIB_DBG_ERROR,\r
("NdisAllocateBufferPool returned %08X\n", ndis_status) );\r
return IB_INSUFFICIENT_RESOURCES;\r
1, PROTOCOL_RESERVED_SIZE_IN_PACKET );\r
if( ndis_status != NDIS_STATUS_SUCCESS )\r
{\r
+ NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+ EVENT_IPOIB_SEND_PKT_POOL, 1, ndis_status );\r
IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,\r
("NdisAllocatePacketPool returned %08X\n", ndis_status) );\r
return IB_INSUFFICIENT_RESOURCES;\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_TRACE_EXIT( IPOIB_DBG_ERROR,\r
("NdisAllocateBufferPool returned %08X\n", ndis_status) );\r
return IB_INSUFFICIENT_RESOURCES;\r
sizeof(NDIS_PACKET*) * 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_TRACE_EXIT( IPOIB_DBG_ERROR,\r
("cl_malloc for PNDIS_PACKET array failed.\n") );\r
return IB_INSUFFICIENT_MEMORY;\r
CL_ASSERT( *pp_dst );\r
}\r
\r
+ if( *pp_src && (*pp_src)->qpn != p_wc->recv.ud.remote_qp )\r
+ {\r
+ /* Update the QPN for the endpoint. */\r
+ IPOIB_TRACE( (IPOIB_DBG_RECV | IPOIB_DBG_WARN),\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_TRACE( (IPOIB_DBG_RECV | IPOIB_DBG_INFO),\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
continue;\r
}\r
\r
- len = p_wc->length;\r
+ len = p_wc->length - sizeof(ib_grh_t);\r
\r
- if( len < (sizeof(ib_grh_t) + sizeof(ipoib_hdr_t)) )\r
+ if( len < sizeof(ipoib_hdr_t) )\r
{\r
IPOIB_TRACE( IPOIB_DBG_ERROR,\r
("Received ETH packet < min size\n") );\r
p_eth = &p_desc->p_buf->eth.pkt;\r
#endif /*IPOIB_INLINE_RECV */\r
\r
- /* Don't report loopback traffic - we requested SW loopback. */\r
- if( !cl_memcmp( &p_port->p_adapter->mac, &p_eth->hdr.src,\r
- sizeof(p_port->p_adapter->mac) ) )\r
+ if( p_src )\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 receive. */\r
- cl_obj_deref( &p_port->obj );\r
- continue;\r
+ /* Don't report loopback traffic - we requested SW loopback. */\r
+ if( !cl_memcmp( &p_port->p_adapter->mac, &p_src->mac,\r
+ sizeof(p_port->p_adapter->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
+ cl_obj_deref( &p_port->obj );\r
+ continue;\r
+ }\r
}\r
\r
switch( p_ipoib->hdr.type )\r
{\r
case ETH_PROT_TYPE_IP:\r
- if( len <\r
- (sizeof(ib_grh_t) + sizeof(ipoib_hdr_t) + sizeof(ip_hdr_t)) )\r
+ if( len < (sizeof(ipoib_hdr_t) + sizeof(ip_hdr_t)) )\r
{\r
IPOIB_TRACE( IPOIB_DBG_ERROR,\r
("Received IP packet < min size\n") );\r
}\r
\r
/* First packet of a UDP transfer. */\r
- if( len < (sizeof(ib_grh_t) + sizeof(ipoib_hdr_t) +\r
- sizeof(ip_hdr_t) + sizeof(udp_hdr_t)) )\r
+ if( len <\r
+ (sizeof(ipoib_hdr_t) + sizeof(ip_hdr_t) + sizeof(udp_hdr_t)) )\r
{\r
IPOIB_TRACE( IPOIB_DBG_ERROR,\r
("Received UDP packet < min size\n") );\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(ib_grh_t) + sizeof(ipoib_hdr_t) +\r
- sizeof(ip_hdr_t) + sizeof(udp_hdr_t) + DHCP_MIN_SIZE ))\r
+ if( len < (sizeof(ipoib_hdr_t) + sizeof(ip_hdr_t) +\r
+ sizeof(udp_hdr_t) + DHCP_MIN_SIZE) )\r
{\r
IPOIB_TRACE( IPOIB_DBG_ERROR,\r
("Received DHCP < min size\n") );\r
{\r
p_desc->len =\r
len + sizeof(eth_hdr_t) - sizeof(ipoib_hdr_t);\r
- if( p_dst )\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
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
+ p_eth_hdr->dst.addr[0] == 0x01 &&\r
+ p_eth_hdr->dst.addr[1] == 0x00 &&\r
+ p_eth_hdr->dst.addr[2] == 0x5E )\r
+ {\r
+ if( ipoib_port_join_mcast( p_port, p_eth_hdr->dst ) == IB_SUCCESS )\r
+ {\r
+ IPOIB_TRACE_EXIT( IPOIB_DBG_ENDPT,\r
+ ("Multicast Mac - trying to join.\n") );\r
+ return NDIS_STATUS_PENDING;\r
+ }\r
+ }\r
+\r
IPOIB_EXIT( IPOIB_DBG_SEND );\r
return status;\r
}\r
else if( status != NDIS_STATUS_SUCCESS )\r
{\r
ASSERT( status == NDIS_STATUS_NO_ROUTE_TO_DESTINATION );\r
+\r
+ if( p_eth_hdr->dst.addr[0] == 0x01 &&\r
+ p_eth_hdr->dst.addr[1] == 0x00 &&\r
+ p_eth_hdr->dst.addr[2] == 0x5E )\r
+ {\r
+ if( ipoib_port_join_mcast( p_port, p_eth_hdr->dst ) ==\r
+ IB_SUCCESS )\r
+ {\r
+ IPOIB_TRACE_EXIT( IPOIB_DBG_ENDPT,\r
+ ("Multicast Mac - trying to join.\n") );\r
+ cl_qlist_insert_head( &p_port->send_mgr.pending_list,\r
+ IPOIB_LIST_ITEM_FROM_PACKET( desc.p_pkt ) );\r
+ break;\r
+ }\r
+ }\r
+\r
/*\r
* Complete the send as if we sent it - WHQL tests don't like the\r
* sends to fail.\r
ib_wc_t wc[MAX_SEND_WC], *p_wc, *p_free;\r
cl_qlist_t done_list;\r
NDIS_PACKET *p_packet;\r
+ uint32_t length;\r
ipoib_endpt_t *p_endpt;\r
send_buf_t *p_send_buf;\r
ip_stat_sel_t type;\r
{\r
type = IP_STAT_UCAST_BYTES;\r
}\r
- ipoib_inc_send_stat( p_port->p_adapter, type,\r
- p_wc->length - sizeof(ipoib_hdr_t) + sizeof(eth_hdr_t) );\r
+ NdisQueryPacketLength( p_packet, &length );\r
+ ipoib_inc_send_stat( p_port->p_adapter, type, length );\r
NdisMSendComplete( p_port->p_adapter->h_adapter,\r
p_packet, NDIS_STATUS_SUCCESS );\r
break;\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_TRACE_EXIT( IPOIB_DBG_ENDPT, ("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
static inline NDIS_STATUS\r
__endpt_mgr_ref(\r
IN ipoib_port_t* const p_port,\r
\r
IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
\r
+ if( !cl_memcmp( &mac, &p_port->p_adapter->mac, sizeof(mac) ) )\r
+ {\r
+ /* Discard loopback traffic. */\r
+ IPOIB_TRACE( IPOIB_DBG_WARN, ("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_TRACE( (IPOIB_DBG_ENDPT | IPOIB_DBG_INFO),\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
{\r
IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
\r
+ IPOIB_TRACE( (IPOIB_DBG_ENDPT | IPOIB_DBG_INFO),\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
av_attr.port_num = p_port->port_num;\r
av_attr.sl = 0;\r
av_attr.dlid = p_port_info->base_lid;\r
- switch( p_port_info->link_width_active )\r
- {\r
- case IB_LINK_WIDTH_ACTIVE_1X:\r
- av_attr.static_rate = IB_PATH_RECORD_RATE_2_5_GBS;\r
- break;\r
-\r
- case IB_LINK_WIDTH_ACTIVE_4X:\r
- av_attr.static_rate = IB_PATH_RECORD_RATE_10_GBS;\r
- break;\r
-\r
- case IB_LINK_WIDTH_ACTIVE_12X:\r
- av_attr.static_rate = IB_PATH_RECORD_RATE_30_GBS;\r
- break;\r
-\r
- default:\r
- cl_obj_destroy( &p_endpt->obj );\r
- return IB_INVALID_SETTING;\r
- }\r
+ av_attr.static_rate = ib_port_info_compute_rate( p_port_info );\r
av_attr.path_bits = 0;\r
status =\r
p_port->p_adapter->p_ifc->create_av( p_port->ib_mgr.h_pd, &av_attr, &p_endpt->h_av );\r
IPOIB_TRACE( IPOIB_DBG_INFO,\r
("Received port info: link width = %d.\n",\r
p_port_rec->port_info.link_width_active) );\r
+\r
+ p_port->ib_mgr.rate =\r
+ ib_port_info_compute_rate( &p_port_rec->port_info );\r
+\r
ipoib_set_rate( p_port->p_adapter,\r
- p_port_rec->port_info.link_width_active );\r
+ p_port_rec->port_info.link_width_active,\r
+ ib_port_info_get_link_speed_active( &p_port_rec->port_info ) );\r
+\r
__port_get_mcast( p_port );\r
}\r
else\r
("Instance destroying - Aborting.\n") );\r
break;\r
\r
+ case IB_TIMEOUT:\r
+ NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+ EVENT_IPOIB_PORT_INFO_TIMEOUT, 0 );\r
+ IPOIB_TRACE( IPOIB_DBG_INFO, ("Port info query timed out.\n") );\r
+ break;\r
+\r
+ case IB_REMOTE_ERROR:\r
+ NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+ EVENT_IPOIB_PORT_INFO_REJECT, 0 );\r
+ IPOIB_TRACE( IPOIB_DBG_INFO, ("Port info query rejected by SA.\n") );\r
+ break;\r
+\r
default:\r
- /* Flag the adapter as hung. */\r
- p_port->p_adapter->hung = TRUE;\r
+ NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+ EVENT_IPOIB_QUERY_PORT_INFO, 1, p_query_rec->status );\r
+ /* Hopefully we'll get an SM change event that will restart things. */\r
IPOIB_TRACE( IPOIB_DBG_INFO, ("Port info query failed.\n") );\r
}\r
\r
\r
IPOIB_ENTER( IPOIB_DBG_MCAST );\r
\r
- info.method = IB_MAD_METHOD_GETTABLE;\r
+ info.method = IB_MAD_METHOD_GET;\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
IPOIB_TRACE( IPOIB_DBG_INIT, ("Instance destroying - Aborting.\n") );\r
\r
default:\r
+ NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+ EVENT_IPOIB_BCAST_GET, 1, p_query_rec->status );\r
/* Flag the adapter as hung. */\r
p_port->p_adapter->hung = TRUE;\r
}\r
\r
IPOIB_ENTER( IPOIB_DBG_MCAST );\r
\r
+ /* Check that the rate is realizable for our port. */\r
+ if( p_port->ib_mgr.rate < (p_member_rec->rate & 0x3F) )\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_TRACE( IPOIB_DBG_WARN,\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;\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
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( p_port->p_adapter->h_al, p_port->ib_mgr.h_query );\r
}\r
else\r
{\r
+ NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+ EVENT_IPOIB_BCAST_JOIN, 1, p_mcast_rec->status );\r
/* Flag the adapter as hung. */\r
p_port->p_adapter->hung = TRUE;\r
}\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
CL_ASSERT( p_qitem == &p_endpt->lid_item );\r
}\r
cl_obj_unlock( &p_port->obj );\r
+ \r
+ /* Try to send all pending sends. */\r
+ ipoib_port_resume( p_port );\r
+\r
cl_obj_deref( &p_port->obj );\r
\r
IPOIB_EXIT( IPOIB_DBG_MCAST );\r
ib_mr_handle_t h_mr;\r
net32_t lkey;\r
\r
+ uint8_t rate;\r
ib_member_rec_t bcast_rec;\r
\r
} ipoib_ib_mgr_t;\r
ipoib_port_resume(\r
IN ipoib_port_t* const p_port );\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
#endif /* _IPOIB_PORT_H_ */\r
*********/\r
\r
\r
+/****f* IPOIB/ipoib_mac_from_mlx_guid\r
+* NAME\r
+* ipoib_mac_from_sst_guid\r
+*\r
+* DESCRIPTION\r
+* Generates an ethernet MAC address given a Mellanox port GUID.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline ib_api_status_t\r
+ipoib_mac_from_mlx_guid(\r
+ IN const net64_t port_guid,\r
+ OUT mac_addr_t* const p_mac_addr )\r
+{\r
+ const uint8_t *p_guid = (const uint8_t*)&port_guid;\r
+ uint32_t low24;\r
+\r
+ /* Port guid is in network byte order. OUI is in lower 3 bytes. */\r
+ ASSERT( p_guid[0] == 0x00 && p_guid[1] == 0x02 && p_guid[2] == 0xc9 );\r
+\r
+ if( (port_guid & CL_HTON64( 0x000000ffff0000 )) !=\r
+ CL_HTON64(0x00000002000000))\r
+ {\r
+ return IB_INVALID_GUID;\r
+ }\r
+\r
+ low24 = ((uint32_t)cl_ntoh64( port_guid ) & 0x00FFFFFF);\r
+\r
+ p_mac_addr->addr[0] = p_guid[0];\r
+ p_mac_addr->addr[1] = p_guid[1];\r
+ p_mac_addr->addr[2] = p_guid[2];\r
+ p_mac_addr->addr[3] = (uint8_t)(low24 >> 16);\r
+ p_mac_addr->addr[4] = (uint8_t)(low24 >> 8);\r
+ p_mac_addr->addr[5] = (uint8_t)low24;\r
+ \r
+ return IB_SUCCESS;\r
+}\r
+/*\r
+* PARAMETERS\r
+* port_guid\r
+* The port GUID, in network byte order, for which to generate a\r
+* MAC address.\r
+*\r
+* p_mac_addr\r
+* Pointer to a mac address in which to store the results.\r
+*\r
+* RETURN VALUES\r
+* IB_SUCCESS\r
+* The MAC address was successfully converted.\r
+*\r
+* IB_INVALID_GUID\r
+* The port GUID provided was not a known GUID format.\r
+*\r
+* NOTES\r
+* The algorithm to convert portGuid to MAC address is as per DN0074, and\r
+* assumes a 2 port HCA.\r
+*\r
+* SEE ALSO\r
+* IPOIB\r
+*********/\r
+\r
+\r
/****f* IPOIB/ipoib_mac_from_guid\r
* NAME\r
* ipoib_mac_from_guid\r
if( status == IB_SUCCESS )\r
return IB_SUCCESS;\r
}\r
-\r
+ if( p_guid[0] == 0x00 && p_guid[1] == 0x02 && p_guid[2] == 0xc9 )\r
+ {\r
+ status = ipoib_mac_from_mlx_guid( port_guid, p_mac_addr );\r
+ if( status == IB_SUCCESS )\r
+ return IB_SUCCESS;\r
+ }\r
+ \r
/* Value of zero is reserved. */\r
laa = cl_atomic_inc( &g_ipoib.laa_idx );\r
\r
*********/\r
\r
\r
-/****f* IPOIB/ipoib_guid_from_mac\r
+/****f* IPOIB/ipoib_sst_guid_from_mac\r
* NAME\r
-* ipoib_guid_from_mac\r
+* ipoib_sst_guid_from_mac\r
*\r
* DESCRIPTION\r
* Generates a port GUID given an ethernet MAC address.\r
* SYNOPSIS\r
*/\r
static inline ib_api_status_t\r
-ipoib_guid_from_mac(\r
+ipoib_sst_guid_from_mac(\r
IN const mac_addr_t mac,\r
OUT net64_t* const p_port_guid )\r
{\r
*********/\r
\r
\r
+/****f* IPOIB/ipoib_mlx_guid_from_mac\r
+* NAME\r
+* ipoib_mlx_guid_from_mac\r
+*\r
+* DESCRIPTION\r
+* Generates a port GUID given an ethernet MAC address.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline ib_api_status_t\r
+ipoib_mlx_guid_from_mac(\r
+ IN const mac_addr_t mac,\r
+ OUT net64_t* const p_port_guid )\r
+{\r
+ uint8_t *p_guid = (uint8_t*)p_port_guid;\r
+ uint32_t low24;\r
+\r
+ /* MAC address is in network byte order. OUI is in lower 3 bytes. */\r
+ if( mac.addr[0] != 0x00 || \r
+ mac.addr[1] != 0x02 || \r
+ mac.addr[2] != 0xc9 )\r
+ {\r
+ return IB_INVALID_GUID;\r
+ }\r
+\r
+ low24 = mac.addr[3] << 16 || mac.addr[4] << 8 || mac.addr[5];\r
+\r
+ /* OUI */\r
+ p_guid[0] = mac.addr[0];\r
+ p_guid[1] = mac.addr[1];\r
+ p_guid[2] = mac.addr[2];\r
+ p_guid[3] = 0x02;\r
+ p_guid[4] = 0x00;\r
+ /* Serial Number */\r
+ p_guid[5] = (uint8_t)(low24 >> 16);\r
+ p_guid[6] = (uint8_t)(low24 >> 8);\r
+ p_guid[7] = (uint8_t)low24;\r
+ \r
+ return IB_SUCCESS;\r
+}\r
+/*\r
+* PARAMETERS\r
+* port_guid\r
+* The port GUID, in network byte order, for which to generate a\r
+* MAC address.\r
+*\r
+* p_mac_addr\r
+* Pointer to a mac address in which to store the results.\r
+*\r
+* RETURN VALUES\r
+* IB_SUCCESS\r
+* The MAC address was successfully converted.\r
+*\r
+* IB_INVALID_GUID\r
+* The port GUID provided was not a known GUID format.\r
+*\r
+* NOTES\r
+* The algorithm to convert portGuid to MAC address is as \r
+*\r
+* SEE ALSO\r
+* IPOIB\r
+*********/\r
\r
\r
#ifdef __cplusplus\r
-; SilverStorm Technologies Internet Protocol over InfiniBand Adapter\r
+; OpenIB Internet Protocol over InfiniBand Adapter\r
; Copyright 2005 SilverStorm Technologies all Rights Reserved.\r
\r
[Version]\r
Signature = "$Windows NT$"\r
Class = Net\r
ClassGUID = {4d36e972-e325-11ce-bfc1-08002be10318}\r
-Provider = %SST%\r
-CatalogFile = netipoib.cat\r
-DriverVer=09/01/2005,3.0.0036.0\r
+Provider = %OPENIB%\r
+DriverVer=01/12/2006,1.0.0000.213\r
\r
[Manufacturer]\r
-%SST% = SST,ntx86,ntamd64,ntia64\r
+%OPENIB% = OPENIB,ntx86,ntamd64,ntia64\r
\r
[ControlFlags]\r
ExcludeFromSelect = IBA\IPoIB\r
\r
-[SST]\r
+[OPENIB]\r
; empty since we don't support W9x/Me\r
\r
-[SST.ntx86]\r
-%IpoibDesc% = Ipoib.DDInstall, IBA\IPoIB ; SilverStorm Internet Protocol over InfiniBand Adapter\r
+[OPENIB.ntx86]\r
+%IpoibDesc% = Ipoib.DDInstall, IBA\IPoIB ; Internet Protocol over InfiniBand Adapter\r
\r
-[SST.ntamd64]\r
-%IpoibDesc% = Ipoib.DDInstall, IBA\IPoIB ; SilverStorm Internet Protocol over InfiniBand Adapter\r
+[OPENIB.ntamd64]\r
+%IpoibDesc% = Ipoib.DDInstall, IBA\IPoIB ; Internet Protocol over InfiniBand Adapter\r
\r
-[SST.ntia64]\r
-%IpoibDesc% = Ipoib.DDInstall, IBA\IPoIB ; SilverStorm Internet Protocol over InfiniBand Adapter\r
+[OPENIB.ntia64]\r
+%IpoibDesc% = Ipoib.DDInstall, IBA\IPoIB ; Internet Protocol over InfiniBand Adapter\r
\r
[Ipoib.DDInstall.ntx86]\r
Characteristics = 0x81 ; NCF_HAS_UI | NCF_VIRTUAL\r
\r
[IpoibAddReg]\r
HKR, Ndi, Service, 0, "ipoib"\r
-HKR, Ndi\Interfaces, UpperRange, 0, "ndis5_ip"\r
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"\r
HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"\r
\r
HKR, Ndi\Params\RqDepth, ParamDesc, 0, "Receive Queue Depth"\r
ErrorControl = 1 ;%SERVICE_ERROR_NORMAL%\r
ServiceBinary = %12%\ipoib.sys\r
LoadOrderGroup = NDIS\r
+AddReg = Ipoib.ParamsReg\r
+\r
+[Ipoib.ParamsReg]\r
+HKR,"Parameters","DebugFlags",%REG_DWORD_NO_CLOBBER%,0x80000000\r
\r
[IpoibEventLog]\r
AddReg = IpoibAddEventLogReg\r
\r
[IpoibAddEventLogReg]\r
-HKR, , EventMessageFile, 0x00020000, "%%SystemRoot%%\System32\netevent.dll"\r
+HKR, , EventMessageFile, 0x00020000, "%%SystemRoot%%\System32\netevent.dll";"%%SystemRoot%%\System32\drivers\ipoib.sys"\r
HKR, , TypesSupported, 0x00010001, 7\r
\r
\r
DefaultDestDir = %DIRID_SYSTEM%\r
\r
[Strings]\r
-SST = "SilverStorm Technologies"\r
-IpoibDesc = "SilverStorm IPoIB Adapter"\r
+OPENIB = "OpenIB Alliance"\r
+IpoibDesc = "OpenIB IPoIB Adapter"\r
IpoibServiceDispName = "IPoIB"\r
-IcsDisk1 = "SilverStorm Systems IPoIB Disk #1"\r
+IcsDisk1 = "OpenIB IPoIB Disk #1"\r
DIRID_SYSTEM = 11\r
DIRID_DRIVERS = 12\r
DIRID_SYSTEM_X86 = 16425\r
+REG_DWORD_NO_CLOBBER = 0x00010003\r