On 1/10/2024 3:41 AM, Hillf Danton wrote: > On Tue, 9 Jan 2024 11:37:45 -0800 Elliot Berman <quic_eberman@xxxxxxxxxxx> >> + >> +static irqreturn_t gunyah_rm_tx(int irq, void *data) >> +{ >> + struct gunyah_rm *rm = data; >> + >> + complete_all(&rm->send_ready); >> + >> + return IRQ_HANDLED; >> +} >> + >> +static int gunyah_rm_msgq_send(struct gunyah_rm *rm, size_t size, bool push) >> + __must_hold(&rm->send_lock) >> +{ >> + const u64 tx_flags = push ? GUNYAH_HYPERCALL_MSGQ_TX_FLAGS_PUSH : 0; >> + enum gunyah_error gunyah_error; >> + void *data = &rm->send_msg[0]; >> + bool ready; > > lockdep_assert_held(&rm->send_lock); instead of __must_hold >> + >> +again: >> + wait_for_completion(&rm->send_ready); >> + /* reinit completion before hypercall. As soon as hypercall returns, we could get the >> + * ready interrupt. This might be before we have time to reinit the completion >> + */ >> + reinit_completion(&rm->send_ready); > > Given wait_for_completion(&rm->send_ready) with rm->send_lock held, > complete(&rm->send_ready) works for you with the bonus of cutting this > reinit off. > Good point, thanks! Applied both suggestions - Elliot