lkml.org 
[lkml]   [2021]   [Dec]   [16]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
From
SubjectRe: [PATCH v6, 2/2] net: Add dm9051 driver
On Thu, Dec 16, 2021 at 05:32:46PM +0800, Joseph CHAMG wrote:
> Add davicom dm9051 spi ethernet driver, The driver work with the
> device platform's spi master
>
> remove the redundant code that phylib has support,
> adjust to be the reasonable sequence,
> fine tune comments, add comments for pause function support
>
> Tested with raspberry pi 4. Test for netwroking function, CAT5
> cable unplug/plug and also ethtool detect for link state, and
> all are ok.

You have been asked two or three times now to include a list of what
you changed relative to the previous version. This is expected for
kernel patches, just look at other submissions.

> +/* spi low level code */
> +static int
> +dm9051_xfer(struct board_info *db, u8 cmdphase, u8 *txb, u8 *rxb, unsigned int len)
> +{
> + struct device *dev = &db->spidev->dev;
> + int ret = 0;
> +
> + db->cmd[0] = cmdphase;
> + db->spi_xfer2[0].tx_buf = &db->cmd[0];
> + db->spi_xfer2[0].rx_buf = NULL;
> + db->spi_xfer2[0].len = 1;
> + if (!rxb) {
> + db->spi_xfer2[1].tx_buf = txb;
> + db->spi_xfer2[1].rx_buf = NULL;
> + db->spi_xfer2[1].len = len;
> + } else {
> + db->spi_xfer2[1].tx_buf = txb;
> + db->spi_xfer2[1].rx_buf = rxb;
> + db->spi_xfer2[1].len = len;
> + }
> + ret = spi_sync(db->spidev, &db->spi_msg2);
> + if (ret < 0)
> + dev_err(dev, "dm9Err spi burst cmd 0x%02x, ret=%d\n", cmdphase, ret);
> + return ret;
> +}
> +
> +static u8 dm9051_ior(struct board_info *db, unsigned int reg)
> +{
> + u8 rxb[1];
> +
> + dm9051_xfer(db, DM_SPI_RD | reg, NULL, rxb, 1);

dm9051_xfer() returns an error code. You should pass it up the call
stack. We want to know about errors.

> +/* basic read/write to phy
> + */
> +static int dm_phy_read(struct board_info *db, int reg)

Does this comment have any value? From the function name i can see
this is a PHY read.

And you still don't have consistent prefix of dm9051_

> +{
> + int ret;
> + u8 check_val;
> +
> + dm9051_iow(db, DM9051_EPAR, DM9051_PHY | reg);
> + dm9051_iow(db, DM9051_EPCR, EPCR_ERPRR | EPCR_EPOS);
> + ret = read_poll_timeout(dm9051_ior, check_val, !(check_val & EPCR_ERRE), 100, 10000,
> + true, db, DM9051_EPCR);
> + dm9051_iow(db, DM9051_EPCR, 0x0);
> + if (ret) {
> + netdev_err(db->ndev, "timeout read phy register\n");
> + return DM9051_PHY_NULLVALUE;

No, return whatever read_poll_timeout() returned, probably
-ETIMEDOUT. You need to report the error all the way up the call
stack.

> + }
> + ret = (dm9051_ior(db, DM9051_EPDRH) << 8) | dm9051_ior(db, DM9051_EPDRL);
> + return ret;
> +}
> +
> +static void dm_phy_write(struct board_info *db, int reg, int value)
> +{
> + int ret;
> + u8 check_val;
> +
> + dm9051_iow(db, DM9051_EPAR, DM9051_PHY | reg);
> + dm9051_iow(db, DM9051_EPDRL, value);
> + dm9051_iow(db, DM9051_EPDRH, value >> 8);
> + dm9051_iow(db, DM9051_EPCR, EPCR_EPOS | EPCR_ERPRW);
> + ret = read_poll_timeout(dm9051_ior, check_val, !(check_val & EPCR_ERRE), 100, 10000,
> + true, db, DM9051_EPCR);
> + dm9051_iow(db, DM9051_EPCR, 0x0);
> + if (ret)
> + netdev_err(db->ndev, "timeout write phy register\n");

And you need to return ret to the caller.

> +static int dm9051_mdio_read(struct mii_bus *mdiobus, int phy_id, int reg)
> +{
> + struct board_info *db = mdiobus->priv;
> + int val;
> +
> + if (phy_id == DM9051_PHY_ID) {
> + mutex_lock(&db->addr_lock);
> + val = dm_phy_read(db, reg);
> + mutex_unlock(&db->addr_lock);
> + return val;
> + }
> +
> + return DM9051_PHY_NULLVALUE;

Please just use 0xffff. Don't hide it.

The MDIO bus has a pull up on the data line. So if you try to read
from a device which does not exist, you get all 1s returned. Registers
are 16 bit wide, so you get 0xffff. When the MDIO is registered the
bus will be probed, and when the read returns 0xffff it knows there is
no device at that address. This is the only time you should use
0xffff. It is not an error, it simply indicates there is no device
there.

> +
> +/* read chip id
> + */
> +static unsigned int dm9051_chipid(struct board_info *db)

Don't you think we can work out this function reads the chip id from
the name of the function. Please only have comments if they are
actually useful.

Useful comments tend to explain why something is being done, not what
is being done.

> +static void dm9051_fifo_reset(struct board_info *db)
> +{
> + db->bc.DO_FIFO_RST_counter++;
> +
> + dm9051_iow(db, DM9051_FCR, FCR_FLOW_ENABLE); /* FlowCtrl */
> + dm9051_iow(db, DM9051_PPCR, PPCR_PAUSE_COUNT); /* Pause Pkt Count */
> + dm9051_iow(db, DM9051_LMCR, db->lcr_all); /* LEDMode1 */
> + dm9051_iow(db, DM9051_INTCR, INTCR_POL_LOW); /* INTCR */
> +}

> +static void dm_handle_link_change(struct net_device *ndev)
> +{
> + /* MAC and phy are integrated together, such as link state, speed,
> + * and Duplex are sync inside
> + */

What about Pause?

dm9051_fifo_reset() does:
dm9051_iow(db, DM9051_FCR, FCR_FLOW_ENABLE); /* FlowCtrl */

Is this enabling Pause processing? Do you need to disable it if
autoneg decided it is not wanted?

> +static int dm9051_probe(struct spi_device *spi)
> +{
> + struct device *dev = &spi->dev;
> + struct net_device *ndev;
> + struct board_info *db;
> + unsigned int id;
> + int ret = 0;
> +
> + ndev = devm_alloc_etherdev(dev, sizeof(struct board_info));
> + if (!ndev)
> + return -ENOMEM;
> +
> + SET_NETDEV_DEV(ndev, dev);
> + dev_set_drvdata(dev, ndev);
> + db = netdev_priv(ndev);
> + memset(db, 0, sizeof(struct board_info));

No need to use memset. If you look at how

devm_alloc_etherdev() is implemented you end up here:

https://elixir.bootlin.com/linux/v5.16-rc5/source/net/core/dev.c#L10801

The z in kvzalloc() means zero.

Andrew

\
 
 \ /
  Last update: 2021-12-16 22:57    [W:0.069 / U:0.056 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site