[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