The current semantics when a queued event is received before the driver
is done loading is to ignore it with a log warning. This was not sufficient
to implement the flush_retry_qp setup, which relies on lid change events.
Unfortunately the solution to make an exception for lid events for the
flush_retry_qp is not valid because it defeats the purpose of the
check in the first place by allowing such an event to be handled before
the data structure needed to handle it is initialized.
This commit introduces a new kernel completion that the driver completes
when the whole driver load is finished. The first EPSC event queued on the
sif work queue will now block on this completion.
This covers all the remaining cases not handled by commit
"eq: Avoid enabling interrupts on TSU EQs until the initialization is complete"
and solves the original problem that introduced the need for a fix.
Orabug:
24296729
Signed-off-by: Knut Omang <knut.omang@oracle.com>
Reviewed-by: HÃ¥kon Bugge <haakon.bugge@oracle.com>
struct sif_idr pd_refs; /* Mgmt of sif_pd allocations */
struct sif_spqp_pool ki_spqp; /* Stencil PQPs for key invalidates */
/* Misc settings */
+ struct completion ready_for_events; /* Set when we are ready to receive events from sif */
bool registered; /* Set when we are registered with the verbs layer */
u64 min_resp_ticks; /* expected min. hw resp.time in ticks */
atomic_inc(&ew->eq->work_cnt);
if (unlikely(!sdev->registered)) {
- sif_log(sdev, SIF_INFO,
- "Event of type %s received before verbs framework is up - ignoring",
- ib_event2str(ew->ibe.event));
-
- if ((ew->ibe.event == IB_EVENT_LID_CHANGE)
- && (PSIF_REVISION(sdev) <= 3))
- sif_r3_recreate_flush_qp(sdev, ew->ibe.element.port_num - 1);
- goto out;
+ wait_for_completion_interruptible(&sdev->ready_for_events);
}
switch (ew->ibe.event) {
sif_log(sdev, SIF_INFO, "Unhandled event type %d", ew->ibe.event);
break;
}
-out:
kfree(ew);
- }
+}
/* Generic event handler - @eqe contains little endian copy of event triggering the call
* ib_dispatch_event dispatches directly so we have to defer the actual dispatch
sdev->ib_dev.local_dma_lkey = sdev->dma_mr->index;
sdev->registered = true;
+ complete(&sdev->ready_for_events);
sif_log(sdev, SIF_VERBS_V, "%s registered with IB", sdev->ib_dev.name);
return 0;
const struct pci_device_id *id)
{
int err = 0;
+ char tmp[IB_DEVICE_NAME_MAX+6];
/* TBD: Zeroed memory from ib_alloc_device? */
struct sif_dev *sdev =
sdev->fw_vfs = -1; /* #of VFS enabled in firmware not known yet */
sdev->ib_dev.dma_device = &pdev->dev;
sdev->limited_mode = sif_feature(force_limited_mode) ? true : false;
+ init_completion(&sdev->ready_for_events);
strlcpy(sdev->ib_dev.name, "sif%d", IB_DEVICE_NAME_MAX);
err = -ENOMEM;
goto wq_fail;
}
- sdev->misc_wq = create_singlethread_workqueue("sif_misc_wq");
+
+ /* Hold back wq event processing until everything is up */
+
+
+ sprintf(tmp, "%s_misc", sdev->ib_dev.name);
+ sdev->misc_wq = create_singlethread_workqueue(tmp);
if (!sdev->misc_wq) {
sif_log(sdev, SIF_INFO, "Failed to allocate sif misc work queue");
err = -ENOMEM;