\r
ref_al_obj( &h_mcast->obj );\r
status = al_send_sa_req(\r
- &h_mcast->sa_dereg_req, h_mcast->port_guid, 500, 0, &sa_mad_data );\r
+ &h_mcast->sa_dereg_req, h_mcast->port_guid, 500, 0, &sa_mad_data, 0 );\r
if( status != IB_SUCCESS )\r
deref_al_obj( &h_mcast->obj );\r
\r
\r
p_mcast->state = SA_REG_STARTING;\r
status = al_send_sa_req( &p_mcast->sa_reg_req, p_mcast->port_guid,\r
- p_mcast_req->timeout_ms, p_mcast_req->retry_cnt, &sa_mad_data );\r
+ p_mcast_req->timeout_ms, p_mcast_req->retry_cnt, &sa_mad_data, 0 );\r
\r
CL_EXIT( AL_DBG_MCAST, g_al_dbg_lvl );\r
return status;\r
static ib_api_status_t\r
query_sa(\r
IN al_query_t *p_query,\r
- IN const ib_query_req_t* const p_query_req );\r
+ IN const ib_query_req_t* const p_query_req,\r
+ IN const ib_al_flags_t flags );\r
\r
void\r
query_req_cb(\r
IN al_sa_req_t *p_sa_req,\r
IN ib_mad_element_t *p_mad_response );\r
\r
-static void\r
-__free_query(\r
- IN OUT al_query_t *p_query );\r
-\r
-\r
\r
ib_api_status_t\r
ib_query(\r
{\r
al_query_t *p_query;\r
ib_api_status_t status;\r
- cl_status_t cl_status;\r
- boolean_t sync;\r
\r
CL_ENTER( AL_DBG_QUERY, g_al_dbg_lvl );\r
\r
return IB_INSUFFICIENT_MEMORY;\r
}\r
\r
- /* Check for synchronous operation. */\r
- p_query->flags = p_query_req->flags;\r
- cl_event_construct( &p_query->event );\r
- sync = ( (p_query->flags & IB_FLAGS_SYNC) == IB_FLAGS_SYNC );\r
- if( sync )\r
- {\r
- cl_status = cl_event_init( &p_query->event, TRUE );\r
- if( cl_status != CL_SUCCESS )\r
- {\r
- status = ib_convert_cl_status( cl_status );\r
- CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl,\r
- ("cl_init_event failed: %s\n", ib_get_err_str(status) ) );\r
- __free_query( p_query );\r
- return status;\r
- }\r
- }\r
-\r
/* Copy the query context information. */\r
p_query->sa_req.pfn_sa_req_cb = query_req_cb;\r
p_query->sa_req.user_context = p_query_req->query_context;\r
/* Track the query with the AL instance. */\r
al_insert_query( h_al, p_query );\r
\r
+ /*\r
+ * Set the query handle now so that users that do sync queries\r
+ * can also cancel the queries.\r
+ */\r
+ if( ph_query )\r
+ *ph_query = p_query;\r
+\r
/* Issue the MAD to the SA. */\r
- status = query_sa( p_query, (ib_query_req_t*)p_query_req );\r
- if( status == IB_SUCCESS )\r
- {\r
- /*\r
- * Set the query handle now so that users that do sync queries\r
- * can also cancel the queries.\r
- */\r
- if( ph_query )\r
- *ph_query = p_query;\r
- /* If synchronous, wait for the completion. */\r
- if( sync )\r
- {\r
- do\r
- {\r
- cl_status = cl_event_wait_on(\r
- &p_query->event, EVENT_NO_TIMEOUT, AL_WAIT_ALERTABLE );\r
- } while( cl_status == CL_NOT_DONE );\r
- CL_ASSERT( cl_status == CL_SUCCESS );\r
- }\r
- }\r
- else if( status != IB_INVALID_GUID )\r
+ status = query_sa( p_query, p_query_req, p_query_req->flags );\r
+ if( status != IB_SUCCESS && status != IB_INVALID_GUID )\r
{\r
CL_TRACE( AL_DBG_ERROR, g_al_dbg_lvl,\r
("query_sa failed: %s\n", ib_get_err_str(status) ) );\r
}\r
\r
/* Cleanup from issuing the query if it failed or was synchronous. */\r
- if( ( status != IB_SUCCESS ) || sync )\r
+ if( status != IB_SUCCESS )\r
{\r
al_remove_query( p_query );\r
- __free_query( p_query );\r
+ cl_free( p_query );\r
}\r
\r
CL_EXIT( AL_DBG_QUERY, g_al_dbg_lvl );\r
static ib_api_status_t\r
query_sa(\r
IN al_query_t *p_query,\r
- IN const ib_query_req_t* const p_query_req )\r
+ IN const ib_query_req_t* const p_query_req,\r
+ IN const ib_al_flags_t flags )\r
{\r
ib_user_query_t sa_req, *p_sa_req;\r
union _query_sa_recs\r
\r
status = al_send_sa_req(\r
&p_query->sa_req, p_query_req->port_guid, p_query_req->timeout_ms,\r
- p_query_req->retry_cnt, p_sa_req );\r
+ p_query_req->retry_cnt, p_sa_req, flags );\r
CL_EXIT( AL_DBG_QUERY, g_al_dbg_lvl );\r
return status;\r
}\r
/* Notify the user of the result. */\r
p_query->pfn_query_cb( &query_rec );\r
\r
- /* Check for synchronous operation. */\r
- if( (p_query->flags & IB_FLAGS_SYNC) == IB_FLAGS_SYNC )\r
- {\r
- cl_event_signal( &p_query->event );\r
- }\r
- else\r
- {\r
- /* Cleanup from issuing the query. */\r
- al_remove_query( p_query );\r
- __free_query( p_query );\r
- }\r
+ /* Cleanup from issuing the query. */\r
+ al_remove_query( p_query );\r
+ cl_free( p_query );\r
\r
CL_EXIT( AL_DBG_QUERY, g_al_dbg_lvl );\r
}\r
-\r
-\r
-\r
-static void\r
-__free_query(\r
- IN OUT al_query_t *p_query )\r
-{\r
- CL_ASSERT( p_query );\r
-\r
- cl_event_destroy( &p_query->event );\r
- cl_free( p_query );\r
-}\r
sa_req_svc_t *p_sa_req_svc; /* For cancellation */\r
ib_mad_element_t *p_mad_response;\r
ib_mad_element_t *p_mad_request; /* For cancellation */\r
+ KEVENT *p_sync_event;\r
#else /* defined( CL_KERNEL ) */\r
uint64_t hdl;\r
ual_send_sa_req_ioctl_t ioctl;\r
{\r
al_sa_req_t sa_req; /* Must be first. */\r
\r
- /* Used to perform synchronous requests. */\r
- ib_al_flags_t flags;\r
- cl_event_t event;\r
-\r
ib_al_handle_t h_al;\r
ib_pfn_query_cb_t pfn_query_cb;\r
ib_query_type_t query_type;\r
IN const net64_t port_guid,\r
IN const uint32_t timeout_ms,\r
IN const uint32_t retry_cnt,\r
- IN const ib_user_query_t* const p_sa_req_data );\r
+ IN const ib_user_query_t* const p_sa_req_data,\r
+ IN const ib_al_flags_t flags );\r
\r
#if defined( CL_KERNEL )\r
static __inline void\r
{\r
ib_reg_svc_handle_t h_reg_svc;\r
\r
- h_reg_svc = PARENT_STRUCT ( p_sa_req, al_reg_svc_t, sa_req );\r
+ /*\r
+ * Note that we come into this callback with a reference\r
+ * on the registration object.\r
+ */\r
+ h_reg_svc = PARENT_STRUCT( p_sa_req, al_reg_svc_t, sa_req );\r
\r
if( p_mad_response )\r
ib_put_mad( p_mad_response );\r
\r
- deref_al_obj( &h_reg_svc->obj );\r
+ h_reg_svc->obj.pfn_destroy( &h_reg_svc->obj, NULL );\r
}\r
\r
\r
sa_mad_data.comp_mask = ~CL_CONST64(0);\r
\r
if( al_send_sa_req( &h_reg_svc->sa_req, h_reg_svc->port_guid,\r
- 500, 0, &sa_mad_data ) != IB_SUCCESS )\r
+ 500, 0, &sa_mad_data, 0 ) != IB_SUCCESS )\r
{\r
/* Cleanup from the registration. */\r
deref_al_obj( &h_reg_svc->obj );\r
\r
h_reg_svc->pfn_reg_svc_cb( ®_svc_rec );\r
\r
- /* Check for synchronous operation. */\r
- if( (h_reg_svc->flags & IB_FLAGS_SYNC) == IB_FLAGS_SYNC )\r
- cl_event_signal( &h_reg_svc->event );\r
-\r
- /* Release the reference taken when issuing the request. */\r
- deref_al_obj( &h_reg_svc->obj );\r
+ if( p_sa_req->status != IB_SUCCESS )\r
+ {\r
+ h_reg_svc->obj.pfn_destroy( &h_reg_svc->obj, NULL );\r
+ }\r
+ else\r
+ {\r
+ /* Release the reference taken when issuing the request. */\r
+ deref_al_obj( &h_reg_svc->obj );\r
+ }\r
}\r
\r
\r
h_sa_reg = PARENT_STRUCT( p_obj, al_reg_svc_t, obj );\r
\r
destroy_al_obj( p_obj );\r
- cl_event_destroy( &h_sa_reg->event );\r
cl_free( h_sa_reg );\r
\r
AL_EXIT( AL_DBG_SA_REQ );\r
IN const ib_reg_svc_req_t* const p_reg_svc_req )\r
{\r
ib_user_query_t sa_mad_data;\r
- ib_api_status_t status;\r
\r
/* Set the request information. */\r
h_reg_svc->sa_req.pfn_sa_req_cb = reg_svc_req_cb;\r
sa_mad_data.comp_mask = p_reg_svc_req->svc_data_mask;\r
sa_mad_data.p_attr = &h_reg_svc->svc_rec;\r
\r
- status = al_send_sa_req( &h_reg_svc->sa_req, h_reg_svc->port_guid,\r
- p_reg_svc_req->timeout_ms, p_reg_svc_req->retry_cnt, &sa_mad_data );\r
- return status;\r
+ return al_send_sa_req( &h_reg_svc->sa_req, h_reg_svc->port_guid,\r
+ p_reg_svc_req->timeout_ms, p_reg_svc_req->retry_cnt, &sa_mad_data,\r
+ p_reg_svc_req->flags );\r
}\r
\r
\r
{\r
ib_reg_svc_handle_t h_sa_reg = NULL;\r
ib_api_status_t status;\r
- cl_status_t cl_status;\r
\r
AL_ENTER( AL_DBG_SA_REQ );\r
\r
return IB_INSUFFICIENT_MEMORY;\r
}\r
\r
- h_sa_reg->flags = p_reg_svc_req->flags;\r
- cl_event_construct( &h_sa_reg->event );\r
construct_al_obj( &h_sa_reg->obj, AL_OBJ_TYPE_H_SA_REG );\r
\r
status = init_al_obj( &h_sa_reg->obj, p_reg_svc_req->svc_context, TRUE,\r
return status;\r
}\r
\r
- /* Check for synchronous operation. */\r
- if( h_sa_reg->flags & IB_FLAGS_SYNC )\r
- {\r
- cl_status = cl_event_init( &h_sa_reg->event, TRUE );\r
- if( cl_status != CL_SUCCESS )\r
- {\r
- status = ib_convert_cl_status( cl_status );\r
- AL_TRACE_EXIT( AL_DBG_ERROR,\r
- ("cl_init_event failed: %s\n", ib_get_err_str(status)) );\r
- h_sa_reg->obj.pfn_destroy( &h_sa_reg->obj, NULL );\r
- return status;\r
- }\r
- }\r
-\r
/* Store the port GUID on which to issue the request. */\r
h_sa_reg->port_guid = p_reg_svc_req->port_guid;\r
\r
\r
/* Issue the MAD to the SA. */\r
status = sa_reg_svc( h_sa_reg, p_reg_svc_req );\r
- if( status == IB_SUCCESS )\r
- {\r
- /* If synchronous, wait for the completion. */\r
- if( h_sa_reg->flags & IB_FLAGS_SYNC )\r
- {\r
- do\r
- {\r
- cl_status = cl_event_wait_on(\r
- &h_sa_reg->event, EVENT_NO_TIMEOUT, AL_WAIT_ALERTABLE );\r
- } while( cl_status == CL_NOT_DONE );\r
- CL_ASSERT( cl_status == CL_SUCCESS );\r
-\r
- /* Cleanup from issuing the request if it failed. */\r
- if( h_sa_reg->state == SA_REG_ERROR )\r
- {\r
- status = h_sa_reg->req_status;\r
- /* The callback released the reference from init_al_obj. */\r
- ref_al_obj( &h_sa_reg->obj );\r
- }\r
- }\r
- }\r
- else\r
+ if( status != IB_SUCCESS )\r
{\r
AL_TRACE( AL_DBG_ERROR,\r
("sa_reg_svc failed: %s\n", ib_get_err_str(status) ) );\r
h_sa_reg->state = SA_REG_ERROR;\r
- }\r
\r
- if( status != IB_SUCCESS )\r
h_sa_reg->obj.pfn_destroy( &h_sa_reg->obj, NULL );\r
+ }\r
else\r
+ {\r
*ph_reg_svc = h_sa_reg;\r
+ }\r
\r
AL_EXIT( AL_DBG_SA_REQ );\r
return status;\r
/* Additional status information returned in the registration response. */\r
ib_net16_t resp_status;\r
\r
- /* Used to perform synchronous requests. */\r
- ib_al_flags_t flags;\r
- cl_event_t event;\r
-\r
al_sa_reg_state_t state;\r
ib_pfn_reg_svc_cb_t pfn_reg_svc_cb;\r
\r
p_context = p_open_context;\r
\r
p_io_stack = IoGetCurrentIrpStackLocation( h_ioctl );\r
- if( (uintn_t)p_io_stack->FileObject->FsContext2 != AL_OBJ_TYPE_SA_REQ_SVC )\r
+ /*\r
+ * We support SA requests coming in either through the main file object\r
+ * or the async file handle.\r
+ */\r
+ if( p_io_stack->FileObject->FsContext2 &&\r
+ (uintn_t)p_io_stack->FileObject->FsContext2 != AL_OBJ_TYPE_SA_REQ_SVC )\r
{\r
AL_TRACE_EXIT( AL_DBG_ERROR,\r
("Invalid file object type for request: %d\n",\r
/* Synchronize with callbacks. */\r
cl_spinlock_acquire( &p_context->h_al->obj.lock );\r
\r
+ /*\r
+ * We never pass the user-mode flag when sending SA requests - the\r
+ * I/O manager will perform all synchronization to make this IRP sync\r
+ * if it needs to.\r
+ */\r
ib_status = al_send_sa_req( p_sa_req, p_ioctl->in.port_guid,\r
p_ioctl->in.timeout_ms, p_ioctl->in.retry_cnt,\r
- &p_ioctl->in.sa_req );\r
+ &p_ioctl->in.sa_req, 0 );\r
if( ib_status == IB_SUCCESS )\r
{\r
/* Hold a reference on the proxy context until the request completes. */\r
IN const net64_t port_guid,\r
IN const uint32_t timeout_ms,\r
IN const uint32_t retry_cnt,\r
- IN const ib_user_query_t* const p_sa_req_data )\r
+ IN const ib_user_query_t* const p_sa_req_data,\r
+ IN const ib_al_flags_t flags )\r
{\r
ib_api_status_t status;\r
sa_req_svc_t *p_sa_req_svc;\r
ib_mad_element_t *p_mad_request;\r
ib_mad_t *p_mad_hdr;\r
ib_sa_mad_t *p_sa_mad;\r
+ KEVENT event;\r
\r
CL_ENTER( AL_DBG_SA_REQ, g_al_dbg_lvl );\r
- \r
+\r
+ if( flags & IB_FLAGS_SYNC )\r
+ {\r
+ if( !cl_is_blockable() )\r
+ {\r
+ AL_TRACE_EXIT( AL_DBG_ERROR,\r
+ ("Thread context not blockable\n") );\r
+ return IB_INVALID_SETTING;\r
+ }\r
+\r
+ KeInitializeEvent( &event, NotificationEvent, FALSE );\r
+ p_sa_req->p_sync_event = &event;\r
+ }\r
+ else\r
+ {\r
+ p_sa_req->p_sync_event = NULL;\r
+ }\r
+\r
/* Locate the sa_req service to issue the sa_req on. */\r
p_sa_req->p_sa_req_svc = acquire_sa_req_svc( port_guid );\r
if( !p_sa_req->p_sa_req_svc )\r
ib_put_mad( p_mad_request );\r
deref_al_obj( &p_sa_req->p_sa_req_svc->obj );\r
}\r
+ else if( flags & IB_FLAGS_SYNC )\r
+ {\r
+ /* Wait for the MAD completion. */\r
+ KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, NULL );\r
+ }\r
\r
CL_EXIT( AL_DBG_SA_REQ, g_al_dbg_lvl );\r
return status;\r
{\r
al_sa_req_t *p_sa_req;\r
sa_req_svc_t *p_sa_req_svc;\r
+ KEVENT *p_sync_event;\r
\r
CL_ENTER( AL_DBG_SA_REQ, g_al_dbg_lvl );\r
\r
\r
p_sa_req = p_request_mad->send_context1;\r
p_sa_req_svc = p_sa_req->p_sa_req_svc;\r
+ p_sync_event = p_sa_req->p_sync_event;\r
\r
p_sa_req->status = convert_wc_status( p_request_mad->status );\r
p_sa_req->pfn_sa_req_cb( p_sa_req, NULL );\r
+ if( p_sync_event )\r
+ KeSetEvent( p_sync_event, 0, FALSE );\r
deref_al_obj( &p_sa_req_svc->obj );\r
}\r
\r
al_sa_req_t *p_sa_req;\r
sa_req_svc_t *p_sa_req_svc;\r
ib_sa_mad_t *p_sa_mad;\r
+ KEVENT *p_sync_event;\r
\r
CL_ENTER( AL_DBG_SA_REQ, g_al_dbg_lvl );\r
\r
\r
p_sa_req = p_mad_response->send_context1;\r
p_sa_req_svc = p_sa_req->p_sa_req_svc;\r
+ p_sync_event = p_sa_req->p_sync_event;\r
\r
//*** check for SA redirection...\r
\r
/* Notify the requestor of the result. */\r
CL_TRACE( AL_DBG_SA_REQ, g_al_dbg_lvl, ("notifying user\n") );\r
p_sa_req->pfn_sa_req_cb( p_sa_req, p_mad_response );\r
+ if( p_sync_event )\r
+ KeSetEvent( p_sync_event, 0, FALSE );\r
deref_al_obj( &p_sa_req_svc->obj );\r
\r
CL_EXIT( AL_DBG_SA_REQ, g_al_dbg_lvl );\r
}\r
\r
\r
-\r
ib_api_status_t\r
al_send_sa_req(\r
IN al_sa_req_t *p_sa_req,\r
IN const net64_t port_guid,\r
IN const uint32_t timeout_ms,\r
IN const uint32_t retry_cnt,\r
- IN const ib_user_query_t* const p_sa_req_data )\r
+ IN const ib_user_query_t* const p_sa_req_data,\r
+ IN const ib_al_flags_t flags )\r
{\r
ib_api_status_t status;\r
+ HANDLE h_dev;\r
+ DWORD ret_bytes;\r
\r
AL_ENTER( AL_DBG_QUERY );\r
\r
p_sa_req->ioctl.in.ph_sa_req = &p_sa_req->hdl;\r
p_sa_req->ioctl.in.p_status = &p_sa_req->status;\r
\r
- if( !DeviceIoControl( gp_sa_req_mgr->h_sa_dev, UAL_SEND_SA_REQ,\r
+ if( flags & IB_FLAGS_SYNC )\r
+ h_dev = g_al_device;\r
+ else\r
+ h_dev = gp_sa_req_mgr->h_sa_dev;\r
+\r
+ if( !DeviceIoControl( h_dev, UAL_SEND_SA_REQ,\r
&p_sa_req->ioctl.in, sizeof(p_sa_req->ioctl.in),\r
&p_sa_req->ioctl.out, sizeof(p_sa_req->ioctl.out),\r
NULL, &p_sa_req->ov ) )\r
}\r
else\r
{\r
- CL_ASSERT( GetLastError() == ERROR_IO_PENDING );\r
- status = IB_ERROR;\r
+ /* Completed synchronously. */\r
+ if( GetOverlappedResult( h_dev, &p_sa_req->ov, &ret_bytes, FALSE ) )\r
+ {\r
+ status = IB_SUCCESS;\r
+ /* Process the completion. */\r
+ sa_req_cb( 0, ret_bytes, &p_sa_req->ov );\r
+ }\r
+ else\r
+ {\r
+ sa_req_cb( GetLastError(), 0, &p_sa_req->ov );\r
+ status = IB_ERROR;\r
+ }\r
}\r
\r
AL_EXIT( AL_DBG_QUERY );\r
}\r
\r
\r
-\r
void CALLBACK\r
sa_req_cb(\r
IN DWORD error_code,\r