All of lore.kernel.org
 help / color / mirror / Atom feed
From: Vadym Kochan <vadym.kochan@plvision.eu>
To: Andy Shevchenko <andy.shevchenko@gmail.com>
Cc: "David S. Miller" <davem@davemloft.net>,
	Jakub Kicinski <kuba@kernel.org>, Jiri Pirko <jiri@mellanox.com>,
	Ido Schimmel <idosch@mellanox.com>, Andrew Lunn <andrew@lunn.ch>,
	Oleksandr Mazur <oleksandr.mazur@plvision.eu>,
	Serhiy Boiko <serhiy.boiko@plvision.eu>,
	Serhiy Pshyk <serhiy.pshyk@plvision.eu>,
	Volodymyr Mytnyk <volodymyr.mytnyk@plvision.eu>,
	Taras Chornyi <taras.chornyi@plvision.eu>,
	Andrii Savka <andrii.savka@plvision.eu>,
	netdev <netdev@vger.kernel.org>,
	Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
	Mickey Rachamim <mickeyr@marvell.com>
Subject: Re: [PATCH net-next v7 1/6] net: marvell: prestera: Add driver for Prestera family ASIC devices
Date: Mon, 7 Sep 2020 10:30:40 +0300	[thread overview]
Message-ID: <20200907073040.GA3562@plvision.eu> (raw)
In-Reply-To: <CAHp75Vc_MN-tD+iQNbUcB6fbYizyfKJSJnm1W7uXCT6JAvPauA@mail.gmail.com>

Hi Andy,

On Fri, Sep 04, 2020 at 10:12:07PM +0300, Andy Shevchenko wrote:
> On Fri, Sep 4, 2020 at 7:52 PM Vadym Kochan <vadym.kochan@plvision.eu> wrote:
> >
> > Marvell Prestera 98DX326x integrates up to 24 ports of 1GbE with 8
> > ports of 10GbE uplinks or 2 ports of 40Gbps stacking for a largely
> > wireless SMB deployment.
> >
> > The current implementation supports only boards designed for the Marvell
> > Switchdev solution and requires special firmware.
> >
> > The core Prestera switching logic is implemented in prestera_main.c,
> > there is an intermediate hw layer between core logic and firmware. It is
> > implemented in prestera_hw.c, the purpose of it is to encapsulate hw
> > related logic, in future there is a plan to support more devices with
> > different HW related configurations.
> >
> > This patch contains only basic switch initialization and RX/TX support
> > over SDMA mechanism.
> >
> > Currently supported devices have DMA access range <= 32bit and require
> > ZONE_DMA to be enabled, for such cases SDMA driver checks if the skb
> > allocated in proper range supported by the Prestera device.
> >
> > Also meanwhile there is no TX interrupt support in current firmware
> > version so recycling work is scheduled on each xmit.
> >
> > Port's mac address is generated from the switch base mac which may be
> > provided via device-tree (static one or as nvme cell), or randomly
> > generated. This is required by the firmware.
> 
> ...
> 
> > +#define prestera_dev(sw)               ((sw)->dev->dev)
> 
> The point of this is...? (What I see it's 2 characters longer)
> 
> ...
It is not about the length but rather about easier semantics, so
the prestera_dev() is more easier to remember than sw->dev->dev.

> 
> > +       words[0] = ntohl(dsa_words[0]);
> > +       words[1] = ntohl(dsa_words[1]);
> > +       words[2] = ntohl(dsa_words[2]);
> > +       words[3] = ntohl(dsa_words[3]);
> 
> This is (semi-)NIH of be32_to_cpu_array()
> 
> You may add an additional patch to provide ntohl_array() as an alias
> how it's done for the rest:
> https://elixir.bootlin.com/linux/v5.9-rc3/source/include/linux/byteorder/generic.h#L123
> 
> ...
> 
> > +       dsa->vlan.vid &= ~PRESTERA_VID_MASK;
> > +       dsa->vlan.vid |= FIELD_PREP(PRESTERA_VID_MASK, field);
> 
> Consider to use uXX_replace_bits() (XX for size of the variable).
> Look at bitfield.h closer.
> 
> ...
> 
> > +       dsa->hw_dev_num &= PRESTERA_W3_HW_DEV_NUM;
> > +       dsa->hw_dev_num |= FIELD_PREP(PRESTERA_DEV_NUM_MASK, field);
> 
> Ditto? (Not sure why first line w/o _MASK)
> 
> ...
> 
> > +       if (dsa->hw_dev_num >= BIT(12))
> > +               return -EINVAL;
> > +       if (dsa->port_num >= BIT(17))
> > +               return -EINVAL;
> 
> Magic numbers!
> 
> ...
> 
> > +       words[3] |= FIELD_PREP(PRESTERA_W3_HW_DEV_NUM, (dsa->hw_dev_num >> 5));
> 
> Ditto.
> 
> ...
> 
> > +       dsa_words[0] = htonl(words[0]);
> > +       dsa_words[1] = htonl(words[1]);
> > +       dsa_words[2] = htonl(words[2]);
> > +       dsa_words[3] = htonl(words[3]);
> 
> NIH of cpu_to_be32_array().
> 
> ...
> 
> > +/*
> > + * Copyright (c) 2020 Marvell International Ltd. All rights reserved.
> > + *
> > + */
> 
> One line.
> 
> ...
> 
> > +       err = prestera_find_event_handler(sw, msg->type, &eh);
> 
> > +       if (err || !fw_event_parsers[msg->type].func)
> > +               return -EEXIST;
> 
> Why shadowing error code?
> 
> ...
> 
> > +       struct prestera_msg_port_info_req req = {
> > +               .port = port->id
> 
> Leave comma here.
> Another possibility, if you not expect this to grow, move to one line.
> 
> > +       };
> 
> ...
> 
> > +               .param = {.admin_state = admin_state}
> 
> + white spaces? Whatever you choose, just be consistent among all
> similar definitions.
> 
> ...
> 
> > +               .port = port->hw_id,
> > +               .dev = port->dev_id
> 
> Leave comma.
> 
> ...
> 
> > +       struct prestera_msg_port_attr_req req = {
> > +               .attr = PRESTERA_CMD_PORT_ATTR_CAPABILITY,
> > +               .port = port->hw_id,
> > +               .dev = port->dev_id
> 
> Ditto. I have a deja vu that I already pointed out to these.
> 
> > +       };
> 
> ...
> 
> > +       err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
> > +                              &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
> > +       if (err)
> > +               return err;
> > +
> > +       caps->supp_link_modes = resp.param.cap.link_mode;
> > +       caps->supp_fec = resp.param.cap.fec;
> > +       caps->type = resp.param.cap.type;
> > +       caps->transceiver = resp.param.cap.transceiver;
> > +
> 
> > +       return err;
> 
> return 0;
> 
> > +}
> 
> ...
> 
> > +               .param = {.autoneg = {.link_mode = link_modes,
> > +                                     .enable = autoneg,
> > +                                     .fec = fec}
> 
> Fix indentation and style.
> 
> > +               }
> 
> ...
> 
> > +       struct prestera_msg_port_attr_req req = {
> > +               .attr = PRESTERA_CMD_PORT_ATTR_STATS,
> > +               .port = port->hw_id,
> > +               .dev = port->dev_id
> 
> + Comma.
> 
> > +       };
> 
> ...
> 
> > +/*
> > + * Copyright (c) 2019-2020 Marvell International Ltd. All rights reserved.
> > + *
> > + */
> 
> One line.
> 
> ...
> 
> > +#include <linux/kernel.h>
> > +#include <linux/module.h>
> > +#include <linux/list.h>
> > +#include <linux/netdevice.h>
> > +#include <linux/netdev_features.h>
> > +#include <linux/etherdevice.h>
> > +#include <linux/jiffies.h>
> > +#include <linux/of.h>
> > +#include <linux/of_net.h>
> 
> Perhaps sorted?
> 
> ...
> 
> > +static int prestera_port_state_set(struct net_device *dev, bool is_up)
> > +{
> > +       struct prestera_port *port = netdev_priv(dev);
> > +       int err;
> > +
> > +       if (is_up) {
> > +               err = prestera_hw_port_state_set(port, true);
> > +               if (err)
> > +                       return err;
> > +
> > +               netif_start_queue(dev);
> > +       } else {
> > +               netif_stop_queue(dev);
> > +
> > +               err = prestera_hw_port_state_set(port, false);
> > +               if (err)
> > +                       return err;
> > +       }
> > +
> > +       return 0;
> > +}
> > +
> > +static int prestera_port_open(struct net_device *dev)
> > +{
> > +       return prestera_port_state_set(dev, true);
> > +}
> > +
> > +static int prestera_port_close(struct net_device *dev)
> > +{
> > +       return prestera_port_state_set(dev, false);
> > +}
> 
> What the point to have above function if you simple can put its
> contents in these two?
> 
This is really makes sense.

> ...
> 
> > +       /* firmware requires that port's mac address contains first 5 bytes
> > +        * of base mac address
> 
> mac -> MAC? (two cases)
> 
> > +        */
> 
> ...
> 
> > +static int prestera_port_autoneg_set(struct prestera_port *port, bool enable,
> > +                                    u64 link_modes, u8 fec)
> > +{
> > +       bool refresh = false;
> 
> > +       int err = 0;
> 
> Redundant assignment.
> 
> > +       if (port->caps.type != PRESTERA_PORT_TYPE_TP)
> > +               return enable ? -EINVAL : 0;
> > +
> > +       if (port->adver_link_modes != link_modes || port->adver_fec != fec) {
> > +               port->adver_fec = fec ?: BIT(PRESTERA_PORT_FEC_OFF);
> > +               port->adver_link_modes = link_modes;
> > +               refresh = true;
> > +       }
> > +
> > +       if (port->autoneg == enable && !(port->autoneg && refresh))
> > +               return 0;
> > +
> > +       err = prestera_hw_port_autoneg_set(port, enable, port->adver_link_modes,
> > +                                          port->adver_fec);
> > +       if (err)
> 
> > +               return -EINVAL;
> 
> Why shadowed?
> 
> > +       port->autoneg = enable;
> > +       return 0;
> > +}
> 
> ...
> 
> > +       /* firmware requires that port's mac address consist of the first
> > +        * 5 bytes of base mac address
> > +        */
> 
> 
> > +       memcpy(dev->dev_addr, sw->base_mac, dev->addr_len - 1);
> 
> Can't you call above helper for that?

Not sure if I got this right, but I assume that may be just use
ether_addr_copy() and then just perform the below assignment on the
last byte ?

> 
> ...
> 
> > +       dev->dev_addr[dev->addr_len - 1] = (char)port->fp_id;
> 
> Why explicit casting?
> 
> ...
> 
> > +static int prestera_switch_set_base_mac_addr(struct prestera_switch *sw)
> > +{
> > +       struct device_node *base_mac_np;
> > +       struct device_node *np;
> > +
> > +       np = of_find_compatible_node(NULL, NULL, "marvell,prestera");
> 
> > +       if (np) {
> 
> I think it's useless check, b/c...
> 
> > +               base_mac_np = of_parse_phandle(np, "base-mac-provider", 0);
> 
> ...this will return error.
> 
> So, something like struct device_node *np = of_find_...(...); above.
> 
> > +               if (base_mac_np) {
> 
> I think it's useless check.
> Similar as above.
> 
Really!

> > +                       const char *base_mac;
> > +
> > +                       base_mac = of_get_mac_address(base_mac_np);
> > +                       of_node_put(base_mac_np);
> > +                       if (!IS_ERR(base_mac))
> > +                               ether_addr_copy(sw->base_mac, base_mac);
> > +               }
> > +       }
> > +       if (!is_valid_ether_addr(sw->base_mac)) {
> > +               eth_random_addr(sw->base_mac);
> > +               dev_info(sw->dev->dev, "using random base mac address\n");
> > +       }
> > +
> > +       return prestera_hw_switch_mac_set(sw, sw->base_mac);
> > +}
> 
> ...
> 
> > +int prestera_device_register(struct prestera_device *dev)
> > +{
> > +       struct prestera_switch *sw;
> > +       int err;
> > +
> > +       sw = kzalloc(sizeof(*sw), GFP_KERNEL);
> > +       if (!sw)
> > +               return -ENOMEM;
> > +
> > +       dev->priv = sw;
> > +       sw->dev = dev;
> > +
> > +       err = prestera_switch_init(sw);
> > +       if (err) {
> > +               kfree(sw);
> 
> > +               return err;
> > +       }
> > +
> > +       return 0;
> 
> return err;
> 
> > +}
> 
> ...
> 
> > +#include <linux/dmapool.h>
> > +#include <linux/etherdevice.h>
> > +#include <linux/if_vlan.h>
> > +#include <linux/of.h>
> > +#include <linux/of_address.h>
> > +#include <linux/of_device.h>
> > +#include <linux/netdevice.h>
> > +#include <linux/platform_device.h>
> 
> ...
> 
> > +#define PRESTERA_SDMA_RX_DESC_IS_RCVD(desc) \
> > +       (PRESTERA_SDMA_RX_DESC_OWNER((desc)) == PRESTERA_SDMA_RX_DESC_CPU_OWN)
> 
> Double (()) make no sense here.
> 
> ...
> 
> > +static void prestera_sdma_rx_desc_set_len(struct prestera_sdma_desc *desc,
> > +                                         size_t val)
> > +{
> > +       u32 word = le32_to_cpu(desc->word2);
> > +
> > +       word = (word & ~GENMASK(15, 0)) | val;
> > +       desc->word2 = cpu_to_le32(word);
> > +}
> 
> Why not simple le32_replace_bits() ?
> 
I was not aware of these helpers, thanks.

> ...
> 
> > +       port = prestera_port_find_by_hwid(sdma->sw, dev_id, hw_port);
> > +       if (unlikely(!port)) {
> 
> > +               pr_warn_ratelimited("received pkt for non-existent port(%u, %u)\n",
> > +                                   dev_id, hw_port);
> 
> What's wrong with dev_warn_ratelimited() ?
> 
I will use it, thanks.

> > +               return -EEXIST;
> > +       }
> 
> ...
> 
> > +               for (b = 0; b < bnum; b++) {
> > +                       struct prestera_sdma_buf *buf = &ring->bufs[b];
> > +
> > +                       err = prestera_sdma_buf_init(sdma, buf);
> > +                       if (err)
> > +                               return err;
> > +
> > +                       err = prestera_sdma_rx_skb_alloc(sdma, buf);
> > +                       if (err)
> 
> No need to uninit previously init buffers?
> No need to dealloc previously allocated stuff?
> 
> > +                               return err;
This is done in the prestera_rxtx.c:prestera_sdma_switch_init() caller
which calls the generic rx_uninit() on error path handling.

> 
> ...
> 
> > +                       if (b == 0)
> > +                               continue;
> > +
> > +                       prestera_sdma_rx_desc_set_next(sdma,
> > +                                                      ring->bufs[b - 1].desc,
> > +                                                      buf->desc_dma);
> > +
> > +                       if (b == PRESTERA_SDMA_RX_DESC_PER_Q - 1)
> > +                               prestera_sdma_rx_desc_set_next(sdma, buf->desc,
> > +                                                              head->desc_dma);
> 
> I guess knowing what the allowed range of bnum the above can be optimized.
> 
> > +               }
I will think of this, thanks.

> 
> ...
> 
> > +       u32 word = le32_to_cpu(desc->word2);
> > +
> > +       word = (word & ~GENMASK(30, 16)) | ((len + ETH_FCS_LEN) << 16);
> > +
> > +       desc->word2 = cpu_to_le32(word);
> 
> le32_replace_bits()
> 
> ...
> 
> > +static void prestera_sdma_tx_desc_xmit(struct prestera_sdma_desc *desc)
> > +{
> > +       u32 word = le32_to_cpu(desc->word1);
> > +
> > +       word |= PRESTERA_SDMA_TX_DESC_DMA_OWN << 31;
> > +
> > +       /* make sure everything is written before enable xmit */
> > +       wmb();
> > +
> > +       desc->word1 = cpu_to_le32(word);
> 
> Seems to me it's also safe to use le32_replace_bits(), but I'm not
> sure if desc->word1 can be changed after barrier by somebody else.
> 
> > +}
> 
> ...
> 
> > +       for (b = 0; b < bnum; b++) {
> > +               struct prestera_sdma_buf *buf = &tx_ring->bufs[b];
> > +
> > +               err = prestera_sdma_buf_init(sdma, buf);
> > +               if (err)
> > +                       return err;
> > +
> > +               prestera_sdma_tx_desc_init(sdma, buf->desc);
> > +
> > +               buf->is_used = false;
> > +
> > +               if (b == 0)
> > +                       continue;
> > +
> > +               prestera_sdma_tx_desc_set_next(sdma, tx_ring->bufs[b - 1].desc,
> > +                                              buf->desc_dma);
> > +
> > +               if (b == PRESTERA_SDMA_TX_DESC_PER_Q - 1)
> > +                       prestera_sdma_tx_desc_set_next(sdma, buf->desc,
> > +                                                      head->desc_dma);
> > +       }
> 
> Similar comments as per above similar for-loop.
> 
> ...
> 
> > +static int prestera_sdma_tx_wait(struct prestera_sdma *sdma,
> > +                                struct prestera_tx_ring *tx_ring)
> > +{
> > +       int tx_retry_num = PRESTERA_SDMA_WAIT_MUL * tx_ring->max_burst;
> > +
> > +       do {
> > +               if (prestera_sdma_is_ready(sdma))
> > +                       return 0;
> > +
> > +               udelay(1);
> > +       } while (--tx_retry_num);
> > +
> > +       return -EBUSY;
> > +}
> 
> iopoll.h
> readx_poll_timeout().
> 
> ...
> 
> > +/*
> > + * Copyright (c) 2019-2020 Marvell International Ltd. All rights reserved.
> > + *
> > + */
> 
> One line.
> 
> ...
> 
> > +#include "prestera.h"
> 
> I don't see users of the above header here. You may use declarations instead.
> 
> > +int prestera_rxtx_switch_init(struct prestera_switch *sw);
> > +void prestera_rxtx_switch_fini(struct prestera_switch *sw);
> > +
> > +int prestera_rxtx_port_init(struct prestera_port *port);
> > +
> > +netdev_tx_t prestera_rxtx_xmit(struct prestera_port *port, struct sk_buff *skb);
> 
> -- 
> With Best Regards,
> Andy Shevchenko

Thanks a lot!

  reply	other threads:[~2020-09-07  7:31 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-09-04 16:52 [PATCH net-next v7 0/6] net: marvell: prestera: Add Switchdev driver for Prestera family ASIC device 98DX3255 (AC3x) Vadym Kochan
2020-09-04 16:52 ` [PATCH net-next v7 1/6] net: marvell: prestera: Add driver for Prestera family ASIC devices Vadym Kochan
2020-09-04 19:12   ` Andy Shevchenko
2020-09-07  7:30     ` Vadym Kochan [this message]
2020-09-07  7:55       ` Andy Shevchenko
2020-09-09 14:17         ` Vadym Kochan
2020-09-08  8:35     ` Vadym Kochan
2020-09-08  9:38       ` Andy Shevchenko
2020-09-09 14:00         ` Vadym Kochan
2020-09-09 14:09           ` Andy Shevchenko
2020-09-10  8:25     ` Vadym Kochan
2020-09-10 11:28       ` Andy Shevchenko
2020-09-04 16:52 ` [PATCH net-next v7 2/6] net: marvell: prestera: Add PCI interface support Vadym Kochan
2020-09-04 19:25   ` Andy Shevchenko
2020-09-04 16:52 ` [PATCH net-next v7 3/6] net: marvell: prestera: Add basic devlink support Vadym Kochan
2020-09-04 16:52 ` [PATCH net-next v7 4/6] net: marvell: prestera: Add ethtool interface support Vadym Kochan
2020-09-04 19:38   ` Andy Shevchenko
2020-09-04 16:52 ` [PATCH net-next v7 5/6] net: marvell: prestera: Add Switchdev driver implementation Vadym Kochan
2020-09-04 19:41   ` Andy Shevchenko
2020-09-10  7:03     ` Vadym Kochan
2020-09-04 16:52 ` [PATCH net-next v7 6/6] dt-bindings: marvell,prestera: Add description for device-tree bindings Vadym Kochan

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=20200907073040.GA3562@plvision.eu \
    --to=vadym.kochan@plvision.eu \
    --cc=andrew@lunn.ch \
    --cc=andrii.savka@plvision.eu \
    --cc=andy.shevchenko@gmail.com \
    --cc=davem@davemloft.net \
    --cc=idosch@mellanox.com \
    --cc=jiri@mellanox.com \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mickeyr@marvell.com \
    --cc=netdev@vger.kernel.org \
    --cc=oleksandr.mazur@plvision.eu \
    --cc=serhiy.boiko@plvision.eu \
    --cc=serhiy.pshyk@plvision.eu \
    --cc=taras.chornyi@plvision.eu \
    --cc=volodymyr.mytnyk@plvision.eu \
    /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.