[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Mon, 18 Jan 2021 22:15:42 +0200
From: Vladimir Oltean <olteanv@...il.com>
To: "David S . Miller" <davem@...emloft.net>,
Jakub Kicinski <kuba@...nel.org>, netdev@...r.kernel.org
Cc: Andrew Lunn <andrew@...n.ch>,
Florian Fainelli <f.fainelli@...il.com>,
Vivien Didelot <vivien.didelot@...il.com>,
Richard Cochran <richardcochran@...il.com>,
Claudiu Manoil <claudiu.manoil@....com>,
Alexandru Marginean <alexandru.marginean@....com>,
Alexandre Belloni <alexandre.belloni@...tlin.com>,
Xiaoliang Yang <xiaoliang.yang_1@....com>,
Hongbo Wang <hongbo.wang@....com>, Po Liu <po.liu@....com>,
Yangbo Lu <yangbo.lu@....com>,
Maxim Kochetkov <fido_max@...ox.ru>,
Eldar Gasanov <eldargasanov2@...il.com>,
Andrey L <al@...omtech.com>, UNGLinuxDriver@...rochip.com
Subject: Re: [PATCH v3 net-next 10/15] net: mscc: ocelot: refactor
ocelot_port_inject_frame out of ocelot_port_xmit
On Mon, Jan 18, 2021 at 06:17:26PM +0200, Vladimir Oltean wrote:
> From: Vladimir Oltean <vladimir.oltean@....com>
>
> The felix DSA driver will inject some frames through register MMIO, same
> as ocelot switchdev currently does. So we need to be able to reuse the
> common code.
>
> Signed-off-by: Vladimir Oltean <vladimir.oltean@....com>
> ---
Sadly there are some build errors starting with this patch when
drivers/net/ethernet/mscc/mscc_ocelot.ko is built as module.
They are due to me not using EXPORT_SYMBOL on the refactored functions
that were moved inside the common mscc_ocelot_switch_lib. I am adding
the EXPORT_SYMBOL later (in the last patch I think) but it needs to be
done now.
> Changes in v3:
> None.
>
> Changes in v2:
> Patch is new.
>
> drivers/net/ethernet/mscc/ocelot.c | 78 +++++++++++++++++++++++++
> drivers/net/ethernet/mscc/ocelot.h | 4 ++
> drivers/net/ethernet/mscc/ocelot_net.c | 81 +++-----------------------
> 3 files changed, 89 insertions(+), 74 deletions(-)
>
> diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
> index 895df050abba..7aba384fe6bf 100644
> --- a/drivers/net/ethernet/mscc/ocelot.c
> +++ b/drivers/net/ethernet/mscc/ocelot.c
> @@ -561,6 +561,84 @@ void ocelot_get_txtstamp(struct ocelot *ocelot)
> }
> EXPORT_SYMBOL(ocelot_get_txtstamp);
>
> +/* Generate the IFH for frame injection
> + *
> + * The IFH is a 128bit-value
> + * bit 127: bypass the analyzer processing
> + * bit 56-67: destination mask
> + * bit 28-29: pop_cnt: 3 disables all rewriting of the frame
> + * bit 20-27: cpu extraction queue mask
> + * bit 16: tag type 0: C-tag, 1: S-tag
> + * bit 0-11: VID
> + */
> +static int ocelot_gen_ifh(u32 *ifh, struct frame_info *info)
> +{
> + ifh[0] = IFH_INJ_BYPASS | ((0x1ff & info->rew_op) << 21);
> + ifh[1] = (0xf00 & info->port) >> 8;
> + ifh[2] = (0xff & info->port) << 24;
> + ifh[3] = (info->tag_type << 16) | info->vid;
> +
> + return 0;
> +}
> +
> +bool ocelot_can_inject(struct ocelot *ocelot, int grp)
> +{
> + u32 val = ocelot_read(ocelot, QS_INJ_STATUS);
> +
> + if (!(val & QS_INJ_STATUS_FIFO_RDY(BIT(grp))))
> + return false;
> + if (val & QS_INJ_STATUS_WMARK_REACHED(BIT(grp)))
> + return false;
> +
> + return true;
> +}
> +
> +void ocelot_port_inject_frame(struct ocelot *ocelot, int port, int grp,
> + u32 rew_op, struct sk_buff *skb)
> +{
> + struct frame_info info = {};
> + u32 ifh[OCELOT_TAG_LEN / 4];
> + unsigned int i, count, last;
> +
> + ocelot_write_rix(ocelot, QS_INJ_CTRL_GAP_SIZE(1) |
> + QS_INJ_CTRL_SOF, QS_INJ_CTRL, grp);
> +
> + info.port = BIT(port);
> + info.tag_type = IFH_TAG_TYPE_C;
> + info.vid = skb_vlan_tag_get(skb);
> + info.rew_op = rew_op;
> +
> + ocelot_gen_ifh(ifh, &info);
> +
> + for (i = 0; i < OCELOT_TAG_LEN / 4; i++)
> + ocelot_write_rix(ocelot, (__force u32)cpu_to_be32(ifh[i]),
> + QS_INJ_WR, grp);
> +
> + count = DIV_ROUND_UP(skb->len, 4);
> + last = skb->len % 4;
> + for (i = 0; i < count; i++)
> + ocelot_write_rix(ocelot, ((u32 *)skb->data)[i], QS_INJ_WR, grp);
> +
> + /* Add padding */
> + while (i < (OCELOT_BUFFER_CELL_SZ / 4)) {
> + ocelot_write_rix(ocelot, 0, QS_INJ_WR, grp);
> + i++;
> + }
> +
> + /* Indicate EOF and valid bytes in last word */
> + ocelot_write_rix(ocelot, QS_INJ_CTRL_GAP_SIZE(1) |
> + QS_INJ_CTRL_VLD_BYTES(skb->len < OCELOT_BUFFER_CELL_SZ ? 0 : last) |
> + QS_INJ_CTRL_EOF,
> + QS_INJ_CTRL, grp);
> +
> + /* Add dummy CRC */
> + ocelot_write_rix(ocelot, 0, QS_INJ_WR, grp);
> + skb_tx_timestamp(skb);
> +
> + skb->dev->stats.tx_packets++;
> + skb->dev->stats.tx_bytes += skb->len;
> +}
> +
> int ocelot_fdb_add(struct ocelot *ocelot, int port,
> const unsigned char *addr, u16 vid)
> {
> diff --git a/drivers/net/ethernet/mscc/ocelot.h b/drivers/net/ethernet/mscc/ocelot.h
> index e8621dbc14f7..cf6493e55eab 100644
> --- a/drivers/net/ethernet/mscc/ocelot.h
> +++ b/drivers/net/ethernet/mscc/ocelot.h
> @@ -127,6 +127,10 @@ int ocelot_port_devlink_init(struct ocelot *ocelot, int port,
> enum devlink_port_flavour flavour);
> void ocelot_port_devlink_teardown(struct ocelot *ocelot, int port);
>
> +bool ocelot_can_inject(struct ocelot *ocelot, int grp);
> +void ocelot_port_inject_frame(struct ocelot *ocelot, int port, int grp,
> + u32 rew_op, struct sk_buff *skb);
> +
> extern struct notifier_block ocelot_netdevice_nb;
> extern struct notifier_block ocelot_switchdev_nb;
> extern struct notifier_block ocelot_switchdev_blocking_nb;
> diff --git a/drivers/net/ethernet/mscc/ocelot_net.c b/drivers/net/ethernet/mscc/ocelot_net.c
> index 55847d2a83e1..9a29d7d3b0e2 100644
> --- a/drivers/net/ethernet/mscc/ocelot_net.c
> +++ b/drivers/net/ethernet/mscc/ocelot_net.c
> @@ -488,53 +488,20 @@ static int ocelot_port_stop(struct net_device *dev)
> return 0;
> }
>
> -/* Generate the IFH for frame injection
> - *
> - * The IFH is a 128bit-value
> - * bit 127: bypass the analyzer processing
> - * bit 56-67: destination mask
> - * bit 28-29: pop_cnt: 3 disables all rewriting of the frame
> - * bit 20-27: cpu extraction queue mask
> - * bit 16: tag type 0: C-tag, 1: S-tag
> - * bit 0-11: VID
> - */
> -static int ocelot_gen_ifh(u32 *ifh, struct frame_info *info)
> -{
> - ifh[0] = IFH_INJ_BYPASS | ((0x1ff & info->rew_op) << 21);
> - ifh[1] = (0xf00 & info->port) >> 8;
> - ifh[2] = (0xff & info->port) << 24;
> - ifh[3] = (info->tag_type << 16) | info->vid;
> -
> - return 0;
> -}
> -
> -static int ocelot_port_xmit(struct sk_buff *skb, struct net_device *dev)
> +static netdev_tx_t ocelot_port_xmit(struct sk_buff *skb, struct net_device *dev)
> {
> struct ocelot_port_private *priv = netdev_priv(dev);
> - struct skb_shared_info *shinfo = skb_shinfo(skb);
> struct ocelot_port *ocelot_port = &priv->port;
> struct ocelot *ocelot = ocelot_port->ocelot;
> - u32 val, ifh[OCELOT_TAG_LEN / 4];
> - struct frame_info info = {};
> - u8 grp = 0; /* Send everything on CPU group 0 */
> - unsigned int i, count, last;
> int port = priv->chip_port;
> + u32 rew_op = 0;
>
> - val = ocelot_read(ocelot, QS_INJ_STATUS);
> - if (!(val & QS_INJ_STATUS_FIFO_RDY(BIT(grp))) ||
> - (val & QS_INJ_STATUS_WMARK_REACHED(BIT(grp))))
> + if (!ocelot_can_inject(ocelot, 0))
> return NETDEV_TX_BUSY;
>
> - ocelot_write_rix(ocelot, QS_INJ_CTRL_GAP_SIZE(1) |
> - QS_INJ_CTRL_SOF, QS_INJ_CTRL, grp);
> -
> - info.port = BIT(port);
> - info.tag_type = IFH_TAG_TYPE_C;
> - info.vid = skb_vlan_tag_get(skb);
> -
> /* Check if timestamping is needed */
> - if (ocelot->ptp && (shinfo->tx_flags & SKBTX_HW_TSTAMP)) {
> - info.rew_op = ocelot_port->ptp_cmd;
> + if (ocelot->ptp && (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
> + rew_op = ocelot_port->ptp_cmd;
>
> if (ocelot_port->ptp_cmd == IFH_REW_OP_TWO_STEP_PTP) {
> struct sk_buff *clone;
> @@ -547,45 +514,11 @@ static int ocelot_port_xmit(struct sk_buff *skb, struct net_device *dev)
>
> ocelot_port_add_txtstamp_skb(ocelot, port, clone);
>
> - info.rew_op |= clone->cb[0] << 3;
> + rew_op |= clone->cb[0] << 3;
> }
> }
>
> - if (ocelot->ptp && shinfo->tx_flags & SKBTX_HW_TSTAMP) {
> - info.rew_op = ocelot_port->ptp_cmd;
> - if (ocelot_port->ptp_cmd == IFH_REW_OP_TWO_STEP_PTP)
> - info.rew_op |= skb->cb[0] << 3;
> - }
> -
> - ocelot_gen_ifh(ifh, &info);
> -
> - for (i = 0; i < OCELOT_TAG_LEN / 4; i++)
> - ocelot_write_rix(ocelot, (__force u32)cpu_to_be32(ifh[i]),
> - QS_INJ_WR, grp);
> -
> - count = DIV_ROUND_UP(skb->len, 4);
> - last = skb->len % 4;
> - for (i = 0; i < count; i++)
> - ocelot_write_rix(ocelot, ((u32 *)skb->data)[i], QS_INJ_WR, grp);
> -
> - /* Add padding */
> - while (i < (OCELOT_BUFFER_CELL_SZ / 4)) {
> - ocelot_write_rix(ocelot, 0, QS_INJ_WR, grp);
> - i++;
> - }
> -
> - /* Indicate EOF and valid bytes in last word */
> - ocelot_write_rix(ocelot, QS_INJ_CTRL_GAP_SIZE(1) |
> - QS_INJ_CTRL_VLD_BYTES(skb->len < OCELOT_BUFFER_CELL_SZ ? 0 : last) |
> - QS_INJ_CTRL_EOF,
> - QS_INJ_CTRL, grp);
> -
> - /* Add dummy CRC */
> - ocelot_write_rix(ocelot, 0, QS_INJ_WR, grp);
> - skb_tx_timestamp(skb);
> -
> - dev->stats.tx_packets++;
> - dev->stats.tx_bytes += skb->len;
> + ocelot_port_inject_frame(ocelot, port, 0, rew_op, skb);
>
> kfree_skb(skb);
>
> --
> 2.25.1
>
Powered by blists - more mailing lists