[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH 27/27 v10] xen/arm: vpl011: Correct the logic for asserting/de-asserting SBSA UART TX interrupt



On 11 October 2017 at 15:38, Dave Martin <Dave.Martin@xxxxxxx> wrote:
> On Wed, Oct 11, 2017 at 01:28:44PM +0530, Bhupinder Thakur wrote:
>> Hi Dave,
>>
>> On 26 September 2017 at 20:08, Dave Martin <Dave.Martin@xxxxxxx> wrote:
>> > On Fri, Sep 22, 2017 at 01:53:26PM +0530, Bhupinder Thakur wrote:
>> >> This patch fixes the issue observed when pl011 patches were tested on
>> >> the junos hardware by Andre/Julien. It was observed that when large 
>> >> output is
>> >> generated such as on running 'find /', output was getting truncated 
>> >> intermittently
>> >> due to OUT ring buffer getting full.
>> >>
>> >> This issue was due to the fact that the SBSA UART driver expects that when
>> >> a TX interrupt is asserted then the FIFO queue should be atleast half 
>> >> empty and
>> >> that it can write N bytes in the FIFO, where N is half the FIFO queue 
>> >> size, without
>> >> the bytes getting dropped due to FIFO getting full.
>> >>
>> >> The SBSA UART emulation logic was asserting the TX interrupt as soon as
>> >> any space became available in the FIFO and the SBSA UART driver tried to 
>> >> write
>> >> more data (upto 16 bytes) in the FIFO expecting that there is enough space
>> >> available leading to dropped bytes.
>> >>
>> >> The SBSA spec [1] does not specify when the TX interrupt should be 
>> >> asserted
>> >> or de-asserted. Due to lack of clarity on the expected behavior, it is
>> >> assumed for now that TX interrupt should be asserted only when the FIFO 
>> >> goes
>> >> half empty.
>> >>
>> >> TBD: Once the SBSA spec is updated with the expected behavior, the 
>> >> implementation
>> >> will be modified to align with the spec requirement.
>> >>
>> >> [1] http://infocenter.arm.com/help/topic/com.arm.doc.ddi0183f/DDI0183.pdf
>> >>
>> >> Signed-off-by: Bhupinder Thakur <bhupinder.thakur@xxxxxxxxxx>
>> >> ---
>> >> CC: Julien Grall <julien.grall@xxxxxxx>
>> >> CC: Andre Przywara <andre.przywara@xxxxxxx>
>> >> CC: Stefano Stabellini <sstabellini@xxxxxxxxxx>
>> >
>> > (Taking a quick look at this because I remember fighthing with FIFO
>> > behaviour issues when hacking the Linux driver -- but beware, I'm not a
>> > Xen guy...)
>> >
>> >
>> > Should this patch be flattened into the patches is fixes?  Keeping
>> > known-wrong code in the series does not help reviewers (but maybe it's
>> > the Xen way).
>> >
>> >> Changes since v8:
>> >> - Used variables fifo_level/fifo_threshold for more clarity
>> >> - Added a new macro SBSA_UART_FIFO_SIZE instead of using a magic number
>> >
>> > What's sizeof(intf->in), sizeof(intf->out)?
>> >
>> > For correct operation, you assume that the total ring buffer size is >=
>> > SBSA_UART_FIFO_SIZE, but nothing enforces this.  If the xencons ring
>> > buffer size is set elsewhere and can't be chosen by a driver, you may at
>> > least add a build-time assert to check that it's big enough.
>> >
>> I will add an assert to check this condition.
>>
>> > [...]
>> >
>> >> @@ -144,28 +148,41 @@ static void vpl011_write_data(struct domain *d, 
>> >> uint8_t data)
>> >
>> > [...]
>> >
>> >> +         * Clear the TXI bit if the fifo level exceeds fifo_size/2 mark 
>> >> which
>> >> +         * is the trigger level for asserting/de-assterting the TX 
>> >> interrupt.
>> >>           */
>> >> -        vpl011->uartfr |= BUSY;
>> >> +        fifo_threshold = sizeof (intf->out) - SBSA_UART_FIFO_SIZE/2;
>> >> +
>> >> +        if ( fifo_level <= fifo_threshold )
>> >> +            vpl011->uartris |= TXI;
>> >> +        else
>> >> +            vpl011->uartris &= ~TXI;
>> >>      }
>> >> +    else
>> >> +        gprintk(XENLOG_ERR, "vpl011: Unexpected OUT ring buffer full\n");
>> >>
>> >>      vpl011->uartfr &= ~TXFE;
>> >>
>> >
>> > [...]
>> >
>> >> @@ -353,37 +370,51 @@ static void vpl011_data_avail(struct domain *d)
>> >>
>> >>      smp_rmb();
>> >>
>> >> -    in_ring_qsize = xencons_queued(in_prod,
>> >> +    in_fifo_level = xencons_queued(in_prod,
>> >>                                     in_cons,
>> >>                                     sizeof(intf->in));
>> >>
>> >> -    out_ring_qsize = xencons_queued(out_prod,
>> >> +    out_fifo_level = xencons_queued(out_prod,
>> >>                                      out_cons,
>> >>                                      sizeof(intf->out));
>> >>
>> >>      /* Update the uart rx state if the buffer is not empty. */
>> >> -    if ( in_ring_qsize != 0 )
>> >> +    if ( in_fifo_level != 0 )
>> >>      {
>> >>          vpl011->uartfr &= ~RXFE;
>> >> -        if ( in_ring_qsize == sizeof(intf->in) )
>> >> +
>> >> +        if ( in_fifo_level == sizeof(intf->in) )
>> >>              vpl011->uartfr |= RXFF;
>> >> +
>> >>          vpl011->uartris |= RXI;
>> >>      }
>> >>
>> >>      /* Update the uart tx state if the buffer is not full. */
>> >> -    if ( out_ring_qsize != sizeof(intf->out) )
>> >> +    if ( out_fifo_level != sizeof(intf->out) )
>> >>      {
>> >> +        unsigned int out_fifo_threshold;
>> >> +
>> >>          vpl011->uartfr &= ~TXFF;
>> >> -        vpl011->uartris |= TXI;
>> >>
>> >>          /*
>> >> -         * Clear the BUSY bit as soon as space becomes available
>> >> +         * Clear the BUSY bit as soon as space becomes avaliable
>> >>           * so that the SBSA UART driver can start writing more data
>> >>           * without any further delay.
>> >>           */
>> >>          vpl011->uartfr &= ~BUSY;
>> >>
>> >> -        if ( out_ring_qsize == 0 )
>> >> +        /*
>> >> +         * Set the TXI bit only when there is space for fifo_size/2 
>> >> bytes which
>> >> +         * is the trigger level for asserting/de-assterting the TX 
>> >> interrupt.
>> >> +         */
>> >> +        out_fifo_threshold = sizeof(intf->out) - SBSA_UART_FIFO_SIZE/2;
>> >> +
>> >> +        if ( out_fifo_level <= out_fifo_threshold )
>> >> +            vpl011->uartris |= TXI;
>> >> +        else
>> >> +            vpl011->uartris &= ~TXI;
>> >
>> > Should this logic be factored out?  You do the same thing in
>> > _write_data().
>> I will add a common function to set the TXI bit.
>> >
>> > Also, is there a reason why you implement the trigger threshold logic on
>> > the TX side only?  It looks inconsistent now.
>> I did try with RX FIFO threshold also but it seems the current pl011
>> driver does not
>> poll on the RX FIFO and just waits for the RX interrupt trigger to
>> start processing the RX data.
>> This makes RX very slow and if the RX FIFO is not filled sufficiently,
>> it does not read data further.
>> >
>> > I think a real PL011 implements the trigger logic in exactly the same
>> > way for RX and TX (except for swapping >= for <= in the threshold
>> > comparison).
>> >
>> >
>> > It doesn't look like the Linux pl011 driver relies on a correctly
>> > implemented RX trigger level today, but it may have done in the past --
>> > I did some hacking in this area at some point, but can't remember the
>> > details now.
>> >
>> The current pl011 driver
>> > Asserting RXI whenever the RX FIFO is nonempty would result in excessive
>> > interrupts if you are streaming the data from a slow source (such as a
>> > real UART) and pushing the chars one by one to the emulated UART: the
>> > guest would take an IRQ on each char rather than waiting until the RX
>> > FIFO is half-full.
>> >
>> I agree it is an overhead. This may be an issue with the driver which
>> is solely depending on the RX
>> interrupt. I think it should switch to polling if there are no
>> interrupts received recently.
>
> Hmmm, good point, but isn't that what the receive timeout interrupt is
> supposed to be for?
>
> The Linux driver seems to rely on the receive timeout interrupt
> to recover from an RX stall when the FIFO is not empty but also not full
> enough to trigger the RX FIFO interrupt.
>
> Does your driver actually implement the receive timeout interrupt?
> I'm not very familiar with the code, so I may have missed it.

This patch emulates the SBSA UART spec, which is a subset of the pl011
UART. The SBSA spec [1], Appendix B does not define the requirement of
supporting RX timeout interrupt.

[1] 
https://static.docs.arm.com/den0029/a/Server_Base_System_Architecture_v3_1_ARM_DEN_0029A.pdf

Regards,
Bhupinder

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.