On Thu, Aug 5, 2021 at 2:49 PM Viresh Kumar viresh.kumar@linaro.org wrote:
On 05-08-21, 14:03, Arnd Bergmann wrote:
On Thu, Aug 5, 2021 at 1:26 PM Viresh Kumar via Stratos-dev
Based on discussion we had today (offline), I changed the design a bit and used handle_level_irq() instead, as it provides consistent calls to mask/unmask(), which simplified the whole thing a bit.
The new flow looks much nicer to me, without the workqueue, and doing the requeue directly in the unmask() operation.
I don't quite understand the purpose of the type_pending and mask_pending flags yet, can you explain what they actually do?
They are required to make sure we don't send unnecessary VIRTIO_GPIO_MSG_IRQ_TYPE events to the device, every time bus_unlock() is called.
mask_pending tracks if the masked state has changed since the time last bus_unlock() was called. So on an interrupt, both mask() and unmask() will get called by the irq-core now and mask_pending will change to true (in mask()} and then false (in unmask()). And eventually in bus_unlock() we won't send an extra VIRTIO_GPIO_MSG_IRQ_TYPE message.
I hope this can still be simplified by working out better which state transitions are needed exactly. In particular, I would expect that we can get away with not sending a VIRTIO_GPIO_MSG_IRQ_TYPE for 'mask' state changes at all, but use that only for forcing 'enabled' state changes.
One part that I think is missing though is remembering the case when an eventq message came in after an interrupt got masked when the message was already armed. In this case, the virtio_gpio_event_vq() function would not call the irq handler, but the subsequent "unmask" callback would need to arrange having it called.
Arnd