Message ID | 20210118161731.2837700-11-olteanv@gmail.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | tag_8021q for Ocelot switches | expand |
Context | Check | Description |
---|---|---|
netdev/cover_letter | success | Link |
netdev/fixes_present | success | Link |
netdev/patch_count | success | Link |
netdev/tree_selection | success | Clearly marked for net-next |
netdev/subject_prefix | success | Link |
netdev/cc_maintainers | warning | 1 maintainers not CCed: vladimir.oltean@nxp.com |
netdev/source_inline | success | Was 0 now: 0 |
netdev/verify_signedoff | success | Link |
netdev/module_param | success | Was 0 now: 0 |
netdev/build_32bit | fail | Errors and warnings before: 0 this patch: 5 |
netdev/kdoc | success | Errors and warnings before: 0 this patch: 0 |
netdev/verify_fixes | success | Link |
netdev/checkpatch | warning | WARNING: line length of 93 exceeds 80 columns |
netdev/build_allmodconfig_warn | fail | Errors and warnings before: 0 this patch: 5 |
netdev/header_inline | success | Link |
netdev/stable | success | Stable not CCed |
On Mon, Jan 18, 2021 at 06:17:26PM +0200, Vladimir Oltean wrote: > From: Vladimir Oltean <vladimir.oltean@nxp.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@nxp.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 >
Hi Vladimir,
I love your patch! Yet something to improve:
[auto build test ERROR on net-next/master]
url: https://github.com/0day-ci/linux/commits/Vladimir-Oltean/tag_8021q-for-Ocelot-switches/20210119-004520
base: https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git 213b97b125808aa220ba460a7af09d8f3772f669
config: sh-allmodconfig (attached as .config)
compiler: sh4-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/0day-ci/linux/commit/b0c94dae99772294285cc3219500b73026853e83
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Vladimir-Oltean/tag_8021q-for-Ocelot-switches/20210119-004520
git checkout b0c94dae99772294285cc3219500b73026853e83
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=sh
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
All errors (new ones prefixed by >>, old ones prefixed by <<):
>> ERROR: modpost: "ocelot_can_inject" [drivers/net/ethernet/mscc/mscc_ocelot.ko] undefined!
ERROR: modpost: "ocelot_port_inject_frame" [drivers/net/ethernet/mscc/mscc_ocelot.ko] undefined!
ERROR: modpost: "__delay" [drivers/net/mdio/mdio-cavium.ko] undefined!
ERROR: modpost: "__udivdi3" [fs/btrfs/btrfs.ko] undefined!
ERROR: modpost: "__umoddi3" [fs/btrfs/btrfs.ko] undefined!
Kconfig warnings: (for reference only)
WARNING: unmet direct dependencies detected for SND_ATMEL_SOC_PDC
Depends on SOUND && !UML && SND && SND_SOC && SND_ATMEL_SOC && HAS_DMA
Selected by
- SND_ATMEL_SOC_SSC && SOUND && !UML && SND && SND_SOC && SND_ATMEL_SOC
- SND_ATMEL_SOC_SSC_PDC && SOUND && !UML && SND && SND_SOC && SND_ATMEL_SOC && ATMEL_SSC
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
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);