I came up with this version, it kind of reverses the logic of your patch but reuses the _items function (renamed _length), please see if it looks ok and possibly even works.
[sorry about the delay, I was out of office for a while] Yes, your version works (both on paper and in practice). I'm not quite sure I like the way it breaches the apparent abstraction of the FIFO handling routines (if you can call it that) or the way it first gives FIFO slots back to the guest but then rewinds them back. Not that either of those concerns necessarily matter much. BTW, now that I look at it, if either HW_FILL_ACCEL or HW_RECT_ACCEL is not set 'badcmd' will be called, but args won't be set (as far as I can see). Isn't that wrong? Although I think the bug was there even before your changes.