[ofw] [PATCH 11/12] ci/events: support multiple event handlers

Sean Hefty sean.hefty at intel.com
Mon Jul 21 09:35:52 PDT 2008


Modify the channel interface to allow clients to register different
event handlers.  This is in addition to the event handler specified when
opening the channel adapter.  The latter can be replaced in a subsequent
patch, but is left as is to minimize changes.

This change allows the channel interface to support multiple direct
call clients, such as winverbs and ibal.

Signed-off-by: Sean Hefty <sean.hefty at intel.com>
---
The existing call structures were left in place, but this patch allows the HCAs
to invoke event handlers directly, rather than going through an intermediate driver,
such as ibal.

diff -up -r -X trunk\docs\dontdiff.txt -I '\$Id:' trunk/hw/mlx4/kernel/hca/ca.c branches\winverbs/hw/mlx4/kernel/hca/ca.c
--- trunk/hw/mlx4/kernel/hca/ca.c	2008-07-11 14:29:30.507125000 -0700
+++ branches\winverbs/hw/mlx4/kernel/hca/ca.c	2008-07-14 15:49:53.038453100 -0700
@@ -99,6 +99,32 @@ err_set_cb:
 	return status;
 }
 
+static void
+mlnx_register_event_handler (
+	IN		const	ib_ca_handle_t				h_ca,
+	IN				ci_event_handler_t*			p_reg)
+{
+	mlnx_hca_t *p_hca = (mlnx_hca_t *) h_ca;
+	KIRQL irql;
+
+	KeAcquireSpinLock(&p_hca->event_list_lock, &irql);
+	InsertTailList(&p_hca->event_list, &p_reg->entry);
+	KeReleaseSpinLock(&p_hca->event_list_lock, irql);
+}
+
+static void
+mlnx_unregister_event_handler (
+	IN		const	ib_ca_handle_t				h_ca,
+	IN				ci_event_handler_t*			p_reg)
+{
+	mlnx_hca_t *p_hca = (mlnx_hca_t *) h_ca;
+	KIRQL irql;
+
+	KeAcquireSpinLock(&p_hca->event_list_lock, &irql);
+	RemoveEntryList(&p_reg->entry);
+	KeReleaseSpinLock(&p_hca->event_list_lock, irql);
+}
+
 ib_api_status_t
 mlnx_query_ca (
 	IN		const	ib_ca_handle_t				h_ca,
@@ -407,6 +433,8 @@ mlnx_ca_if(
 	p_interface->modify_ca = mlnx_modify_ca; 
 	p_interface->query_ca = mlnx_query_ca;
 	p_interface->close_ca = mlnx_close_ca;
+	p_interface->register_event_handler = mlnx_register_event_handler;
+	p_interface->unregister_event_handler = mlnx_unregister_event_handler;
 }
 
 void
diff -up -r -X trunk\docs\dontdiff.txt -I '\$Id:' trunk/hw/mlx4/kernel/hca/data.c branches\winverbs/hw/mlx4/kernel/hca/data.c
--- trunk/hw/mlx4/kernel/hca/data.c	2008-07-11 14:29:30.632125000 -0700
+++ branches\winverbs/hw/mlx4/kernel/hca/data.c	2008-07-14 16:00:38.494523800 -0700
@@ -298,10 +298,12 @@ void ca_event_handler(struct ib_event *e
 {
 	mlnx_hca_t *p_hca = (mlnx_hca_t *)context;
 	ib_event_rec_t event_rec;
+	LIST_ENTRY *entry;
+	ci_event_handler_t *event_handler;
 
 	// prepare parameters
-	event_rec.context = (void *)p_hca->ca_context;
 	event_rec.type = ev->event;
+	event_rec.port_number = ev->element.port_num;
 	if (event_rec.type > IB_AE_UNKNOWN) {
 		// CL_ASSERT(0); // This shouldn't happen
 		HCA_PRINT(TRACE_LEVEL_ERROR,HCA_DBG_SHIM,("Unmapped E_EV_CA event of type 0x%x. Replaced by 0x%x
(IB_AE_LOCAL_FATAL)\n", 
@@ -310,9 +312,20 @@ void ca_event_handler(struct ib_event *e
 	}
 
 	// call the user callback
-	if (p_hca && p_hca->async_cb_p)
+	KeAcquireSpinLockAtDpcLevel(&p_hca->event_list_lock);
+	for (entry = p_hca->event_list.Flink; entry != &p_hca->event_list;
+		 entry = entry->Flink) {
+
+		event_handler = CONTAINING_RECORD(entry, ci_event_handler_t, entry);
+		event_rec.context = (void *) event_handler;
+		event_handler->pfn_async_event_cb(&event_rec);
+	}
+	KeReleaseSpinLockFromDpcLevel(&p_hca->event_list_lock);
+
+	if (p_hca && p_hca->async_cb_p) {
+		event_rec.context = (void *)p_hca->ca_context;
 		(p_hca->async_cb_p)(&event_rec);
-	else {
+	} else {
 		HCA_PRINT(TRACE_LEVEL_ERROR ,HCA_DBG_SHIM ,("Incorrect context. Async callback was not invoked\n"));
 	}
 }
diff -up -r -X trunk\docs\dontdiff.txt -I '\$Id:' trunk/hw/mlx4/kernel/hca/data.h branches\winverbs/hw/mlx4/kernel/hca/data.h
--- trunk/hw/mlx4/kernel/hca/data.h	2008-07-11 14:29:30.694625000 -0700
+++ branches\winverbs/hw/mlx4/kernel/hca/data.h	2008-07-14 15:57:56.825650200 -0700
@@ -155,6 +155,8 @@ typedef struct _mlnx_hca_t {
 	net64_t			guid;					// HCA node Guid
 	uint32_t			hw_ver;				// HCA HW version
 	// HOB
+	KSPIN_LOCK			event_list_lock;
+	LIST_ENTRY			event_list;
 	ci_async_event_cb_t async_cb_p;
 	const void          *ca_context;
 	void                *cl_device_h;
diff -up -r -X trunk\docs\dontdiff.txt -I '\$Id:' trunk/hw/mlx4/kernel/hca/drv.c branches\winverbs/hw/mlx4/kernel/hca/drv.c
--- trunk/hw/mlx4/kernel/hca/drv.c	2008-05-20 00:38:35.973625000 -0700
+++ branches\winverbs/hw/mlx4/kernel/hca/drv.c	2008-07-14 16:07:13.574005400 -0700
@@ -648,7 +648,9 @@ EvtDevicePrepareHardware(
 	}
 	p_fdo->bus_ib_ifc_taken = TRUE;
 	p_fdo->bus_ib_ifc.p_ibdev->x.p_fdo = p_fdo;
-	
+
+	InitializeListHead(&p_fdo->hca.event_list);
+	KeInitializeSpinLock(&p_fdo->hca.event_list_lock);
 
 	/* get node GUID */
 	err = __get_dev_info( p_fdo, &p_fdo->hca.guid, &p_fdo->hca.hw_ver );
diff -up -r -X trunk\docs\dontdiff.txt -I '\$Id:' trunk/hw/mthca/kernel/hca_data.c branches\winverbs/hw/mthca/kernel/hca_data.c
--- trunk/hw/mthca/kernel/hca_data.c	2008-07-11 14:29:31.069625000 -0700
+++ branches\winverbs/hw/mthca/kernel/hca_data.c	2008-07-14 12:17:01.953074900 -0700
@@ -335,10 +335,12 @@ void ca_event_handler(struct ib_event *e
 {
 	mlnx_hob_t *hob_p = (mlnx_hob_t *)context;
 	ib_event_rec_t event_rec;
+	LIST_ENTRY *entry;
+	ci_event_handler_t *event_handler;
 
 	// prepare parameters
-	event_rec.context = (void *)hob_p->ca_context;
 	event_rec.type = ev->event;
+	event_rec.port_number = ev->element.port_num;
 	if (event_rec.type > IB_AE_UNKNOWN) {
 		// CL_ASSERT(0); // This shouldn't happen
 		HCA_PRINT(TRACE_LEVEL_ERROR,HCA_DBG_SHIM,("Unmapped E_EV_CA event of type 0x%x. Replaced by 0x%x
(IB_AE_LOCAL_FATAL)\n", 
@@ -347,9 +349,20 @@ void ca_event_handler(struct ib_event *e
 	}
 
 	// call the user callback
-	if (hob_p && hob_p->async_cb_p)
+	KeAcquireSpinLockAtDpcLevel(&hob_p->event_list_lock);
+	for (entry = hob_p->event_list.Flink; entry != &hob_p->event_list;
+		 entry = entry->Flink) {
+
+		event_handler = CONTAINING_RECORD(entry, ci_event_handler_t, entry);
+		event_rec.context = (void *) event_handler;
+		event_handler->pfn_async_event_cb(&event_rec);
+	}
+	KeReleaseSpinLockFromDpcLevel(&hob_p->event_list_lock);
+
+	if (hob_p && hob_p->async_cb_p) {
+		event_rec.context = (void *)hob_p->ca_context;
 		(hob_p->async_cb_p)(&event_rec);
-	else {
+	} else {
 		HCA_PRINT(TRACE_LEVEL_ERROR ,HCA_DBG_SHIM ,("Incorrect context. Async callback was not invoked\n"));
 	}
 }
diff -up -r -X trunk\docs\dontdiff.txt -I '\$Id:' trunk/hw/mthca/kernel/hca_data.h branches\winverbs/hw/mthca/kernel/hca_data.h
--- trunk/hw/mthca/kernel/hca_data.h	2008-07-11 14:29:31.194625000 -0700
+++ branches\winverbs/hw/mthca/kernel/hca_data.h	2008-07-14 11:27:09.887729900 -0700
@@ -171,6 +171,8 @@ typedef struct _attr_cache
 
 typedef struct _ib_ca {
 	ENUM_MARK           mark;
+	KSPIN_LOCK			event_list_lock;
+	LIST_ENTRY			event_list;
 	ci_async_event_cb_t async_cb_p;
 	const void          *ca_context;
 	void                *cl_device_h;
diff -up -r -X trunk\docs\dontdiff.txt -I '\$Id:' trunk/hw/mthca/kernel/hca_verbs.c branches\winverbs/hw/mthca/kernel/hca_verbs.c
--- trunk/hw/mthca/kernel/hca_verbs.c	2008-07-11 14:29:31.475875000 -0700
+++ branches\winverbs/hw/mthca/kernel/hca_verbs.c	2008-07-14 15:17:33.205726700 -0700
@@ -115,6 +115,32 @@ err_set_cb:
 	return status;
 }
 
+static void
+mlnx_register_event_handler (
+	IN		const	ib_ca_handle_t				h_ca,
+	IN				ci_event_handler_t*			p_reg)
+{
+	mlnx_hob_t *hob_p = (mlnx_hob_t *) h_ca;
+	KIRQL irql;
+
+	KeAcquireSpinLock(&hob_p->event_list_lock, &irql);
+	InsertTailList(&hob_p->event_list, &p_reg->entry);
+	KeReleaseSpinLock(&hob_p->event_list_lock, irql);
+}
+
+static void
+mlnx_unregister_event_handler (
+	IN		const	ib_ca_handle_t				h_ca,
+	IN				ci_event_handler_t*			p_reg)
+{
+	mlnx_hob_t *hob_p = (mlnx_hob_t *) h_ca;
+	KIRQL irql;
+
+	KeAcquireSpinLock(&hob_p->event_list_lock, &irql);
+	RemoveEntryList(&p_reg->entry);
+	KeReleaseSpinLock(&hob_p->event_list_lock, irql);
+}
+
 ib_api_status_t
 mlnx_query_ca (
 	IN		const	ib_ca_handle_t FUNC_PTR64				h_ca,
@@ -1654,6 +1680,8 @@ setup_ci_interface(
 	p_interface->close_ca = mlnx_close_ca;
 	p_interface->um_open_ca = mlnx_um_open;
 	p_interface->um_close_ca = mlnx_um_close;
+	p_interface->register_event_handler = mlnx_register_event_handler;
+	p_interface->unregister_event_handler = mlnx_unregister_event_handler;
 
 	p_interface->allocate_pd = mlnx_allocate_pd;
 	p_interface->deallocate_pd = mlnx_deallocate_pd;
diff -up -r -X trunk\docs\dontdiff.txt -I '\$Id:' trunk/hw/mthca/kernel/mthca_main.c
branches\winverbs/hw/mthca/kernel/mthca_main.c
--- trunk/hw/mthca/kernel/mthca_main.c	2008-07-07 09:59:57.828000000 -0700
+++ branches\winverbs/hw/mthca/kernel/mthca_main.c	2008-07-14 12:04:25.205753700 -0700
@@ -956,6 +956,9 @@ find_pci_dev:	
 		goto end;
 	}
 
+	InitializeListHead(&ext->hca.hob.event_list);
+	KeInitializeSpinLock(&ext->hca.hob.event_list_lock);
+
 	/* allocate mdev structure */
 	mdev = kzalloc(sizeof *mdev, GFP_KERNEL);
 	if (!mdev) {
diff -up -r -X trunk\docs\dontdiff.txt -I '\$Id:' trunk/inc/iba/ib_ci.h branches\winverbs/inc/iba/ib_ci.h
--- trunk/inc/iba/ib_ci.h	2008-07-11 14:29:32.288375000 -0700
+++ branches\winverbs/inc/iba/ib_ci.h	2008-07-14 12:25:36.827330300 -0700
@@ -193,6 +193,8 @@ typedef void
 *	channel adapter.  The event notification record passed has relevant
 *	information on the type of the event, the source that caused the event,
 *	and the context associated.
+*
+*   This routine is called at DISPATCH.
 *****/
 
 
@@ -249,6 +251,28 @@ typedef ib_api_status_t
 *********/
 
 
+/*
+ * Structure is provided by caller, and must be valid while registered.
+ * Callback context for CA events references structure.
+ */
+typedef struct _ci_event_handler
+{
+	LIST_ENTRY				entry;
+	ci_async_event_cb_t		pfn_async_event_cb;
+
+}	ci_event_handler_t;
+
+typedef void
+(*ci_register_event_handler_t) (
+	IN		const	ib_ca_handle_t				h_ca,
+	IN				ci_event_handler_t*			p_reg);
+
+typedef void
+(*ci_unregister_event_handler_t) (
+	IN		const	ib_ca_handle_t				h_ca,
+	IN				ci_event_handler_t*			p_reg);
+
+
 /****f* Verbs/ci_um_open_ca
 * NAME
 *	ci_um_open_ca -- Create a CA context for use by user-mode processes.
@@ -2798,6 +2822,9 @@ typedef struct _ci_interface
 	ci_modify_ca		modify_ca;
 	ci_close_ca			close_ca;
 	ci_um_close_ca_t	um_close_ca;
+	ci_register_event_handler_t		register_event_handler;
+	ci_unregister_event_handler_t	unregister_event_handler;
+
 
 	ci_vendor_call		vendor_call;
 
diff -up -r -X trunk\docs\dontdiff.txt -I '\$Id:' trunk/inc/iba/ib_types.h branches\winverbs/inc/iba/ib_types.h
--- trunk/inc/iba/ib_types.h	2008-07-11 14:29:35.382125000 -0700
+++ branches\winverbs/inc/iba/ib_types.h	2008-07-13 23:45:25.484375000 -0700
@@ -8921,7 +8921,6 @@ typedef enum _ib_async_event_t
 *****/
 
 
-
 /****f* IBA Base: Types/ib_get_async_event_str
 * NAME
 *	ib_get_async_event_str
@@ -8972,6 +8971,7 @@ typedef struct _ib_event_rec
 
 	//HCA vendor specific event information. 
 	uint64_t				vendor_specific;
+	uint8_t					port_number;
 
 }	ib_event_rec_t;
 /*******/





More information about the ofw mailing list