public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
From: Shawn Guo <shawn.guo@linaro.org>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH 2/3] net: add higmacv300 Ethernet driver for HiSilicon platform
Date: Wed, 13 Feb 2019 19:46:34 +0800	[thread overview]
Message-ID: <20190213114632.GB4027@dragon> (raw)
In-Reply-To: <CANr=Z=aK-ufWL2buNhZQa3vrnpZON4m+aV+VC2RO2XPQRZ6n2A@mail.gmail.com>

Hi Joe,

Thanks for spending time to review the patch.

On Mon, Feb 04, 2019 at 11:48:40PM +0000, Joe Hershberger wrote:
> On Mon, Jan 28, 2019 at 3:16 AM Shawn Guo <shawn.guo@linaro.org> wrote:
> >
> > It adds the driver for HIGMACV300 Ethernet controller found on HiSilicon
> > SoCs like Hi3798CV200.  It's based on a downstream U-Boot driver, but
> > quite a lot of code gets rewritten and cleaned up to adopt driver model
> > and PHY API.
> >
> > Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> > ---
> >  drivers/net/Kconfig      |   9 +
> >  drivers/net/Makefile     |   1 +
> >  drivers/net/higmacv300.c | 592 +++++++++++++++++++++++++++++++++++++++
> >  3 files changed, 602 insertions(+)
> >  create mode 100644 drivers/net/higmacv300.c

<snip>

> > +#define MDIO_WRITE                     1
> > +#define MDIO_READ                      2
> > +#define MDIO_COMMAND(rw, addr, reg)    (BIT_MDIO_BUSY | \
> > +                                       (((rw) & 0x3) << 16) | \
> > +                                       (((addr) & 0x1f) << 8) | \
> > +                                       ((reg) & 0x1f))
> > +#define MDIO_WRITE_CMD(addr, reg)      MDIO_COMMAND(MDIO_WRITE, addr, reg)
> > +#define MDIO_READ_CMD(addr, reg)       MDIO_COMMAND(MDIO_READ, addr, reg)
> 
> This is a strange construct... can you just inline this into the
> actual functions? I don't see the value in these macros that hide
> what's happening.

Yes, I can eliminate the macros with inline code.  That's actually what
kernel driver does.

> 
> > +
> > +enum higmac_queue {
> > +       RX_FQ,
> > +       RX_BQ,
> > +       TX_BQ,
> > +       TX_RQ,
> > +};

<snip>

> > +static int higmac_free_pkt(struct udevice *dev, uchar *packet, int length)
> > +{
> > +       if (packet)
> > +               free(packet);
> 
> Why free them and reallocate them? Won't that just fragment memory?

Practically it will not fragment the memory, as all the buffers get
a fixed size and allocation/free always happens as a pair for given
network transaction.  But I still think it's a good suggestion to get
all buffers allocated at initialization time, so that we do not need to
allocate/free buffers repeatedly.

> Also, you should be somehow telling the MAC that the buffer /
> descriptor is no longer in use here.

Sensible suggestion.

> 
> > +
> > +       return 0;
> > +}
> > +
> > +static int higmac_recv(struct udevice *dev, int flags, uchar **packetp)
> > +{
> > +       struct higmac_priv *priv = dev_get_priv(dev);
> > +       struct higmac_desc *fqd = priv->rxfq;
> > +       struct higmac_desc *bqd = priv->rxbq;
> > +       int fqw_pos, fqr_pos, bqw_pos, bqr_pos;
> > +       int timeout = 100000;
> > +       unsigned long addr;
> > +       int len = 0;
> > +       int space;
> > +       int i;
> > +
> > +       fqw_pos = DESC_CNT(readl(priv->base + RX_FQ_WR_ADDR));
> > +       fqr_pos = DESC_CNT(readl(priv->base + RX_FQ_RD_ADDR));
> > +
> > +       if (fqw_pos >= fqr_pos)
> > +               space = RX_DESC_NUM - (fqw_pos - fqr_pos);
> > +       else
> > +               space = fqr_pos - fqw_pos;
> > +
> > +       /* Leave one free to distinguish full filled from empty buffer */
> > +       for (i = 0; i < space - 1; i++) {
> > +               void *buf = memalign(ARCH_DMA_MINALIGN, MAC_MAX_FRAME_SIZE);
> > +
> > +               if (!buf)
> > +                       break;
> > +
> > +               fqd = priv->rxfq + fqw_pos;
> > +               fqd->buf_addr = (unsigned long)buf;
> > +               invalidate_dcache_range(fqd->buf_addr,
> > +                                       fqd->buf_addr + MAC_MAX_FRAME_SIZE);
> > +
> > +               fqd->descvid = DESC_VLD_FREE;
> > +               fqd->buf_len = MAC_MAX_FRAME_SIZE - 1;
> > +               flush_desc(fqd);
> > +
> > +               if (++fqw_pos >= RX_DESC_NUM)
> > +                       fqw_pos = 0;
> > +
> > +               writel(DESC_BYTE(fqw_pos), priv->base + RX_FQ_WR_ADDR);
> > +       }
> > +
> > +       bqr_pos = DESC_CNT(readl(priv->base + RX_BQ_RD_ADDR));
> > +       bqd += bqr_pos;
> > +       /* BQ is only ever written by GMAC */
> > +       invalidate_desc(bqd);
> > +
> > +       do {
> > +               bqw_pos = DESC_CNT(readl(priv->base + RX_BQ_WR_ADDR));
> > +               udelay(1);
> > +       } while (--timeout && bqw_pos == bqr_pos);
> > +
> > +       if (!timeout)
> > +               return -ETIMEDOUT;
> > +
> > +       if (++bqr_pos >= RX_DESC_NUM)
> > +               bqr_pos = 0;
> > +
> > +       len = bqd->data_len;
> > +
> > +       /* CPU should not have touched this buffer since we added it to FQ */
> > +       addr = bqd->buf_addr;
> > +       invalidate_dcache_range(addr, addr + len);
> > +       *packetp = (void *)addr;
> > +
> > +       writel(DESC_BYTE(bqr_pos), priv->base + RX_BQ_RD_ADDR);
> 
> Does this belong in free_pkt()?

Yeah, I guess that's what you mean by telling MAC the descriptors are
not longer used above.

> > +
> > +       return len;
> > +}

<snip>

> > +static int higmac_start(struct udevice *dev)
> > +{
> > +       struct higmac_priv *priv = dev_get_priv(dev);
> > +       struct phy_device *phydev = priv->phydev;
> > +       int ret;
> > +
> > +       ret = phy_startup(phydev);
> > +       if (ret)
> > +               return ret;
> > +
> > +       if (!phydev->link) {
> > +               debug("%s: link down\n", phydev->dev->name);
> > +               return -ENODEV;
> > +       }
> > +
> > +       ret = higmac_adjust_link(priv);
> > +       if (ret)
> > +               return ret;
> > +
> > +       /* Enable port */
> > +       writel(0xf, priv->base + DESC_WR_RD_ENA);
> 
> What is 0xf? No magic numbers please.

Okay, will define it.

> 
> > +       writel(BIT_TX_EN | BIT_RX_EN, priv->base + PORT_EN);
> > +
> > +       return 0;
> > +}
> > +
> > +static void higmac_stop(struct udevice *dev)
> > +{
> > +       struct higmac_priv *priv = dev_get_priv(dev);
> > +
> > +       /* Disable port */
> > +       writel(0, priv->base + PORT_EN);
> > +       writel(0, priv->base + DESC_WR_RD_ENA);
> > +}
> > +
> > +static const struct eth_ops higmac_ops = {
> > +       .start          = higmac_start,
> > +       .send           = higmac_send,
> > +       .recv           = higmac_recv,
> > +       .free_pkt       = higmac_free_pkt,
> > +       .stop           = higmac_stop,
> > +       .write_hwaddr   = higmac_write_hwaddr,
> > +};
> > +
> > +static int higmac_wait_mdio_ready(struct higmac_priv *priv)
> > +{
> > +       int timeout = 1000;
> > +
> > +       while (--timeout) {
> > +               /* Wait until busy bit is cleared */
> > +               if ((readl(priv->base + MDIO_SINGLE_CMD) & BIT_MDIO_BUSY) == 0)
> > +                       break;
> > +               udelay(10);
> > +       }
> 
> It would be good if you retrofit to use wait_bit or its macros
> throughout this driver instead of hand-writing it.

I didn't know that before.  Thanks for the pointer.  Will do.

> 
> > +
> > +       return timeout ? 0 : -ETIMEDOUT;
> > +}

<snip>

> > +static int higmac_probe(struct udevice *dev)
> > +{
> > +       struct higmac_priv *priv = dev_get_priv(dev);
> > +       struct phy_device *phydev;
> > +       struct mii_dev *bus;
> > +       int ret;
> > +
> > +       ret = higmac_hw_init(priv);
> > +       if (ret)
> > +               return ret;
> > +
> > +       bus = mdio_alloc();
> > +       if (!bus)
> > +               return -ENOMEM;
> > +
> > +       bus->read = higmac_mdio_read;
> > +       bus->write = higmac_mdio_write;
> > +       bus->priv = priv;
> > +       priv->bus = bus;
> > +
> > +       ret = mdio_register_seq(bus, dev->seq);
> > +       if (ret)
> > +               return ret;
> > +
> > +       phydev = phy_connect(bus, priv->phyaddr, dev, priv->phyintf);
> > +       if (!phydev)
> > +               return -ENODEV;
> > +
> > +       phydev->supported &= PHY_GBIT_FEATURES;
> 
> I would expect either phydev->supported &= ~PHY_GBIT_FEATURES; or
> phydev->supported |= PHY_GBIT_FEATURES;

To be honest, this code was copied from other drivers.  It's all over
the drivers under driver/net.  The phydev->supported gets initialized as
phydev->drv->features, and we want to make sure feature bits are set on
both sides, no?

Shawn

> 
> > +       phydev->advertising = phydev->supported;
> > +       priv->phydev = phydev;
> > +
> > +       ret = phy_config(phydev);
> > +       if (ret)
> > +               return ret;
> > +
> > +       return 0;
> > +}

  reply	other threads:[~2019-02-13 11:46 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-01-28  9:13 [U-Boot] [PATCH 0/3] Add Ethernet support for Poplar board Shawn Guo
2019-01-28  9:13 ` [U-Boot] [PATCH 1/3] reset: add reset driver for HiSilicon platform Shawn Guo
2019-01-29 21:57   ` Igor Opaniuk
2019-01-28  9:13 ` [U-Boot] [PATCH 2/3] net: add higmacv300 Ethernet " Shawn Guo
2019-01-29 21:50   ` Igor Opaniuk
2019-01-31 10:17     ` Shawn Guo
2019-02-04 23:53   ` Joe Hershberger
2019-02-13 11:46     ` Shawn Guo [this message]
2019-02-09  0:13   ` [U-Boot] [U-Boot, " Tom Rini
2019-02-13  7:21     ` Shawn Guo
2019-01-28  9:13 ` [U-Boot] [PATCH 3/3] poplar: enable Ethernet driver support Shawn Guo
2019-01-29 21:52   ` Igor Opaniuk

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=20190213114632.GB4027@dragon \
    --to=shawn.guo@linaro.org \
    --cc=u-boot@lists.denx.de \
    /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