All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jason Wang <jasowang@redhat.com>
To: Fam Zheng <famz@redhat.com>
Cc: Peter Maydell <peter.maydell@linaro.org>,
	Peter Crosthwaite <peter.crosthwaite@xilinx.com>,
	Rob Herring <robh@kernel.org>,
	qemu-devel@nongnu.org, Michael Walle <michael@walle.cc>,
	Gerd Hoffmann <kraxel@redhat.com>,
	stefanha@redhat.com,
	"Edgar E. Iglesias" <edgar.iglesias@gmail.com>
Subject: Re: [Qemu-devel] [PATCH v2 for-2.4 12/12] axienet: Flush queued packets when rx is done
Date: Thu, 16 Jul 2015 13:38:11 +0800	[thread overview]
Message-ID: <55A74343.40507@redhat.com> (raw)
In-Reply-To: <20150716033247.GB10334@ad.nay.redhat.com>



On 07/16/2015 11:32 AM, Fam Zheng wrote:
> On Thu, 07/16 10:58, Jason Wang wrote:
>>
>> On 07/15/2015 06:19 PM, Fam Zheng wrote:
>>> eth_can_rx checks s->rxsize and returns false if it is non-zero. Because
>>> of the .can_receive semantics change, this will make the incoming queue
>>> disabled by peer, until it is explicitly flushed. So we should flush it
>>> when s->rxsize is becoming zero.
>>>
>>> Squash eth_can_rx semantics into etx_rx and drop .can_receive()
>>> callback, also add flush when rx buffer becomes available again after a
>>> packet gets queued.
>>>
>>> The other conditions, "!axienet_rx_resetting(s) &&
>>> axienet_rx_enabled(s)" are OK because enet_write already calls
>>> qemu_flush_queued_packets when the register bits are changed.
>>>
>>> Signed-off-by: Fam Zheng <famz@redhat.com>
>>> ---
>>>  hw/net/xilinx_axienet.c | 17 +++++++++++++----
>>>  1 file changed, 13 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/hw/net/xilinx_axienet.c b/hw/net/xilinx_axienet.c
>>> index 9205770..d63c423 100644
>>> --- a/hw/net/xilinx_axienet.c
>>> +++ b/hw/net/xilinx_axienet.c
>>> @@ -401,6 +401,9 @@ struct XilinxAXIEnet {
>>>  
>>>      uint8_t rxapp[CONTROL_PAYLOAD_SIZE];
>>>      uint32_t rxappsize;
>>> +
>>> +    /* Whether axienet_eth_rx_notify should flush incoming queue. */
>>> +    bool need_flush;
>>>  };
>>>  
>>>  static void axienet_rx_reset(XilinxAXIEnet *s)
>>> @@ -658,10 +661,8 @@ static const MemoryRegionOps enet_ops = {
>>>      .endianness = DEVICE_LITTLE_ENDIAN,
>>>  };
>>>  
>>> -static int eth_can_rx(NetClientState *nc)
>>> +static int eth_can_rx(XilinxAXIEnet *s)
>>>  {
>>> -    XilinxAXIEnet *s = qemu_get_nic_opaque(nc);
>>> -
>>>      /* RX enabled?  */
>>>      return !s->rxsize && !axienet_rx_resetting(s) && axienet_rx_enabled(s);
>>>  }
>>> @@ -701,6 +702,10 @@ static void axienet_eth_rx_notify(void *opaque)
>>>          s->rxpos += ret;
>>>          if (!s->rxsize) {
>>>              s->regs[R_IS] |= IS_RX_COMPLETE;
>>> +            if (s->need_flush) {
>>> +                s->need_flush = false;
>>> +                qemu_flush_queued_packets(qemu_get_queue(s->nic));
>>> +            }
>>>          }
>>>      }
>>>      enet_update_irq(s);
>>> @@ -721,6 +726,11 @@ static ssize_t eth_rx(NetClientState *nc, const uint8_t *buf, size_t size)
>>>  
>>>      DENET(qemu_log("%s: %zd bytes\n", __func__, size));
>>>  
>>> +    if (!eth_can_rx(s)) {
>>> +        s->need_flush = true;
>>> +        return 0;
>>> +    }
>>> +
>> axienet_eth_rx_notify() was only called by eth_rx(). So when
>> s->need_flush is true, we won't ever reach axienet_eth_rx_notify()?
> We will.
>
> If we are here it measn a previous call to axienet_eth_rx_notify hasn't drained
> the buffer:
>
>     static void axienet_eth_rx_notify(void *opaque)
>     {
>         ...
>
>         while (s->rxsize && stream_can_push(s->tx_data_dev,
>                                             axienet_eth_rx_notify, s)) {
>             size_t ret = stream_push(s->tx_data_dev, (void *)s->rxmem + s->rxpos,
>                                      s->rxsize);
>             s->rxsize -= ret;
>             s->rxpos += ret;
>             if (!s->rxsize) {
>                 s->regs[R_IS] |= IS_RX_COMPLETE;
>             }
>         }
>         ...
>
>     }
>
> axienet_eth_rx_notify is passed to stream_can_push so it will be reached again
> once s->tx_data_dev can receive more data:
>
>     typedef struct StreamSlaveClass {
>         InterfaceClass parent;
>         /**
>          * can push - determine if a stream slave is capable of accepting at least
>          * one byte of data. Returns false if cannot accept. If not implemented, the
>          * slave is assumed to always be capable of receiving.
>          * @notify: Optional callback that the slave will call when the slave is
>          * capable of receiving again. Only called if false is returned.
>          * @notify_opaque: opaque data to pass to notify call.
>          */
>         bool (*can_push)(StreamSlave *obj, StreamCanPushNotifyFn notify,
>                          void *notify_opaque);
>         ...
>
> Am I missing anything?
>
> Fam

Probably not. I misses the possible call in axidma_write(). So the patch
is ok :)

  reply	other threads:[~2015-07-16  5:38 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-07-15 10:19 [Qemu-devel] [PATCH v2 for-2.4 00/12] hw/net: Fix .can_receive() for NICs Fam Zheng
2015-07-15 10:19 ` [Qemu-devel] [PATCH v2 for-2.4 01/12] xgmac: Drop packets with eth_can_rx is false Fam Zheng
2015-07-15 10:19 ` [Qemu-devel] [PATCH v2 for-2.4 02/12] pcnet: Drop pcnet_can_receive Fam Zheng
2015-07-15 10:19 ` [Qemu-devel] [PATCH v2 for-2.4 03/12] eepro100: Drop nic_can_receive Fam Zheng
2015-07-15 10:19 ` [Qemu-devel] [PATCH v2 for-2.4 04/12] usbnet: Drop usbnet_can_receive Fam Zheng
2015-07-15 10:19 ` [Qemu-devel] [PATCH v2 for-2.4 05/12] etsec: Move etsec_can_receive into etsec_receive Fam Zheng
2015-07-15 10:19 ` [Qemu-devel] [PATCH v2 for-2.4 06/12] etsec: Flush queue when rx buffer is consumed Fam Zheng
2015-07-15 10:19 ` [Qemu-devel] [PATCH v2 for-2.4 07/12] mcf_fec: Drop mcf_fec_can_receive Fam Zheng
2015-07-15 10:19 ` [Qemu-devel] [PATCH v2 for-2.4 08/12] milkymist-minimac2: Flush queued packets when link comes up Fam Zheng
2015-07-15 10:19 ` [Qemu-devel] [PATCH v2 for-2.4 09/12] mipsnet: Flush queued packets when receiving is enabled Fam Zheng
2015-07-15 10:19 ` [Qemu-devel] [PATCH v2 for-2.4 10/12] stellaris_enet: Flush queued packets when read done Fam Zheng
2015-07-15 10:19 ` [Qemu-devel] [PATCH v2 for-2.4 11/12] dp8393x: Flush packets when link comes up Fam Zheng
2015-07-15 10:19 ` [Qemu-devel] [PATCH v2 for-2.4 12/12] axienet: Flush queued packets when rx is done Fam Zheng
2015-07-16  2:58   ` Jason Wang
2015-07-16  3:32     ` Fam Zheng
2015-07-16  5:38       ` Jason Wang [this message]
2015-07-16  5:38 ` [Qemu-devel] [PATCH v2 for-2.4 00/12] hw/net: Fix .can_receive() for NICs Jason Wang
2015-07-20 17:09 ` Stefan Hajnoczi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=55A74343.40507@redhat.com \
    --to=jasowang@redhat.com \
    --cc=edgar.iglesias@gmail.com \
    --cc=famz@redhat.com \
    --cc=kraxel@redhat.com \
    --cc=michael@walle.cc \
    --cc=peter.crosthwaite@xilinx.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    --cc=robh@kernel.org \
    --cc=stefanha@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.