All of lore.kernel.org
 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 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.