qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Fabien Chouteau <chouteau@adacore.com>
To: Scott Wood <scottwood@freescale.com>
Cc: qemu-ppc@nongnu.org, qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [Qemu-ppc] [PATCH 2/2] Add Enhanced Three-Speed Ethernet Controller (eTSEC)
Date: Tue, 16 Jul 2013 17:28:28 +0200	[thread overview]
Message-ID: <51E5669C.2080602@adacore.com> (raw)
In-Reply-To: <20130716020617.GA22542@home.buserror.net>

On 07/16/2013 04:06 AM, Scott Wood wrote:
> On 07/10/2013 12:10:02 PM, Fabien Chouteau wrote:
>> This implementation doesn't include ring priority, TCP/IP Off-Load, QoS.
>>
>> Signed-off-by: Fabien Chouteau <chouteau@adacore.com>
> 
> From the code comments I gather this has been tested on VxWorks.  Has it
> been tested on Linux, or anywhere else?
> 

You're right, as I said in the cover letter, this has only been tested on vxWorks.

>>  create mode 100644 hw/net/etsec.c
>>  create mode 100644 hw/uuunet/etsec.h
>>  create mode 100644 hw/net/etsec_miim.c
>>  create mode 100644 hw/net/etsec_registers.c
>>  create mode 100644 hw/net/etsec_registers.h
>>  create mode 100644 hw/net/etsec_rings.c
> 
> This should probably be namespaced as something like fsl_etsec.
> 

Fixed.

>> diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak
>> index 73e4cc5..c7541cf 100644
>> --- a/default-configs/ppc-softmmu.mak
>> +++ b/default-configs/ppc-softmmu.mak
>> @@ -46,3 +46,4 @@ CONFIG_E500=y
>>  CONFIG_OPENPIC_KVM=$(and $(CONFIG_E500),$(CONFIG_KVM))
>>  # For PReP
>>  CONFIG_MC146818RTC=y
>> +CONFIG_ETSEC=y
>> diff --git a/hw/net/Makefile.objs b/hw/net/Makefile.objs
>> index 951cca3..ca03c3f 100644
>> --- a/hw/net/Makefile.objs
>> +++ b/hw/net/Makefile.objs
>> @@ -28,6 +28,7 @@ obj-$(CONFIG_COLDFIRE) += mcf_fec.o
>>  obj-$(CONFIG_MILKYMIST) += milkymist-minimac2.o
>>  obj-$(CONFIG_PSERIES) += spapr_llan.o
>>  obj-$(CONFIG_XILINX_ETHLITE) += xilinx_ethlite.o
>> +obj-$(CONFIG_ETSEC) += etsec.o etsec_registers.o etsec_rings.o etsec_miim.o
> 
> Maybe an fsl_etsec directory?
> 

Is it really necessary?

>> +static uint64_t etsec_read(void *opaque, hwaddr addr, unsigned size)
>> +{
>> +    eTSEC          *etsec     = opaque;
>> +    uint32_t        reg_index = addr / 4;
>> +    eTSEC_Register *reg       = NULL;
>> +    uint32_t        ret       = 0x0;
> 
> It's always awkward when QEMU's type naming convention collides with
> names that have pre-existing significant capitalization, but I suspect
> this ought to be Etsec and EtsecRegister.  Or maybe ETSEC and
> ETSECRegister?  Oh well.

Oh well... :)

> 
>> +    assert(reg_index < REG_NUMBER);
>> +
>> +    reg = &etsec->regs[reg_index];
>> +
>> +
>> +    switch (reg->access) {
>> +    case ACC_WO:
>> +        ret = 0x00000000;
>> +        break;
>> +
>> +    case ACC_RW:
>> +    case ACC_w1c:
>> +    case ACC_RO:
>> +    default:
>> +        ret = reg->value;
>> +        break;
>> +    }
> 
> Why is "w1c" lowercase when the rest are uppercase?  I realize the
> hardware docs do that, but in this case I don't think that takes
> precedence over consistent coding style for #defines.

Fixed.

>> +#ifdef DEBUG_REGISTER
>> +    printf("Read  0x%08x @ 0x" TARGET_FMT_plx
>> +           "                            : %s (%s)\n",
>> +           ret, addr, reg->name, reg->desc);
>> +#endif
> 
> This is likely to bitrot -- please consider doing something similar to DPRINTF in hw/intc/openpic.c.

Fixed.

> 
>> +static void write_ievent(eTSEC          *etsec,
>> +                         eTSEC_Register *reg,
>> +                         uint32_t        reg_index,
>> +                         uint32_t        value)
>> +{
>> +    if (value & IEVENT_TXF) {
>> +        qemu_irq_lower(etsec->tx_irq);
>> +    }
>> +    if (value & IEVENT_RXF) {
>> +        qemu_irq_lower(etsec->rx_irq);
>> +    }
>> +
>> +    /* Write 1 to clear */
>> +    reg->value &= ~value;
>> +}
> 
> What about the error interrupt?  You raise it but never lower it that I
> can see.
>
> TXB/RXB should also be included, and you should only lower the interrupt
> if neither ?XB nor ?XF are set for a particular direction.
> 

I don't claim to support all interrupt flags but I will fix this...

>> +#ifdef HEX_DUMP
>> +static void hex_dump(FILE *f, const uint8_t *buf, int size)
>> +{
>> ...
>> +}
>> +#endif
> 
> qemu_hexdump()
> 

Fixed.

>> +static int etsec_init(SysBusDevice *dev)
>> +{
>> +    eTSEC *etsec = FROM_SYSBUS(typeof(*etsec), dev);
> 
> I was recently yelled at for using FROM_SYSBUS and related
> deprecated infrastructure -- see http://wiki.qemu.org/QOMConventions

Me too ;) Fixed.

> 
>> +DeviceState *etsec_create(hwaddr         base,
>> +                          MemoryRegion * mr,
>> +                          NICInfo      * nd,
>> +                          qemu_irq       tx_irq,
>> +                          qemu_irq       rx_irq,
>> +                          qemu_irq       err_irq)
>>
> Do you plan to update hw/ppc/e500.c (or maybe some other platform?) to
> call this?
> 

No I don't, not for the moment. I use it in one of our machine (that is not in mainstream).
e500.c would require PCI support I think.

> If you're centralizing this part of device creation, how about the device
> tree bits as well?
> 

I don't know about device tree...

>> +/* eTSEC */
>> +
>> +#define REG_NUMBER 1024
> 
> This is pretty vague.
> 

Fixed.

>> +DeviceState *etsec_create(hwaddr        base,
>> +                          MemoryRegion *mr,
>> +                          NICInfo      *nd,
>> +                          qemu_irq      tx_irq,
>> +                          qemu_irq      rx_irq,
>> +                          qemu_irq      err_irq);
> 
> You've got stuff in this file that isn't properly namespaced for
> inclusion by arbitrary QEMU code (especially board code that needs to
> include headers for several devices), such as REG_NUMBER, yet you declare
> etsec_create here which has to be called from board code.

Fixed.

> 
>> +#ifdef ETSEC_RING_DEBUG
>> +#define RING_DEBUG(fmt, ...) printf("%s:%s " fmt, __func__ ,\
>> +                                    etsec->nic->nc.name, ## __VA_ARGS__)
>> +#else
>> +#define RING_DEBUG(...)
>> +#endif  /* ETSEC_RING_DEBUG */
> 
> Please consume the arguments even if debug output is not enabled (so you
> don't get unused variable warnings), and ideally do a printf inside an
> if-statement (on a constant so it will be optimized away) so you still
> get format checking -- again, similar to DPRINTF in hw/intc/openpic.c.

Fixed.

> 
>> +#define RING_DEBUG_A(fmt, ...) printf("%s:%s " fmt, __func__ ,\
>> +                                      etsec->nic->nc.name, ## __VA_ARGS__)
> 
> "A"?
> 
> If this means "always", why not define RING_DEBUG in terms of this?
> 

This was just a handy trick, I will remove it.

> 
> Two instances of this even in the same driver?
> 

Fixed.

>> +static void fill_rx_bd(eTSEC          *etsec,
>> +                       eTSEC_rxtx_bd  *bd,
>> +                       const uint8_t **buf,
>> +                       size_t         *size)
>> +{
>> +    uint16_t to_write = MIN(etsec->rx_fcb_size + *size - etsec->rx_padding,
>> +                            etsec->regs[MRBLR].value);
>> +    uint32_t bufptr   = bd->bufptr;
>> +    uint8_t  padd[etsec->rx_padding];
>> +    uint8_t  rem;
>> +
>> +    RING_DEBUG("eTSEC fill Rx buffer @ 0x%08x"
>> +               " size:%u(padding + crc:%u) + fcb:%u\n",
>> +               bufptr, *size, etsec->rx_padding, etsec->rx_fcb_size);
>> +
>> +    bd->length = 0;
>> +    if (etsec->rx_fcb_size != 0) {
>> +        cpu_physical_memory_write(bufptr, etsec->rx_fcb, etsec->rx_fcb_size);
>> +
>> +        bufptr             += etsec->rx_fcb_size;
>> +        bd->length         += etsec->rx_fcb_size;
>> +        to_write           -= etsec->rx_fcb_size;
>> +        etsec->rx_fcb_size  = 0;
>> +
>> +    }
>> +
>> +    if (to_write > 0) {
>> +        cpu_physical_memory_write(bufptr, *buf, to_write);
>> +
>> +        *buf   += to_write;
>> +        bufptr += to_write;
>> +        *size  -= to_write;
>> +
>> +        bd->flags  &= ~BD_RX_EMPTY;
>> +        bd->length += to_write;
>> +    }
>> +
>> +    if (*size == etsec->rx_padding) {
>> +        /* The remaining bytes are for padding which is not actually allocated
>> +           in the buffer */
>> +
>> +        rem = MIN(etsec->regs[MRBLR].value - bd->length, etsec->rx_padding);
>> +
>> +        if (rem > 0) {
>> +            memset(padd, 0x0, sizeof(padd));
>> +            etsec->rx_padding -= rem;
>> +            *size             -= rem;
>> +            bd->length        += rem;
>> +            cpu_physical_memory_write(bufptr, padd, rem);
>> +        }
>> +    }
> 
> What if *size > 0 && *size < etsec->rx_padding?

I don't think it's possible...

> 
>> +static void rx_init_frame(eTSEC *etsec, const uint8_t *buf, size_t size)
>> +{
>> +    uint32_t fcb_size = 0;
>> +    uint8_t  prsdep   = (etsec->regs[RCTRL].value >> RCTRL_PRSDEP_OFFSET)
>> +        & RCTRL_PRSDEP_MASK;
>> +
>> +    if (prsdep != 0) {
>> +        /* Prepend FCB */
>> +        fcb_size = 8 + 2;          /* FCB size + align */
>> +        /* I can't find this 2 bytes alignement in fsl documentation but VxWorks
>> +           expects them */
> 
> Could these 2 bytes be from RCTRL[PAD], which you seem to ignore?

Did you mean RCTRL[PAL]? It could be that.

> 
>> +    etsec->rx_padding    = 4;

CRC.

>> +    if (size < 60) {
>> +        etsec->rx_padding += 60 - size;
>> +    }
> 
> Could you explain what you're doing with rx_padding?

Avoiding short frames. I'll add a comments.

> 
>> +    /* ring_base = (etsec->regs[RBASEH].value & 0xF) << 32; */
>> +    ring_base     += etsec->regs[RBASE0 + ring_nbr].value & ~0x7;
>> +    start_bd_addr  = bd_addr = etsec->regs[RBPTR0 + ring_nbr].value & ~0x7;
> 
> What about RBDBPH (upper bits of physical address)?  Likewise for TX.
> 

I'm only interested in 32bits address spaces, so RBASEH, TBASEH, RBDBPH or TBDBPH.

>> +                /* NOTE: non-octet aligned frame is impossible in qemu */
> 
> Is it possible in eTSEC?
> 

I think eTSEC can handle it and there's a flag in RxBD for that:

NO | Rx non-octet aligned frame, written by the eTSEC (only valid if L is set).
A frame that contained a number of bits not divisible by eight was received.

But we will never receive such frame from QEMU.


Thanks for your review.

-- 
Fabien Chouteau

  reply	other threads:[~2013-07-16 15:28 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-07-10 17:10 [Qemu-devel] [PATCH 0/2] Enhanced Three Speed Ethernet Controller (eTSEC) Fabien Chouteau
2013-07-10 17:10 ` [Qemu-devel] [PATCH 1/2] Add be16_to_cpupu function Fabien Chouteau
2013-07-10 17:25   ` Peter Maydell
2013-07-12  9:57     ` Fabien Chouteau
2013-07-10 17:10 ` [Qemu-devel] [PATCH 2/2] Add Enhanced Three-Speed Ethernet Controller (eTSEC) Fabien Chouteau
     [not found]   ` <201307110955092430409@cn.fujitsu.com>
2013-07-15  1:25     ` [Qemu-devel] Fw: [PATCH 2/2] Add Enhanced Three-Speed EthernetController (eTSEC) Yao Xingtao
2013-07-15 10:19       ` Fabien Chouteau
2013-07-15  2:00   ` [Qemu-devel] [PATCH 2/2] Add Enhanced Three-Speed Ethernet Controller (eTSEC) Peter Crosthwaite
2013-07-15 14:23     ` Fabien Chouteau
2013-07-16  1:06       ` Peter Crosthwaite
2013-07-16  8:35         ` Fabien Chouteau
2013-07-16  2:06   ` [Qemu-devel] [Qemu-ppc] " Scott Wood
2013-07-16 15:28     ` Fabien Chouteau [this message]
2013-07-16 15:37       ` Alexander Graf
2013-07-16 16:15         ` Fabien Chouteau
2013-07-16 16:54           ` Scott Wood
2013-07-17  8:24             ` Fabien Chouteau
2013-07-17  8:29               ` Alexander Graf
2013-07-17 10:27                 ` Fabien Chouteau
2013-07-16 17:50       ` Scott Wood
2013-07-17 10:17         ` Fabien Chouteau
2013-07-17 10:22           ` Alexander Graf
2013-07-17 10:43             ` Fabien Chouteau
2013-07-17 21:02           ` Scott Wood
2013-07-18  9:27             ` Fabien Chouteau
2013-07-18 20:37               ` Scott Wood
2013-07-19  9:22                 ` Fabien Chouteau
2013-07-19 17:19                   ` Scott Wood
2013-07-22  9:00                     ` Fabien Chouteau

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=51E5669C.2080602@adacore.com \
    --to=chouteau@adacore.com \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-ppc@nongnu.org \
    --cc=scottwood@freescale.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).