* Re: net: ipv6: Fix a bug in ndisc_send_ns when netdev only has a global address
From: Mark Smith @ 2019-07-30 10:28 UTC (permalink / raw)
To: Su Yanjun; +Cc: netdev
In-Reply-To: <93c401b9-bf8b-4d49-9c3b-72d09073444e@cn.fujitsu.com>
Hi Su,
On Tue, 30 Jul 2019 at 19:41, Su Yanjun <suyj.fnst@cn.fujitsu.com> wrote:
>
>
> 在 2019/7/30 16:15, Mark Smith 写道:
> > Hi,
> >
> > I'm not subscribed to the Linux netdev mailing list, so I can't
> > directly reply to the patch email.
> >
> > This patch is not the correct solution to this issue.
> >
<snip>
> In linux implementation, one interface may have no link local address if
> kernel config
>
> *addr_gen_mode* is set to IN6_ADDR_GEN_MODE_NONE. My patch is to fix
> this problem.
>
So this "IN6_ADDR_GEN_MODE_NONE" behaviour doesn't comply with RFC 4291.
As RFC 4291 says,
"All interfaces are *required* to have *at least one* Link-Local
unicast address."
That's not an ambiguous requirement.
This specific, explicit requirement goes as back as far as RFC 2373
from 1998, the ancestor of RFC 4291. It is also heavily implied in RFC
1884s, 2.7 A Node's Required Addresses.
> And what you say is related to the lo interface. I'm not sure whether
> the lo interface needs a ll adreess.
>
It is an IPv6 enabled interface, so it requires a link-local address,
per RFC 4291. RFC 4291 doesn't exclude any interfaces types from the
LL address requirement.
Even special NBMA links/interfaces are not excluded from this
requirement, as Link-Local addresses are formed and used in the NBMA
operation, per RFC 2491.
> IMO the ll address is used to get l2 address by sending ND ns. The lo is
> very special.
>
From an IPv6 perspective, the virtual loopback interface isn't all that special.
A general theme of IPv6 is to try to treat things as similarly as
possible, compared to the IPv4 where a lot of things were treated as
special cases (e.g. ND runs over ICMPv4, in comparison to ARP running
directly and only over Ethernet/802.3. RFC 4861 treats point-to-point
links as multicast capable links, emulating multicast if necessary.
RAs and DHCPv6 are used over PPP links to carry parameters, rather
than using IPv6CP, compared to using IPv4 IPCP to carry e.g. DNS
addresses)
The main place the loopback behaviour causes issues is with IPv6 ND
Duplicate Address Detection. Appendix A of RFC 4861, and RFC 7527,
"Enhanced Duplicate Address Detection" discuss how to deal with that.
Some physical interfaces can be in loopback mode too, so IPv6 DAD has
to deal with that temporary situation.
LL addresses are and can be used for lots of things, including by
end-user applications as a preference when there is a choice between a
set of LL addr(s), GUA and ULA addresses.
Here is an Internet Draft that describes the general characteristics
of Link-Local addresses with references, as well as the benefits of
and how to use them in applications.
"How to use IPv6 Link-Local Addresses in Applications"
https://tools.ietf.org/html/draft-smith-ipv6-link-locals-apps-00
Regards,
Mark.
> Thanks
>
> Su
>
> >
> > "2.1. Addressing Model"
> >
> > ...
> >
> > "All interfaces are required to have at least one Link-Local unicast
> > address (see Section 2.8 for additional required addresses)."
> >
> > I have submitted a more specific bug regarding no Link-Local
> > address/prefix on the Linux kernel loopback interface through RedHat
> > bugzilla as I use Fedora 30, however it doesn't seem to have been
> > looked at yet.
> >
> > "Loopback network interface does not have a Link Local address,
> > contrary to RFC 4291"
> > https://bugzilla.redhat.com/show_bug.cgi?id=1706709
> >
> >
> > Thanks very much,
> > Mark.
> >
> >
>
>
^ permalink raw reply
* Re: [PATCH 03/12] block: bio_release_pages: use flags arg instead of bool
From: Christoph Hellwig @ 2019-07-30 10:25 UTC (permalink / raw)
To: Jerome Glisse
Cc: Christoph Hellwig, john.hubbard, Andrew Morton, Alexander Viro,
Anna Schumaker, David S . Miller, Dominique Martinet,
Eric Van Hensbergen, Jason Gunthorpe, Jason Wang, Jens Axboe,
Latchesar Ionkov, Michael S . Tsirkin, Miklos Szeredi,
Trond Myklebust, Christoph Hellwig, Matthew Wilcox, linux-mm,
LKML, ceph-devel, kvm, linux-block, linux-cifs, linux-fsdevel,
linux-nfs, linux-rdma, netdev, samba-technical, v9fs-developer,
virtualization, John Hubbard, Minwoo Im
In-Reply-To: <20190729205721.GB3760@redhat.com>
On Mon, Jul 29, 2019 at 04:57:21PM -0400, Jerome Glisse wrote:
> > All pages releases by bio_release_pages should come from
> > get_get_user_pages, so I don't really see the point here.
>
> No they do not all comes from GUP for see various callers
> of bio_check_pages_dirty() for instance iomap_dio_zero()
>
> I have carefully tracked down all this and i did not do
> anyconvertion just for the fun of it :)
Well, the point is _should_ not necessarily do. iomap_dio_zero adds the
ZERO_PAGE, which we by definition don't need to refcount. So we can
mark this bio BIO_NO_PAGE_REF safely after removing the get_page there.
Note that the equivalent in the old direct I/O code, dio_refill_pages,
will be a little more complicated as it can match user pages and the
ZERO_PAGE in a single bio, so a per-bio flag won't handle it easily.
Maybe we just need to use a separate bio there as well.
In general with series like this we should not encode the status quo an
pile new hacks upon the old one, but thing where we should be and fix
up the old warts while having to wade through all that code.
^ permalink raw reply
* Re: [RFC PATCH 1/2] gianfar: convert to phylink
From: Russell King - ARM Linux admin @ 2019-07-30 10:23 UTC (permalink / raw)
To: Vladimir Oltean
Cc: Arseny Solokha, Claudiu Manoil, Ioana Ciornei, Andrew Lunn,
netdev, Florian Fainelli
In-Reply-To: <CA+h21hpacLmKzoeKrdE-frZSTsiYCi4rKCObJ4LfAmfrCJ6H9g@mail.gmail.com>
On Tue, Jul 30, 2019 at 02:39:58AM +0300, Vladimir Oltean wrote:
> To be honest I don't have a complete answer to that question. The
> literature recommends writing 0x01a0 to the MII_ADVERTISE (0x4)
> register of the MAC PCS for 1000Base-X, and 0x4001 for SGMII.
That looks entirely sane for both modes.
0x01a0 for 802.3z (1000BASE-X) is defined in 802.3 37.2.5.1.3 as:
bit 5 - full duplex = 1
bit 6 - half duplex = 0
bit 7 - pause = 1
bit 8 - asym_pause = 1
The description of the bits match the config word that is sent in the
link with the exception of bit 14, which is the acknowledgement bit.
Normally, in 802.3z, bit 14 will not be set in the transmitted config
word until we have received the config word from the other end of the
link.
For SGMII, 0x4001 is the acknowledgement code word, which is defined
in the SGMII spec as "tx_config_Reg[15:0] sent from the MAC to the
PHY" which requires:
bit 0 - must be 1
bit 1 .. 13, 15 - must be 0, reserved for future use
bit 14 - must be 1 (auto-negotiation acknowledgement in 802.3z)
> The FMan driver which uses the TSEC MAC does exactly that:
> https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git/tree/drivers/net/ethernet/freescale/fman/fman_dtsec.c#n58
> However I can't seem to be able to trace down the definition of bit 14
> from 0x4001 - it's reserved in all the manuals I see. I have a hunch
> that it selects the format of the Config_Reg base page between
> 1000Base-X and SGMII.
It could be that is what bit 14 is being used for, or it could just be
that they've taken the values from the appropriate specs, and the
hardware behaves the same way irrespective of whether it is in SGMII
or 1000BASE-X mode.
> > +static int gfar_mac_link_state(struct phylink_config *config,
> > + struct phylink_link_state *state)
> > +{
> > + if (state->interface == PHY_INTERFACE_MODE_SGMII ||
> > + state->interface == PHY_INTERFACE_MODE_1000BASEX) {
>
> What if you reduce the indentation level by 1 here, by just exiting if
> the interface mode is not SGMII?
It's only called for in-band negotiation modes anyway, so the above
protection probably doesn't gain much.
> > + struct gfar_private *priv =
> > + netdev_priv(to_net_dev(config->dev));
> > + u16 tbi_cr;
> > +
> > + if (!priv->tbi_phy)
> > + return -ENODEV;
> > +
> > + tbi_cr = phy_read(priv->tbi_phy, MII_TBI_CR);
> > +
> > + state->duplex = !!(tbi_cr & TBI_CR_FULL_DUPLEX);
>
> Woah there. Aren't you supposed to first ensure state->an_complete is
> ok, based on TBI_MII_Register_Set_SR[AN_Done]? There's also a
> Link_Status bit in that register that you could retrieve.
Indeed.
> > + if ((tbi_cr & TBI_CR_SPEED_1000_MASK) == TBI_CR_SPEED_1000_MASK)
> > + state->speed = SPEED_1000;
> > + }
>
> See the Speed_Bit table from TBI_MII_Register_Set_ANLPBPA_SGMII for
> the link partner (aka SGMII PHY) advertisement. You have to do a
> logical-and between that and your own. Also please make sure you
> really are in SGMII AN and not 1000 Base-X when interpreting registers
> 4 & 5 as one way or another.
From what you've said above, yes, this needs to do exactly that.
> > -static noinline void gfar_update_link_state(struct gfar_private *priv)
> > +static void gfar_mac_config(struct phylink_config *config, unsigned int mode,
> > + const struct phylink_link_state *state)
> > {
> > + struct gfar_private *priv = netdev_priv(to_net_dev(config->dev));
> > struct gfar __iomem *regs = priv->gfargrp[0].regs;
> > - struct net_device *ndev = priv->ndev;
> > - struct phy_device *phydev = ndev->phydev;
> > - struct gfar_priv_rx_q *rx_queue = NULL;
> > - int i;
> > + u32 maccfg1, new_maccfg1;
> > + u32 maccfg2, new_maccfg2;
> > + u32 ecntrl, new_ecntrl;
> > + u32 tx_flow, new_tx_flow;
>
> Don't introduce new_ variables. Is there any issue if you
> unconditionally write to the MAC registers?
We do this in every driver, as mac_config() can be called with only a
small number of changes in the settings, and it is important not to
upset the MAC for minor updates.
An example of this is when we are in SGMII mode with an attached PHY.
SGMII will communicate the speed and duplex, but not the results of
the pause negotiation. We read that from the attached PHY and report
it back by calling mac_config() - but at that point, we don't want to
cause the established link to bounce.
So, mac_config() should be implemented to avoid upsetting an already
established link where possible (unless the configuration items that
affect the link have changed.)
> > +static void gfar_mac_an_restart(struct phylink_config *config)
> > +{
> > + /* Not supported */
> > +}
>
> What about running gfar_configure_serdes again?
The intention here is to cause the 802.3z link to renegotiate...
>
> > +
> > +static void gfar_mac_link_down(struct phylink_config *config, unsigned int mode,
> > + phy_interface_t interface)
> > +{
> > + /* Not supported */
> > +}
> > +
>
> What about disabling RX_EN and TX_EN from MACCFG1?
>
> > +static void gfar_mac_link_up(struct phylink_config *config, unsigned int mode,
> > + phy_interface_t interface, struct phy_device *phy)
> > +{
> > + /* Not supported */
> > }
> >
>
> What about enabling RX_EN and TX_EN from MACCFG1?
Note that both of these functions must still allow the link to be
established if we are using in-band negotiation - but they are
expected to start/stop the transmission of packets.
> > @@ -149,8 +148,13 @@ extern const char gfar_driver_version[];
> > #define GFAR_SUPPORTED_GBIT SUPPORTED_1000baseT_Full
> >
> > /* TBI register addresses */
> > +#define MII_TBI_CR 0x00
> > #define MII_TBICON 0x11
> >
> > +/* TBI_CR register bit fields */
> > +#define TBI_CR_FULL_DUPLEX 0x0100
> > +#define TBI_CR_SPEED_1000_MASK 0x0040
> > +
>
> I think BIT() definitions are preferred, even if that means you have
> to convert existing code first.
If MII_TBI_CR is the BMCR of the PCS, how about using the definitions
that we already have in the kernel:
BMCR_SPEED1000 is TBI_CR_SPEED_1000_MASK
BMCR_FULLDPLX is TBI_CR_FULL_DUPLEX
?
--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 12.1Mbps down 622kbps up
According to speedtest.net: 11.9Mbps down 500kbps up
^ permalink raw reply
* [PATCH][next] mlxsw: spectrum_ptp: fix duplicated check on orig_egr_types
From: Colin King @ 2019-07-30 10:21 UTC (permalink / raw)
To: Petr Machata, Jiri Pirko, Ido Schimmel, David S . Miller, netdev
Cc: kernel-janitors, linux-kernel
From: Colin Ian King <colin.king@canonical.com>
Currently there is a duplicated check on orig_egr_types which is
redundant, I believe this is a typo and should actually be
orig_ing_types || orig_egr_types instead of the expression
orig_egr_types || orig_egr_types. Fix this.
Addresses-Coverity: ("Same on both sides")
Fixes: c6b36bdd04b5 ("mlxsw: spectrum_ptp: Increase parsing depth when PTP is enabled")
Signed-off-by: Colin Ian King <colin.king@canonical.com>
---
drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c
index 98c5ba3200bc..f02d74e55d95 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c
@@ -999,7 +999,7 @@ static int mlxsw_sp1_ptp_mtpppc_update(struct mlxsw_sp_port *mlxsw_sp_port,
}
}
- if ((ing_types || egr_types) && !(orig_egr_types || orig_egr_types)) {
+ if ((ing_types || egr_types) && !(orig_ing_types || orig_egr_types)) {
err = mlxsw_sp_nve_inc_parsing_depth_get(mlxsw_sp);
if (err) {
netdev_err(mlxsw_sp_port->dev, "Failed to increase parsing depth");
--
2.20.1
^ permalink raw reply related
* Re: [PATCH net-next 2/2] net: phy: broadcom: add 1000Base-X support for BCM54616S
From: Vladimir Oltean @ 2019-07-30 10:15 UTC (permalink / raw)
To: Tao Ren
Cc: Andrew Lunn, Florian Fainelli, Heiner Kallweit, David S . Miller,
Arun Parameswaran, Justin Chen, netdev, lkml, Andrew Jeffery,
openbmc@lists.ozlabs.org
In-Reply-To: <3987251b-9679-dfbe-6e15-f991c2893bac@fb.com>
On Tue, 30 Jul 2019 at 07:52, Tao Ren <taoren@fb.com> wrote:
>
> On 7/29/19 6:32 PM, Vladimir Oltean wrote:
> > Hi Tao,
> >
> > On Tue, 30 Jul 2019 at 03:31, Tao Ren <taoren@fb.com> wrote:
> >>
> >> Configure the BCM54616S for 1000Base-X mode when "brcm-phy-mode-1000bx"
> >> is set in device tree. This is needed when the PHY is used for fiber and
> >> backplane connections.
> >>
> >> The patch is inspired by commit cd9af3dac6d1 ("PHYLIB: Add 1000Base-X
> >> support for Broadcom bcm5482").
> >
> > As far as I can see, for the commit you referenced,
> > PHY_BCM_FLAGS_MODE_1000BX is referenced from nowhere in the entire
> > mainline kernel:
> > https://urldefense.proofpoint.com/v2/url?u=https-3A__elixir.bootlin.com_linux_latest_ident_PHY-5FBCM-5FFLAGS-5FMODE-5F1000BX&d=DwIBaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=iYElT7HC77pRZ3byVvW8ng&m=gy6Y-3Ylme-_GQcGF4fvOX10irgAT4xh253Weo0np38&s=KL__E2bvsmvUL-hBL9hUmOS5vyPQ92EMj6fEfByn8t8&e=
> > (it is supposed to be put by the MAC driver in phydev->dev_flags prior
> > to calling phy_connect). But I don't see the point to this - can't you
> > check for phydev->interface == PHY_INTERFACE_MODE_1000BASEX?
> > This has the advantage that no MAC driver will need to know that it's
> > talking to a Broadcom PHY. Additionally, no custom DT bindings are
> > needed.
> > Also, for backplane connections you probably want 1000Base-KX which
> > has its own AN/LT, not plain 1000Base-X.
>
> Thank you Vladimir for the quick review!
> Perhaps I misunderstood the purpose of phydev->interface, and I thought it was usually used to defined the interface between MAC and PHY. For example, if I need to pass both "rgmii-id" and "1000base-x" from MAC to PHY driver, what would be the preferred way?
>
Ohhhhhh, now I understand what you're trying to do, sorry, somehow I
was too tired and I thought of something totally unrelated.
Let me see if I can explain: you've got the INTF_SEL pin strapping
configured for something else (like RGMII to copper mode) and then
you're changing the operating mode at runtime through MDIO? Is this
intended to be for production code, or is it just some quick hack to
fix a bad board design?
I think what's supposed to happen (Heiner can comment) is that
genphy_config_init will automatically read the out-of-reset PHY
registers and figure out which link modes are supported. This includes
the 1000Base-X media type, *if* the PHY is strapped correctly.
But you are changing the strapping configuration too late (again, in
.config_init), so phylib doesn't pick up the new Base-X modes. What
happens if you do the switchover from the .probe callback of the
driver, instead of .config_init?
I think what got me confused was your "add support for 1000Base-X"
commit message. If I understand correctly, you're not adding support,
you're just forcing it.
Again, I don't think Linux has generic support for overwriting (or
even describing) the operating mode of a PHY, although maybe that's a
direction we would want to push the discussion towards. RGMII to
copper, RGMII to fiber, SGMII to copper, copper to fiber (media
converter), even RGMII to SGMII (RTL8211FS supports this) - lots of
modes, and this is only for gigabit PHYs...
> >> Signed-off-by: Tao Ren <taoren@fb.com>
> >> ---
> >> drivers/net/phy/broadcom.c | 58 +++++++++++++++++++++++++++++++++++---
> >> include/linux/brcmphy.h | 4 +--
> >> 2 files changed, 56 insertions(+), 6 deletions(-)
> >>
> >> diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
> >> index 2b4e41a9d35a..6c22ac3a844b 100644
> >> --- a/drivers/net/phy/broadcom.c
> >> +++ b/drivers/net/phy/broadcom.c
> >> @@ -383,9 +383,9 @@ static int bcm5482_config_init(struct phy_device *phydev)
> >> /*
> >> * Select 1000BASE-X register set (primary SerDes)
> >> */
> >> - reg = bcm_phy_read_shadow(phydev, BCM5482_SHD_MODE);
> >> - bcm_phy_write_shadow(phydev, BCM5482_SHD_MODE,
> >> - reg | BCM5482_SHD_MODE_1000BX);
> >> + reg = bcm_phy_read_shadow(phydev, BCM54XX_SHD_MODE);
> >> + bcm_phy_write_shadow(phydev, BCM54XX_SHD_MODE,
> >> + reg | BCM54XX_SHD_MODE_1000BX);
> >>
> >> /*
> >> * LED1=ACTIVITYLED, LED3=LINKSPD[2]
> >> @@ -451,6 +451,34 @@ static int bcm5481_config_aneg(struct phy_device *phydev)
> >> return ret;
> >> }
> >>
> >> +static int bcm54616s_config_init(struct phy_device *phydev)
> >> +{
> >> + int err, reg;
> >> + struct device_node *np = phydev->mdio.dev.of_node;
> >> +
> >> + err = bcm54xx_config_init(phydev);
> >> +
> >> + if (of_property_read_bool(np, "brcm-phy-mode-1000bx")) {
> >> + /* Select 1000BASE-X register set. */
> >> + reg = bcm_phy_read_shadow(phydev, BCM54XX_SHD_MODE);
> >> + bcm_phy_write_shadow(phydev, BCM54XX_SHD_MODE,
> >> + reg | BCM54XX_SHD_MODE_1000BX);
> >> +
> >> + /* Auto-negotiation doesn't seem to work quite right
> >> + * in this mode, so we disable it and force it to the
> >> + * right speed/duplex setting. Only 'link status'
> >> + * is important.
> >> + */
> >> + phydev->autoneg = AUTONEG_DISABLE;
> >> + phydev->speed = SPEED_1000;
> >> + phydev->duplex = DUPLEX_FULL;
> >> +
> >
> > 1000Base-X AN does not include speed negotiation, so hardcoding
> > SPEED_1000 is probably correct.
> > What is wrong with the AN of duplex settings?
>
> FULL_DUPLEX bit is set on my platform by default. Let me enable AN and test it out; will share you results tomorrow.
>
> >> + phydev->dev_flags |= PHY_BCM_FLAGS_MODE_1000BX;
> >> + }
> >> +
> >> + return err;
> >> +}
> >> +
> >> static int bcm54616s_config_aneg(struct phy_device *phydev)
> >> {
> >> int ret;
> >> @@ -464,6 +492,27 @@ static int bcm54616s_config_aneg(struct phy_device *phydev)
> >> return ret;
> >> }
> >>
> >> +static int bcm54616s_read_status(struct phy_device *phydev)
> >> +{
> >> + int ret;
> >> +
> >> + ret = genphy_read_status(phydev);
> >> + if (ret < 0)
> >> + return ret;
> >> +
> >> + if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX) {
> >> + /* Only link status matters for 1000Base-X mode, so force
> >> + * 1000 Mbit/s full-duplex status.
> >> + */
> >> + if (phydev->link) {
> >> + phydev->speed = SPEED_1000;
> >> + phydev->duplex = DUPLEX_FULL;
> >> + }
> >> + }
> >> +
> >> + return 0;
> >> +}
> >> +
> >> static int brcm_phy_setbits(struct phy_device *phydev, int reg, int set)
> >> {
> >> int val;
> >> @@ -651,8 +700,9 @@ static struct phy_driver broadcom_drivers[] = {
> >> .phy_id_mask = 0xfffffff0,
> >> .name = "Broadcom BCM54616S",
> >> .features = PHY_GBIT_FEATURES,
> >> - .config_init = bcm54xx_config_init,
> >> + .config_init = bcm54616s_config_init,
> >> .config_aneg = bcm54616s_config_aneg,
> >> + .read_status = bcm54616s_read_status,
> >> .ack_interrupt = bcm_phy_ack_intr,
> >> .config_intr = bcm_phy_config_intr,
> >> }, {
> >> diff --git a/include/linux/brcmphy.h b/include/linux/brcmphy.h
> >> index 6db2d9a6e503..82030155558c 100644
> >> --- a/include/linux/brcmphy.h
> >> +++ b/include/linux/brcmphy.h
> >> @@ -200,8 +200,8 @@
> >> #define BCM5482_SHD_SSD 0x14 /* 10100: Secondary SerDes control */
> >> #define BCM5482_SHD_SSD_LEDM 0x0008 /* SSD LED Mode enable */
> >> #define BCM5482_SHD_SSD_EN 0x0001 /* SSD enable */
> >> -#define BCM5482_SHD_MODE 0x1f /* 11111: Mode Control Register */
> >> -#define BCM5482_SHD_MODE_1000BX 0x0001 /* Enable 1000BASE-X registers */
> >> +#define BCM54XX_SHD_MODE 0x1f /* 11111: Mode Control Register */
> >> +#define BCM54XX_SHD_MODE_1000BX 0x0001 /* Enable 1000BASE-X registers */
> >
> > These registers are also present on my BCM5464, probably safe to
> > assume they're generic for the entire family.
> > So if you make the registers definitions common, you can probably make
> > the 1000Base-X configuration common as well.
>
> If I understand correctly, your recommendation is to add a common function (such as "bcm54xx_config_1000bx") so it can be used by other BCM chips? Sure, I will take care of it.
>
>
> Thanks,
>
> Tao
Regards,
-Vladimir
^ permalink raw reply
* [PATCH 1/2] net: dsa: mv88e6xxx: add support to setup led-control register through device-tree
From: Hubert Feurstein @ 2019-07-30 10:14 UTC (permalink / raw)
To: netdev, linux-kernel
Cc: Hubert Feurstein, Andrew Lunn, Vivien Didelot, Florian Fainelli,
David S. Miller
So it is possible to change the default behaviour of the switch LEDs.
Signed-off-by: Hubert Feurstein <h.feurstein@gmail.com>
---
drivers/net/dsa/mv88e6xxx/chip.c | 52 ++++++++++++++++++++++++++++++++
drivers/net/dsa/mv88e6xxx/chip.h | 2 ++
drivers/net/dsa/mv88e6xxx/port.c | 13 ++++++++
drivers/net/dsa/mv88e6xxx/port.h | 10 ++++++
4 files changed, 77 insertions(+)
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 85638b868d8e..e5a11454e1e0 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -1985,6 +1985,52 @@ static int mv88e6xxx_switch_reset(struct mv88e6xxx_chip *chip)
return mv88e6xxx_software_reset(chip);
}
+static void mv88e6xxx_led_control_init(struct mv88e6xxx_chip *chip,
+ const struct device_node *np)
+{
+ struct device_node *ports, *port;
+ struct mv88e6xxx_port *chip_port;
+ u32 led_control, reg;
+ int err;
+
+ if (!np)
+ return;
+
+ /* Read LED Control register value from device-tree */
+ ports = of_get_child_by_name(np, "ports");
+ if (!ports)
+ return;
+
+ for_each_available_child_of_node(ports, port) {
+ err = of_property_read_u32(port, "reg", ®);
+ if (err || reg >= ARRAY_SIZE(chip->ports))
+ break;
+
+ err = of_property_read_u32(port, "marvell,led-control",
+ &led_control);
+ if (!err) {
+ chip_port = &chip->ports[reg];
+ chip_port->led_control = led_control |
+ MV88E6XXX_LED_CONTROL_VALID;
+ dev_dbg(chip->dev, "LED control value for port%d = 0x%02x\n",
+ reg, led_control);
+ }
+ }
+
+ of_node_put(ports);
+}
+
+static int mv88e6xxx_led_control_setup(struct mv88e6xxx_chip *chip, int port)
+{
+ u16 led_control = chip->ports[port].led_control;
+
+ if ((led_control & MV88E6XXX_LED_CONTROL_VALID) == 0)
+ return 0;
+
+ led_control &= ~MV88E6XXX_LED_CONTROL_VALID;
+ return mv88e6xxx_port_set_led_control(chip, port, led_control);
+}
+
static int mv88e6xxx_set_port_mode(struct mv88e6xxx_chip *chip, int port,
enum mv88e6xxx_frame_mode frame,
enum mv88e6xxx_egress_mode egress, u16 etype)
@@ -2120,6 +2166,11 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
chip->ports[port].chip = chip;
chip->ports[port].port = port;
+ /* Setup LED Control before link-up or link-unforce */
+ err = mv88e6xxx_led_control_setup(chip, port);
+ if (err)
+ return err;
+
/* MAC Forcing register: don't force link, speed, duplex or flow control
* state to any particular values on physical ports, but force the CPU
* port and all DSA ports to their maximum bandwidth and full duplex.
@@ -4851,6 +4902,7 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev)
goto out;
mv88e6xxx_phy_init(chip);
+ mv88e6xxx_led_control_init(chip, np);
if (chip->info->ops->get_eeprom) {
if (np)
diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
index 64872251e479..1bb775855d62 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.h
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
@@ -24,6 +24,7 @@
#define MV88E6XXX_MAX_PVT_PORTS 16
#define MV88E6XXX_MAX_GPIO 16
+#define MV88E6XXX_LED_CONTROL_VALID 0x8000
enum mv88e6xxx_egress_mode {
MV88E6XXX_EGRESS_MODE_UNMODIFIED,
@@ -194,6 +195,7 @@ struct mv88e6xxx_port {
u64 vtu_member_violation;
u64 vtu_miss_violation;
u8 cmode;
+ u16 led_control;
int serdes_irq;
};
diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c
index 04309ef0a1cc..111bb686b764 100644
--- a/drivers/net/dsa/mv88e6xxx/port.c
+++ b/drivers/net/dsa/mv88e6xxx/port.c
@@ -1183,6 +1183,19 @@ int mv88e6351_port_set_ether_type(struct mv88e6xxx_chip *chip, int port,
return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_ETH_TYPE, etype);
}
+/* Offset 0x16: LED Control Register */
+
+int mv88e6xxx_port_set_led_control(struct mv88e6xxx_chip *chip, int port,
+ u16 led_control)
+{
+ led_control &= MV88E6XXX_PORT_LED_CONTROL_DATA_MASK;
+ led_control |= MV88E6XXX_PORT_LED_CONTROL_POINTER_CONTROL_LED01
+ | MV88E6XXX_PORT_LED_CONTROL_UPDATE;
+
+ return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_LED_CONTROL,
+ led_control);
+}
+
/* Offset 0x18: Port IEEE Priority Remapping Registers [0-3]
* Offset 0x19: Port IEEE Priority Remapping Registers [4-7]
*/
diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h
index 141df2988cd1..5aacbccf81e3 100644
--- a/drivers/net/dsa/mv88e6xxx/port.h
+++ b/drivers/net/dsa/mv88e6xxx/port.h
@@ -239,6 +239,14 @@
/* Offset 0x13: OutFiltered Counter */
#define MV88E6XXX_PORT_OUT_FILTERED 0x13
+/* Offset 0x16: LED Control Register */
+#define MV88E6XXX_PORT_LED_CONTROL 0x16
+#define MV88E6XXX_PORT_LED_CONTROL_DATA_MASK 0x07ff
+#define MV88E6XXX_PORT_LED_CONTROL_UPDATE 0x8000
+#define MV88E6XXX_PORT_LED_CONTROL_POINTER_CONTROL_LED01 0x0000
+#define MV88E6XXX_PORT_LED_CONTROL_POINTER_STRECH_BLINK_RATE 0x6000
+#define MV88E6XXX_PORT_LED_CONTROL_POINTER_CONTROL_SPECIAL 0x7000
+
/* Offset 0x18: IEEE Priority Mapping Table */
#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE 0x18
#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_UPDATE 0x8000
@@ -323,6 +331,8 @@ int mv88e6352_port_set_egress_floods(struct mv88e6xxx_chip *chip, int port,
bool unicast, bool multicast);
int mv88e6351_port_set_ether_type(struct mv88e6xxx_chip *chip, int port,
u16 etype);
+int mv88e6xxx_port_set_led_control(struct mv88e6xxx_chip *chip, int port,
+ u16 led_control);
int mv88e6xxx_port_set_message_port(struct mv88e6xxx_chip *chip, int port,
bool message_port);
int mv88e6165_port_set_jumbo_size(struct mv88e6xxx_chip *chip, int port,
--
2.22.0
^ permalink raw reply related
* [PATCH 2/2] dt-bindings: net: dsa: marvell: add property "marvell,led-control"
From: Hubert Feurstein @ 2019-07-30 10:14 UTC (permalink / raw)
To: netdev, linux-kernel
Cc: Hubert Feurstein, Andrew Lunn, Vivien Didelot, Florian Fainelli,
David S. Miller
In-Reply-To: <20190730101451.845-1-h.feurstein@gmail.com>
With this property it is possible to change the default behaviour of
the switch LEDs.
Signed-off-by: Hubert Feurstein <h.feurstein@gmail.com>
---
Documentation/devicetree/bindings/net/dsa/marvell.txt | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/Documentation/devicetree/bindings/net/dsa/marvell.txt b/Documentation/devicetree/bindings/net/dsa/marvell.txt
index 30c11fea491b..5e094e37c76d 100644
--- a/Documentation/devicetree/bindings/net/dsa/marvell.txt
+++ b/Documentation/devicetree/bindings/net/dsa/marvell.txt
@@ -46,6 +46,16 @@ Optional properties:
- mdio? : Container of PHYs and devices on the external MDIO
bus. The node must contains a compatible string of
"marvell,mv88e6xxx-mdio-external"
+- marvell,led-control : The register value for the LED control register (
+ Control for LED 0 & 1). This property can be defined
+ per port. Example:
+ ports {
+ port@0 {
+ [...]
+ marvell,led-control = <0x11>
+ };
+ [...]
+ }
Example:
--
2.22.0
^ permalink raw reply related
* [PATCH] net: dsa: mv88e6xxx: use link-down-define instead of plain value
From: Hubert Feurstein @ 2019-07-30 10:11 UTC (permalink / raw)
To: netdev, linux-kernel
Cc: Hubert Feurstein, Andrew Lunn, Vivien Didelot, Florian Fainelli,
David S. Miller
Using the define here makes the code more expressive.
Signed-off-by: Hubert Feurstein <h.feurstein@gmail.com>
---
drivers/net/dsa/mv88e6xxx/chip.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 58e298cc90e0..85638b868d8e 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -430,7 +430,7 @@ int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port, int link,
return 0;
/* Port's MAC control must not be changed unless the link is down */
- err = chip->info->ops->port_set_link(chip, port, 0);
+ err = chip->info->ops->port_set_link(chip, port, LINK_FORCED_DOWN);
if (err)
return err;
--
2.22.0
^ permalink raw reply related
* [PATCH] net: dsa: mv88e6xxx: extend PTP gettime function to read system clock
From: Hubert Feurstein @ 2019-07-30 10:10 UTC (permalink / raw)
To: netdev, linux-kernel
Cc: Hubert Feurstein, Andrew Lunn, Vivien Didelot, Florian Fainelli,
David S. Miller
This adds support for the PTP_SYS_OFFSET_EXTENDED ioctl.
Signed-off-by: Hubert Feurstein <h.feurstein@gmail.com>
---
drivers/net/dsa/mv88e6xxx/ptp.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/drivers/net/dsa/mv88e6xxx/ptp.c b/drivers/net/dsa/mv88e6xxx/ptp.c
index 51cdf4712517..1ff983376f95 100644
--- a/drivers/net/dsa/mv88e6xxx/ptp.c
+++ b/drivers/net/dsa/mv88e6xxx/ptp.c
@@ -230,14 +230,17 @@ static int mv88e6xxx_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
return 0;
}
-static int mv88e6xxx_ptp_gettime(struct ptp_clock_info *ptp,
- struct timespec64 *ts)
+static int mv88e6xxx_ptp_gettimex(struct ptp_clock_info *ptp,
+ struct timespec64 *ts,
+ struct ptp_system_timestamp *sts)
{
struct mv88e6xxx_chip *chip = ptp_to_chip(ptp);
u64 ns;
mv88e6xxx_reg_lock(chip);
+ ptp_read_system_prets(sts);
ns = timecounter_read(&chip->tstamp_tc);
+ ptp_read_system_postts(sts);
mv88e6xxx_reg_unlock(chip);
*ts = ns_to_timespec64(ns);
@@ -386,7 +389,7 @@ static void mv88e6xxx_ptp_overflow_check(struct work_struct *work)
struct mv88e6xxx_chip *chip = dw_overflow_to_chip(dw);
struct timespec64 ts;
- mv88e6xxx_ptp_gettime(&chip->ptp_clock_info, &ts);
+ mv88e6xxx_ptp_gettimex(&chip->ptp_clock_info, &ts, NULL);
schedule_delayed_work(&chip->overflow_work,
MV88E6XXX_TAI_OVERFLOW_PERIOD);
@@ -444,7 +447,7 @@ int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip)
chip->ptp_clock_info.max_adj = MV88E6XXX_MAX_ADJ_PPB;
chip->ptp_clock_info.adjfine = mv88e6xxx_ptp_adjfine;
chip->ptp_clock_info.adjtime = mv88e6xxx_ptp_adjtime;
- chip->ptp_clock_info.gettime64 = mv88e6xxx_ptp_gettime;
+ chip->ptp_clock_info.gettimex64 = mv88e6xxx_ptp_gettimex;
chip->ptp_clock_info.settime64 = mv88e6xxx_ptp_settime;
chip->ptp_clock_info.enable = ptp_ops->ptp_enable;
chip->ptp_clock_info.verify = ptp_ops->ptp_verify;
--
2.22.0
^ permalink raw reply related
* [PATCH 1/4] net: dsa: mv88e6xxx: add support for MV88E6220
From: Hubert Feurstein @ 2019-07-30 10:04 UTC (permalink / raw)
To: netdev, linux-kernel
Cc: Hubert Feurstein, Andrew Lunn, Vivien Didelot, Florian Fainelli,
David S. Miller, Rasmus Villemoes
In-Reply-To: <20190730100429.32479-1-h.feurstein@gmail.com>
The MV88E6220 is almost the same as MV88E6250 except that the ports 2-4 are
not routed to pins. So the usable ports are 0, 1, 5 and 6.
Signed-off-by: Hubert Feurstein <h.feurstein@gmail.com>
---
drivers/net/dsa/mv88e6xxx/chip.c | 25 +++++++++++++++++++++++++
drivers/net/dsa/mv88e6xxx/chip.h | 3 ++-
drivers/net/dsa/mv88e6xxx/port.h | 1 +
3 files changed, 28 insertions(+), 1 deletion(-)
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 6b17cd961d06..c4982ced908e 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -4283,6 +4283,31 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.ops = &mv88e6240_ops,
},
+ [MV88E6220] = {
+ .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6220,
+ .family = MV88E6XXX_FAMILY_6250,
+ .name = "Marvell 88E6220",
+ .num_databases = 64,
+
+ /* Ports 2-4 are not routed to pins
+ * => usable ports 0, 1, 5, 6
+ */
+ .num_ports = 7,
+ .num_internal_phys = 2,
+ .max_vid = 4095,
+ .port_base_addr = 0x08,
+ .phy_base_addr = 0x00,
+ .global1_addr = 0x0f,
+ .global2_addr = 0x07,
+ .age_time_coeff = 15000,
+ .g1_irqs = 9,
+ .g2_irqs = 10,
+ .atu_move_port_mask = 0xf,
+ .dual_chip = true,
+ .tag_protocol = DSA_TAG_PROTO_DSA,
+ .ops = &mv88e6250_ops,
+ },
+
[MV88E6250] = {
.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6250,
.family = MV88E6XXX_FAMILY_6250,
diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
index 4646e46d47f2..6eb13f269366 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.h
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
@@ -58,6 +58,7 @@ enum mv88e6xxx_model {
MV88E6190X,
MV88E6191,
MV88E6240,
+ MV88E6220,
MV88E6250,
MV88E6290,
MV88E6320,
@@ -77,7 +78,7 @@ enum mv88e6xxx_family {
MV88E6XXX_FAMILY_6097, /* 6046 6085 6096 6097 */
MV88E6XXX_FAMILY_6165, /* 6123 6161 6165 */
MV88E6XXX_FAMILY_6185, /* 6108 6121 6122 6131 6152 6155 6182 6185 */
- MV88E6XXX_FAMILY_6250, /* 6250 */
+ MV88E6XXX_FAMILY_6250, /* 6220, 6250 */
MV88E6XXX_FAMILY_6320, /* 6320 6321 */
MV88E6XXX_FAMILY_6341, /* 6141 6341 */
MV88E6XXX_FAMILY_6351, /* 6171 6175 6350 6351 */
diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h
index 8d5a6cd6fb19..141df2988cd1 100644
--- a/drivers/net/dsa/mv88e6xxx/port.h
+++ b/drivers/net/dsa/mv88e6xxx/port.h
@@ -118,6 +118,7 @@
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6191 0x1910
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6185 0x1a70
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6240 0x2400
+#define MV88E6XXX_PORT_SWITCH_ID_PROD_6220 0x2200
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6250 0x2500
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6290 0x2900
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6321 0x3100
--
2.22.0
^ permalink raw reply related
* [PATCH 2/4] dt-bindings: net: dsa: marvell: add 6220 model to the 6250 family
From: Hubert Feurstein @ 2019-07-30 10:04 UTC (permalink / raw)
To: netdev, linux-kernel
Cc: Hubert Feurstein, Andrew Lunn, Vivien Didelot, Florian Fainelli,
David S. Miller, Rasmus Villemoes
In-Reply-To: <20190730100429.32479-1-h.feurstein@gmail.com>
The MV88E6220 is part of the MV88E6250 family.
Signed-off-by: Hubert Feurstein <h.feurstein@gmail.com>
---
Documentation/devicetree/bindings/net/dsa/marvell.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/net/dsa/marvell.txt b/Documentation/devicetree/bindings/net/dsa/marvell.txt
index 6f9538974bb9..30c11fea491b 100644
--- a/Documentation/devicetree/bindings/net/dsa/marvell.txt
+++ b/Documentation/devicetree/bindings/net/dsa/marvell.txt
@@ -22,7 +22,7 @@ which is at a different MDIO base address in different switch families.
- "marvell,mv88e6190" : Switch has base address 0x00. Use with models:
6190, 6190X, 6191, 6290, 6390, 6390X
- "marvell,mv88e6250" : Switch has base address 0x08 or 0x18. Use with model:
- 6250
+ 6220, 6250
Required properties:
- compatible : Should be one of "marvell,mv88e6085",
--
2.22.0
^ permalink raw reply related
* [PATCH 3/4] net: dsa: mv88e6xxx: setup message port is not supported in the 6250 family
From: Hubert Feurstein @ 2019-07-30 10:04 UTC (permalink / raw)
To: netdev, linux-kernel
Cc: Hubert Feurstein, Andrew Lunn, Vivien Didelot, Florian Fainelli,
David S. Miller, Rasmus Villemoes
In-Reply-To: <20190730100429.32479-1-h.feurstein@gmail.com>
The MV88E6250 family doesn't support the MV88E6XXX_PORT_CTL1_MESSAGE_PORT
bit.
Signed-off-by: Hubert Feurstein <h.feurstein@gmail.com>
---
drivers/net/dsa/mv88e6xxx/chip.c | 34 +++++++++++++++++++++++++++++---
drivers/net/dsa/mv88e6xxx/chip.h | 1 +
2 files changed, 32 insertions(+), 3 deletions(-)
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index c4982ced908e..c2fb4ea66434 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -2252,9 +2252,11 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
return err;
}
- err = mv88e6xxx_setup_message_port(chip, port);
- if (err)
- return err;
+ if (chip->info->ops->port_setup_message_port) {
+ err = chip->info->ops->port_setup_message_port(chip, port);
+ if (err)
+ return err;
+ }
/* Port based VLAN map: give each port the same default address
* database, and allow bidirectional communication between the
@@ -2797,6 +2799,7 @@ static const struct mv88e6xxx_ops mv88e6085_ops = {
.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
.port_link_state = mv88e6352_port_link_state,
.port_get_cmode = mv88e6185_port_get_cmode,
+ .port_setup_message_port = mv88e6xxx_setup_message_port,
.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
@@ -2831,6 +2834,7 @@ static const struct mv88e6xxx_ops mv88e6095_ops = {
.port_set_upstream_port = mv88e6095_port_set_upstream_port,
.port_link_state = mv88e6185_port_link_state,
.port_get_cmode = mv88e6185_port_get_cmode,
+ .port_setup_message_port = mv88e6xxx_setup_message_port,
.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
@@ -2867,6 +2871,7 @@ static const struct mv88e6xxx_ops mv88e6097_ops = {
.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
.port_link_state = mv88e6352_port_link_state,
.port_get_cmode = mv88e6185_port_get_cmode,
+ .port_setup_message_port = mv88e6xxx_setup_message_port,
.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
@@ -2901,6 +2906,7 @@ static const struct mv88e6xxx_ops mv88e6123_ops = {
.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
.port_link_state = mv88e6352_port_link_state,
.port_get_cmode = mv88e6185_port_get_cmode,
+ .port_setup_message_port = mv88e6xxx_setup_message_port,
.stats_snapshot = mv88e6320_g1_stats_snapshot,
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
@@ -2938,6 +2944,7 @@ static const struct mv88e6xxx_ops mv88e6131_ops = {
.port_set_pause = mv88e6185_port_set_pause,
.port_link_state = mv88e6352_port_link_state,
.port_get_cmode = mv88e6185_port_get_cmode,
+ .port_setup_message_port = mv88e6xxx_setup_message_port,
.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
@@ -2982,6 +2989,7 @@ static const struct mv88e6xxx_ops mv88e6141_ops = {
.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
.port_link_state = mv88e6352_port_link_state,
.port_get_cmode = mv88e6352_port_get_cmode,
+ .port_setup_message_port = mv88e6xxx_setup_message_port,
.stats_snapshot = mv88e6390_g1_stats_snapshot,
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6320_stats_get_sset_count,
@@ -3022,6 +3030,7 @@ static const struct mv88e6xxx_ops mv88e6161_ops = {
.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
.port_link_state = mv88e6352_port_link_state,
.port_get_cmode = mv88e6185_port_get_cmode,
+ .port_setup_message_port = mv88e6xxx_setup_message_port,
.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
@@ -3055,6 +3064,7 @@ static const struct mv88e6xxx_ops mv88e6165_ops = {
.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
.port_link_state = mv88e6352_port_link_state,
.port_get_cmode = mv88e6185_port_get_cmode,
+ .port_setup_message_port = mv88e6xxx_setup_message_port,
.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
@@ -3096,6 +3106,7 @@ static const struct mv88e6xxx_ops mv88e6171_ops = {
.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
.port_link_state = mv88e6352_port_link_state,
.port_get_cmode = mv88e6352_port_get_cmode,
+ .port_setup_message_port = mv88e6xxx_setup_message_port,
.stats_snapshot = mv88e6320_g1_stats_snapshot,
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
@@ -3137,6 +3148,7 @@ static const struct mv88e6xxx_ops mv88e6172_ops = {
.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
.port_link_state = mv88e6352_port_link_state,
.port_get_cmode = mv88e6352_port_get_cmode,
+ .port_setup_message_port = mv88e6xxx_setup_message_port,
.stats_snapshot = mv88e6320_g1_stats_snapshot,
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
@@ -3179,6 +3191,7 @@ static const struct mv88e6xxx_ops mv88e6175_ops = {
.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
.port_link_state = mv88e6352_port_link_state,
.port_get_cmode = mv88e6352_port_get_cmode,
+ .port_setup_message_port = mv88e6xxx_setup_message_port,
.stats_snapshot = mv88e6320_g1_stats_snapshot,
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
@@ -3220,6 +3233,7 @@ static const struct mv88e6xxx_ops mv88e6176_ops = {
.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
.port_link_state = mv88e6352_port_link_state,
.port_get_cmode = mv88e6352_port_get_cmode,
+ .port_setup_message_port = mv88e6xxx_setup_message_port,
.stats_snapshot = mv88e6320_g1_stats_snapshot,
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
@@ -3258,6 +3272,7 @@ static const struct mv88e6xxx_ops mv88e6185_ops = {
.port_set_pause = mv88e6185_port_set_pause,
.port_link_state = mv88e6185_port_link_state,
.port_get_cmode = mv88e6185_port_get_cmode,
+ .port_setup_message_port = mv88e6xxx_setup_message_port,
.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
@@ -3300,6 +3315,7 @@ static const struct mv88e6xxx_ops mv88e6190_ops = {
.port_link_state = mv88e6352_port_link_state,
.port_get_cmode = mv88e6352_port_get_cmode,
.port_set_cmode = mv88e6390_port_set_cmode,
+ .port_setup_message_port = mv88e6xxx_setup_message_port,
.stats_snapshot = mv88e6390_g1_stats_snapshot,
.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6320_stats_get_sset_count,
@@ -3345,6 +3361,7 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = {
.port_link_state = mv88e6352_port_link_state,
.port_get_cmode = mv88e6352_port_get_cmode,
.port_set_cmode = mv88e6390x_port_set_cmode,
+ .port_setup_message_port = mv88e6xxx_setup_message_port,
.stats_snapshot = mv88e6390_g1_stats_snapshot,
.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6320_stats_get_sset_count,
@@ -3390,6 +3407,7 @@ static const struct mv88e6xxx_ops mv88e6191_ops = {
.port_link_state = mv88e6352_port_link_state,
.port_get_cmode = mv88e6352_port_get_cmode,
.port_set_cmode = mv88e6390_port_set_cmode,
+ .port_setup_message_port = mv88e6xxx_setup_message_port,
.stats_snapshot = mv88e6390_g1_stats_snapshot,
.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6320_stats_get_sset_count,
@@ -3437,6 +3455,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
.port_link_state = mv88e6352_port_link_state,
.port_get_cmode = mv88e6352_port_get_cmode,
+ .port_setup_message_port = mv88e6xxx_setup_message_port,
.stats_snapshot = mv88e6320_g1_stats_snapshot,
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
@@ -3522,6 +3541,7 @@ static const struct mv88e6xxx_ops mv88e6290_ops = {
.port_link_state = mv88e6352_port_link_state,
.port_get_cmode = mv88e6352_port_get_cmode,
.port_set_cmode = mv88e6390_port_set_cmode,
+ .port_setup_message_port = mv88e6xxx_setup_message_port,
.stats_snapshot = mv88e6390_g1_stats_snapshot,
.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6320_stats_get_sset_count,
@@ -3569,6 +3589,7 @@ static const struct mv88e6xxx_ops mv88e6320_ops = {
.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
.port_link_state = mv88e6352_port_link_state,
.port_get_cmode = mv88e6352_port_get_cmode,
+ .port_setup_message_port = mv88e6xxx_setup_message_port,
.stats_snapshot = mv88e6320_g1_stats_snapshot,
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6320_stats_get_sset_count,
@@ -3612,6 +3633,7 @@ static const struct mv88e6xxx_ops mv88e6321_ops = {
.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
.port_link_state = mv88e6352_port_link_state,
.port_get_cmode = mv88e6352_port_get_cmode,
+ .port_setup_message_port = mv88e6xxx_setup_message_port,
.stats_snapshot = mv88e6320_g1_stats_snapshot,
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6320_stats_get_sset_count,
@@ -3655,6 +3677,7 @@ static const struct mv88e6xxx_ops mv88e6341_ops = {
.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
.port_link_state = mv88e6352_port_link_state,
.port_get_cmode = mv88e6352_port_get_cmode,
+ .port_setup_message_port = mv88e6xxx_setup_message_port,
.stats_snapshot = mv88e6390_g1_stats_snapshot,
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6320_stats_get_sset_count,
@@ -3698,6 +3721,7 @@ static const struct mv88e6xxx_ops mv88e6350_ops = {
.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
.port_link_state = mv88e6352_port_link_state,
.port_get_cmode = mv88e6352_port_get_cmode,
+ .port_setup_message_port = mv88e6xxx_setup_message_port,
.stats_snapshot = mv88e6320_g1_stats_snapshot,
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
@@ -3737,6 +3761,7 @@ static const struct mv88e6xxx_ops mv88e6351_ops = {
.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
.port_link_state = mv88e6352_port_link_state,
.port_get_cmode = mv88e6352_port_get_cmode,
+ .port_setup_message_port = mv88e6xxx_setup_message_port,
.stats_snapshot = mv88e6320_g1_stats_snapshot,
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
@@ -3780,6 +3805,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = {
.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
.port_link_state = mv88e6352_port_link_state,
.port_get_cmode = mv88e6352_port_get_cmode,
+ .port_setup_message_port = mv88e6xxx_setup_message_port,
.stats_snapshot = mv88e6320_g1_stats_snapshot,
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
@@ -3832,6 +3858,7 @@ static const struct mv88e6xxx_ops mv88e6390_ops = {
.port_link_state = mv88e6352_port_link_state,
.port_get_cmode = mv88e6352_port_get_cmode,
.port_set_cmode = mv88e6390_port_set_cmode,
+ .port_setup_message_port = mv88e6xxx_setup_message_port,
.stats_snapshot = mv88e6390_g1_stats_snapshot,
.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6320_stats_get_sset_count,
@@ -3881,6 +3908,7 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = {
.port_link_state = mv88e6352_port_link_state,
.port_get_cmode = mv88e6352_port_get_cmode,
.port_set_cmode = mv88e6390x_port_set_cmode,
+ .port_setup_message_port = mv88e6xxx_setup_message_port,
.stats_snapshot = mv88e6390_g1_stats_snapshot,
.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6320_stats_get_sset_count,
diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
index 6eb13f269366..720cace3db4e 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.h
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
@@ -390,6 +390,7 @@ struct mv88e6xxx_ops {
u8 out);
int (*port_disable_learn_limit)(struct mv88e6xxx_chip *chip, int port);
int (*port_disable_pri_override)(struct mv88e6xxx_chip *chip, int port);
+ int (*port_setup_message_port)(struct mv88e6xxx_chip *chip, int port);
/* CMODE control what PHY mode the MAC will use, eg. SGMII, RGMII, etc.
* Some chips allow this to be configured on specific ports.
--
2.22.0
^ permalink raw reply related
* [PATCH 4/4] net: dsa: mv88e6xxx: add PTP support for MV88E6250 family
From: Hubert Feurstein @ 2019-07-30 10:04 UTC (permalink / raw)
To: netdev, linux-kernel
Cc: Hubert Feurstein, Andrew Lunn, Vivien Didelot, Florian Fainelli,
David S. Miller, Rasmus Villemoes
In-Reply-To: <20190730100429.32479-1-h.feurstein@gmail.com>
This adds PTP support for the MV88E6250 family.
Signed-off-by: Hubert Feurstein <h.feurstein@gmail.com>
---
drivers/net/dsa/mv88e6xxx/chip.c | 4 ++
drivers/net/dsa/mv88e6xxx/chip.h | 4 ++
drivers/net/dsa/mv88e6xxx/ptp.c | 73 ++++++++++++++++++++++----------
3 files changed, 59 insertions(+), 22 deletions(-)
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index c2fb4ea66434..58e298cc90e0 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -3514,6 +3514,8 @@ static const struct mv88e6xxx_ops mv88e6250_ops = {
.reset = mv88e6250_g1_reset,
.vtu_getnext = mv88e6250_g1_vtu_getnext,
.vtu_loadpurge = mv88e6250_g1_vtu_loadpurge,
+ .avb_ops = &mv88e6352_avb_ops,
+ .ptp_ops = &mv88e6352_ptp_ops,
.phylink_validate = mv88e6065_phylink_validate,
};
@@ -4333,6 +4335,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.atu_move_port_mask = 0xf,
.dual_chip = true,
.tag_protocol = DSA_TAG_PROTO_DSA,
+ .ptp_support = true,
.ops = &mv88e6250_ops,
},
@@ -4354,6 +4357,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.atu_move_port_mask = 0xf,
.dual_chip = true,
.tag_protocol = DSA_TAG_PROTO_DSA,
+ .ptp_support = true,
.ops = &mv88e6250_ops,
},
diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
index 720cace3db4e..64872251e479 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.h
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
@@ -273,6 +273,10 @@ struct mv88e6xxx_chip {
u16 trig_config;
u16 evcap_config;
u16 enable_count;
+ u32 ptp_cc_shift;
+ u32 ptp_cc_mult;
+ u32 ptp_cc_mult_num;
+ u32 ptp_cc_mult_dem;
/* Per-port timestamping resources. */
struct mv88e6xxx_port_hwtstamp port_hwtstamp[DSA_MAX_PORTS];
diff --git a/drivers/net/dsa/mv88e6xxx/ptp.c b/drivers/net/dsa/mv88e6xxx/ptp.c
index 768d256f7c9f..51cdf4712517 100644
--- a/drivers/net/dsa/mv88e6xxx/ptp.c
+++ b/drivers/net/dsa/mv88e6xxx/ptp.c
@@ -15,11 +15,38 @@
#include "hwtstamp.h"
#include "ptp.h"
-/* Raw timestamps are in units of 8-ns clock periods. */
-#define CC_SHIFT 28
-#define CC_MULT (8 << CC_SHIFT)
-#define CC_MULT_NUM (1 << 9)
-#define CC_MULT_DEM 15625ULL
+/* The adjfine API clamps ppb between [-32,768,000, 32,768,000], and
+ * therefore scaled_ppm between [-2,147,483,648, 2,147,483,647].
+ * Set the maximum supported ppb to a round value smaller than the maximum.
+ *
+ * Percentually speaking, this is a +/- 0.032x adjustment of the
+ * free-running counter (0.968x to 1.032x).
+ */
+#define MV88E6XXX_MAX_ADJ_PPB 32000000
+
+/* Family MV88E6250:
+ * Raw timestamps are in units of 10-ns clock periods.
+ *
+ * clkadj = scaled_ppm * 10*2^28 / (10^6 * 2^16)
+ * simplifies to
+ * clkadj = scaled_ppm * 2^7 / 5^5
+ */
+#define MV88E6250_CC_SHIFT 28
+#define MV88E6250_CC_MULT (10 << MV88E6250_CC_SHIFT)
+#define MV88E6250_CC_MULT_NUM (1 << 7)
+#define MV88E6250_CC_MULT_DEM 3125ULL
+
+/* Other families:
+ * Raw timestamps are in units of 8-ns clock periods.
+ *
+ * clkadj = scaled_ppm * 8*2^28 / (10^6 * 2^16)
+ * simplifies to
+ * clkadj = scaled_ppm * 2^9 / 5^6
+ */
+#define MV88E6XXX_CC_SHIFT 28
+#define MV88E6XXX_CC_MULT (8 << MV88E6XXX_CC_SHIFT)
+#define MV88E6XXX_CC_MULT_NUM (1 << 9)
+#define MV88E6XXX_CC_MULT_DEM 15625ULL
#define TAI_EVENT_WORK_INTERVAL msecs_to_jiffies(100)
@@ -179,24 +206,14 @@ static void mv88e6352_tai_event_work(struct work_struct *ugly)
static int mv88e6xxx_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
{
struct mv88e6xxx_chip *chip = ptp_to_chip(ptp);
- int neg_adj = 0;
- u32 diff, mult;
- u64 adj;
+ s64 adj;
- if (scaled_ppm < 0) {
- neg_adj = 1;
- scaled_ppm = -scaled_ppm;
- }
- mult = CC_MULT;
- adj = CC_MULT_NUM;
- adj *= scaled_ppm;
- diff = div_u64(adj, CC_MULT_DEM);
+ adj = (s64)scaled_ppm * chip->ptp_cc_mult_num;
+ adj = div_s64(adj, chip->ptp_cc_mult_dem);
mv88e6xxx_reg_lock(chip);
-
timecounter_read(&chip->tstamp_tc);
- chip->tstamp_cc.mult = neg_adj ? mult - diff : mult + diff;
-
+ chip->tstamp_cc.mult = chip->ptp_cc_mult + adj;
mv88e6xxx_reg_unlock(chip);
return 0;
@@ -380,12 +397,24 @@ int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip)
const struct mv88e6xxx_ptp_ops *ptp_ops = chip->info->ops->ptp_ops;
int i;
+ if (chip->info->family == MV88E6XXX_FAMILY_6250) {
+ chip->ptp_cc_shift = MV88E6250_CC_SHIFT;
+ chip->ptp_cc_mult = MV88E6250_CC_MULT;
+ chip->ptp_cc_mult_num = MV88E6250_CC_MULT_NUM;
+ chip->ptp_cc_mult_dem = MV88E6250_CC_MULT_DEM;
+ } else {
+ chip->ptp_cc_shift = MV88E6XXX_CC_SHIFT;
+ chip->ptp_cc_mult = MV88E6XXX_CC_MULT;
+ chip->ptp_cc_mult_num = MV88E6XXX_CC_MULT_NUM;
+ chip->ptp_cc_mult_dem = MV88E6XXX_CC_MULT_DEM;
+ }
+
/* Set up the cycle counter */
memset(&chip->tstamp_cc, 0, sizeof(chip->tstamp_cc));
chip->tstamp_cc.read = mv88e6xxx_ptp_clock_read;
chip->tstamp_cc.mask = CYCLECOUNTER_MASK(32);
- chip->tstamp_cc.mult = CC_MULT;
- chip->tstamp_cc.shift = CC_SHIFT;
+ chip->tstamp_cc.mult = chip->ptp_cc_mult;
+ chip->tstamp_cc.shift = chip->ptp_cc_shift;
timecounter_init(&chip->tstamp_tc, &chip->tstamp_cc,
ktime_to_ns(ktime_get_real()));
@@ -397,7 +426,6 @@ int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip)
chip->ptp_clock_info.owner = THIS_MODULE;
snprintf(chip->ptp_clock_info.name, sizeof(chip->ptp_clock_info.name),
"%s", dev_name(chip->dev));
- chip->ptp_clock_info.max_adj = 1000000;
chip->ptp_clock_info.n_ext_ts = ptp_ops->n_ext_ts;
chip->ptp_clock_info.n_per_out = 0;
@@ -413,6 +441,7 @@ int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip)
}
chip->ptp_clock_info.pin_config = chip->pin_config;
+ chip->ptp_clock_info.max_adj = MV88E6XXX_MAX_ADJ_PPB;
chip->ptp_clock_info.adjfine = mv88e6xxx_ptp_adjfine;
chip->ptp_clock_info.adjtime = mv88e6xxx_ptp_adjtime;
chip->ptp_clock_info.gettime64 = mv88e6xxx_ptp_gettime;
--
2.22.0
^ permalink raw reply related
* [PATCH 0/4] net: dsa: mv88e6xxx: add support for MV88E6220
From: Hubert Feurstein @ 2019-07-30 10:04 UTC (permalink / raw)
To: netdev, linux-kernel
Cc: Hubert Feurstein, Andrew Lunn, Vivien Didelot, Florian Fainelli,
David S. Miller, Rasmus Villemoes
This patch series adds support for the MV88E6220 chip to the mv88e6xxx driver.
The MV88E6220 is almost the same as MV88E6250 except that the ports 2-4 are
not routed to pins.
Furthermore, PTP support is added to the MV88E6250 family.
Hubert Feurstein (4):
net: dsa: mv88e6xxx: add support for MV88E6220
dt-bindings: net: dsa: marvell: add 6220 model to the 6250 family
net: dsa: mv88e6xxx: setup message port is not supported in the 6250
family
net: dsa: mv88e6xxx: add PTP support for MV88E6250 family
.../devicetree/bindings/net/dsa/marvell.txt | 2 +-
drivers/net/dsa/mv88e6xxx/chip.c | 63 +++++++++++++++-
drivers/net/dsa/mv88e6xxx/chip.h | 8 +-
drivers/net/dsa/mv88e6xxx/port.h | 1 +
drivers/net/dsa/mv88e6xxx/ptp.c | 73 +++++++++++++------
5 files changed, 120 insertions(+), 27 deletions(-)
--
2.22.0
^ permalink raw reply
* Re: [PATCH] net: bridge: Allow bridge to joing multicast groups
From: Ido Schimmel @ 2019-07-30 10:04 UTC (permalink / raw)
To: Allan W. Nielsen
Cc: Nikolay Aleksandrov, Horatiu Vultur, roopa, davem, bridge, netdev,
linux-kernel
In-Reply-To: <20190730083027.biuzy7h5dbq7pik3@lx-anielsen.microsemi.net>
On Tue, Jul 30, 2019 at 10:30:28AM +0200, Allan W. Nielsen wrote:
> The 07/30/2019 10:06, Ido Schimmel wrote:
> > As a bonus, existing drivers could benefit from it, as MDB entries are already
> > notified by MAC.
> Not sure I follow. When FDB entries are added, it also generates notification
> events.
I meant the switchdev notification sent to drivers:
/* SWITCHDEV_OBJ_ID_PORT_MDB */
struct switchdev_obj_port_mdb {
struct switchdev_obj obj;
unsigned char addr[ETH_ALEN];
u16 vid;
};
By extending MDB entries to also be keyed by MAC you basically get a lot
of things for free without duplicating the same code for multicast FDBs.
AFAICS, then only change in the fast path is in br_mdb_get() where you
need to use DMAC as key in case Ethertype is not IPv4/IPv6.
^ permalink raw reply
* Re: [PATCH v4 0/5] vsock/virtio: optimizations to increase the throughput
From: Jason Wang @ 2019-07-30 10:03 UTC (permalink / raw)
To: Stefano Garzarella, Michael S. Tsirkin, Stefan Hajnoczi,
David S. Miller
Cc: netdev, linux-kernel, virtualization, kvm
In-Reply-To: <20190730094013.ruqjllqrjmkdnh5y@steredhat>
On 2019/7/30 下午5:40, Stefano Garzarella wrote:
> On Mon, Jul 29, 2019 at 09:59:23AM -0400, Michael S. Tsirkin wrote:
>> On Wed, Jul 17, 2019 at 01:30:25PM +0200, Stefano Garzarella wrote:
>>> This series tries to increase the throughput of virtio-vsock with slight
>>> changes.
>>> While I was testing the v2 of this series I discovered an huge use of memory,
>>> so I added patch 1 to mitigate this issue. I put it in this series in order
>>> to better track the performance trends.
>> Series:
>>
>> Acked-by: Michael S. Tsirkin <mst@redhat.com>
>>
>> Can this go into net-next?
>>
> I think so.
> Michael, Stefan thanks to ack the series!
>
> Should I resend it with net-next tag?
>
> Thanks,
> Stefano
I think so.
Thanks
^ permalink raw reply
* Re: DSA Rate Limiting in 88E6390
From: Benjamin Beckmeyer @ 2019-07-30 9:58 UTC (permalink / raw)
To: Andrew Lunn; +Cc: netdev
In-Reply-To: <20190729150158.GE4110@lunn.ch>
>> Hi all,
>> is there a possibility to set the rate limiting for the 6390 with linux tools?
>> I've seen that the driver will init all to zero, so rate limiting is disabled,
>> but there is no solution for it in the ip tool?
>>
>> The only thing I found for rate limiting is the tc tool, but I guess this is
>> only a software solution?
> Hi Benjamin
>
> In Linux, we accelerate the software solution by offloading it to the
> hardware. So TC is what you need here.
>
>> Furthermore, does exist a table or a tutorial which functions DSA supports?
>> The background is that we are using the DSDT driver (in future maybe the UMSD
>> driver) but we would like to switch to the in kernel DSA entirely. And our
>> software is using some of the DSDT functions, so I have to find an
>> alternative to these functions.
> The DSA framework supports offloading TC. There was some patches a
> while back adding ingress rate limiting to one of the DSA drivers, via
> TC. I forget which, and i don't think they have been merged yet. If
> you can find the patchset, it should give you a good idea how you can
> implement support in the mv88e6xxx driver.
>
> Andrew
Hi Andrew,
I've searched the netdev mailing list for DSA and traffic, but can't find anything
about rate limiting till 2016. Do you have a hint, how I can find it?
Do you know if the patchset was for Marvell or maybe for another company?
Cheers,
Benjamin
^ permalink raw reply
* Re: [PATCH] net: bridge: Allow bridge to joing multicast groups
From: Nikolay Aleksandrov @ 2019-07-30 9:55 UTC (permalink / raw)
To: Allan W. Nielsen
Cc: Ido Schimmel, Horatiu Vultur, roopa, davem, bridge, netdev,
linux-kernel
In-Reply-To: <20190730092118.key2ygh3ggpd3tkq@lx-anielsen.microsemi.net>
On 30/07/2019 12:21, Allan W. Nielsen wrote:
> The 07/30/2019 11:58, Nikolay Aleksandrov wrote:
>> On 30/07/2019 11:30, Allan W. Nielsen wrote:
>>> The 07/30/2019 10:06, Ido Schimmel wrote:
>>>> On Tue, Jul 30, 2019 at 08:27:22AM +0200, Allan W. Nielsen wrote:
>>>>> The 07/29/2019 20:51, Ido Schimmel wrote:
>>>>>> Can you please clarify what you're trying to achieve? I just read the
>>>>>> thread again and my impression is that you're trying to locally receive
>>>>>> packets with a certain link layer multicast address.
>>>>> Yes. The thread is also a bit confusing because we half way through realized
>>>>> that we misunderstood how the multicast packets should be handled (sorry about
>>>>> that). To begin with we had a driver where multicast packets was only copied to
>>>>> the CPU if someone needed it. Andrew and Nikolay made us aware that this is not
>>>>> how other drivers are doing it, so we changed the driver to include the CPU in
>>>>> the default multicast flood-mask.
>>>> OK, so what prevents you from removing all other ports from the
>>>> flood-mask and letting the CPU handle the flooding? Then you can install
>>>> software tc filters to limit the flooding.
>>> I do not have the bandwidth to forward the multicast traffic in the CPU.
>>>
>>> It will also cause enormous latency on the forwarding of L2 multicast packets.
>>>
>>>>> This changes the objective a bit. To begin with we needed to get more packets to
>>>>> the CPU (which could have been done using tc ingress rules and a trap action).
>>>>>
>>>>> Now after we changed the driver, we realized that we need something to limit the
>>>>> flooding of certain L2 multicast packets. This is the new problem we are trying
>>>>> to solve!
>>>>>
>>>>> Example: Say we have a bridge with 4 slave interfaces, then we want to install a
>>>>> forwarding rule saying that packets to a given L2-multicast MAC address, should
>>>>> only be flooded to 2 of the 4 ports.
>>>>>
>>>>> (instead of adding rules to get certain packets to the CPU, we are now adding
>>>>> other rules to prevent other packets from going to the CPU and other ports where
>>>>> they are not needed/wanted).
>>>>>
>>>>> This is exactly the same thing as IGMP snooping does dynamically, but only for
>>>>> IP multicast.
>>>>>
>>>>> The "bridge mdb" allow users to manually/static add/del a port to a multicast
>>>>> group, but still it operates on IP multicast address (not L2 multicast
>>>>> addresses).
>>>>>
>>>>>> Nik suggested SIOCADDMULTI.
>>>>> It is not clear to me how this should be used to limit the flooding, maybe we
>>>>> can make some hacks, but as far as I understand the intend of this is maintain
>>>>> the list of addresses an interface should receive. I'm not sure this should
>>>>> influence how for forwarding decisions are being made.
>>>>>
>>>>>> and I suggested a tc filter to get the packet to the CPU.
>>>>> The TC solution is a good solution to the original problem where wanted to copy
>>>>> more frames to the CPU. But we were convinced that this is not the right
>>>>> approach, and that the CPU by default should receive all multicast packets, and
>>>>> we should instead try to find a way to limit the flooding of certain frames as
>>>>> an optimization.
>>>>
>>>> This can still work. In Linux, ingress tc filters are executed before the
>>>> bridge's Rx handler. The same happens in every sane HW. Ingress ACL is
>>>> performed before L2 forwarding. Assuming you have eth0-eth3 bridged and
>>>> you want to prevent packets with DMAC 01:21:6C:00:00:01 from egressing
>>>> eth2:
>>>>
>>>> # tc filter add dev eth0 ingress pref 1 flower skip_sw \
>>>> dst_mac 01:21:6C:00:00:01 action trap
>>>> # tc filter add dev eth2 egress pref 1 flower skip_hw \
>>>> dst_mac 01:21:6C:00:00:01 action drop
>>>>
>>>> The first filter is only present in HW ('skip_sw') and should result in
>>>> your HW passing you the sole copy of the packet.
>>> Agree.
>>>
>>>> The second filter is only present in SW ('skip_hw', not using HW egress
>>>> ACL that you don't have) and drops the packet after it was flooded by
>>>> the SW bridge.
>>> Agree.
>>>
>>>> As I mentioned earlier, you can install the filter once in your HW and
>>>> share it between different ports using a shared block. This means you
>>>> only consume one TCAM entry.
>>>>
>>>> Note that this allows you to keep flooding all other multicast packets
>>>> in HW.
>>> Yes, but the frames we want to limit the flood-mask on are the exact frames
>>> which occurs at a very high rate, and where latency is important.
>>>
>>> I really do not consider it as an option to forward this in SW, when it is
>>> something that can easily be offloaded in HW.
>>>
>>>>>> If you now want to limit the ports to which this packet is flooded, then
>>>>>> you can use tc filters in *software*:
>>>>>>
>>>>>> # tc qdisc add dev eth2 clsact
>>>>>> # tc filter add dev eth2 egress pref 1 flower skip_hw \
>>>>>> dst_mac 01:21:6C:00:00:01 action drop
>>>>> Yes. This can work in the SW bridge.
>>>>>
>>>>>> If you want to forward the packet in hardware and locally receive it,
>>>>>> you can chain several mirred action and then a trap action.
>>>>> I'm not I fully understand how this should be done, but it does sound like it
>>>>> becomes quite complicated. Also, as far as I understand it will mean that we
>>>>> will be using TCAM/ACL resources to do something that could have been done with
>>>>> a simple MAC entry.
>>>>>
>>>>>> Both options avoid HW egress ACLs which your design does not support.
>>>>> True, but what is wrong with expanding the functionality of the normal
>>>>> forwarding/MAC operations to allow multiple destinations?
>>>>>
>>>>> It is not an uncommon feature (I just browsed the manual of some common L2
>>>>> switches and they all has this feature).
>>>>>
>>>>> It seems to fit nicely into the existing user-interface:
>>>>>
>>>>> bridge fdb add 01:21:6C:00:00:01 port eth0
>>>>> bridge fdb append 01:21:6C:00:00:01 port eth1
>>>>
>>>> Wouldn't it be better to instead extend the MDB entries so that they are
>>>> either keyed by IP or MAC? I believe FDB should remain as unicast-only.
>>>
>>> You might be right, it was not clear to me which of the two would fit the
>>> purpose best.
>>>
>>> From a user-space iproute2 perspective I prefer using the "bridge fdb" command
>>> as it already supports the needed syntax, and I do not think it will be too
>>> pretty if we squeeze this into the "bridge mdb" command syntax.
>>>
>>
>> MDB is a much better fit as Ido already suggested. FDB should remain unicast
>> and mixing them is not a good idea, we already have a good ucast/mcast separation
>> and we'd like to keep it that way.
> Okay. We will explore that option.
>
>
Great, thanks.
>>> But that does not mean that it need to go into the FDB database in the
>>> implementation.
>>>
>>> Last evening when I looked at it again, I was considering keeping the
>>> net_bridge_fdb_entry structure as is, and add a new hashtable with the
>>> following:
>>>
>>> struct net_bridge_fdbmc_entry {
>>> struct rhash_head rhnode;
>>> struct net_bridge_fdbmc_ports *dst;
>>>
>>> struct net_bridge_fdb_key key;
>>> struct hlist_node fdb_node;
>>> unsigned char offloaded:1;
>>>
>>> struct rcu_head rcu;
>>> };
>>>
>>
>> What would the notification for this look like ?
> Not sure. But we will change the direction and use the MDB structures instead.
>
Ack
>>> If we go with this approach then we can look at the MAC address and see if it is
>>> a unicast which will cause a lookup in the fdb, l3-multicast (33:33:* or
>>> 01:00:5e:*) which will cause a lookup in the mdb, or finally a fdbmc which will
>>> need to do a lookup in this new hashtable.
>>
>> That sounds wrong, you will change the current default behaviour of flooding these
>> packets. This will have to be well hidden behind a new option and enabled only on user
>> request.
> It will only affect users who install a static L2-multicast entry. If no entry
> is found, it will default to flooding, which will be the same as before.
>
Ack
>>> Alternative it would be like this:
>>>
>>> struct net_bridge_fdb_entry {
>>> struct rhash_head rhnode;
>>> union net_bridge_port_or_list *dst;
>>>
>>> struct net_bridge_fdb_key key;
>>> struct hlist_node fdb_node;
>>> unsigned char is_local:1,
>>> is_static:1,
>>> is_sticky:1,
>>> added_by_user:1,
>>> added_by_external_learn:1,
>>> offloaded:1;
>>> multi_dst:1;
>>>
>>> /* write-heavy members should not affect lookups */
>>> unsigned long updated ____cacheline_aligned_in_smp;
>>> unsigned long used;
>>>
>>> struct rcu_head rcu;
>>> };
>>>
>>> Both solutions should require fairly few changes, and should not cause any
>>> measurable performance hit.
>>>
>>
>> You'll have to convert these bits to use the proper atomic bitops if you go with
>> the second solution. That has to be done even today, but the second case would
>> make it a must.
> Good to know.
>
> Just for my understanding, is this because this is the "current" guide lines on
> how things should be done, or is this because the multi_dst as a special need.
>
> The multi_dst flag will never be changed in the life-cycle of the structure, and
> the structure is protected by rcu. If this is causeing a raise, then I do not
> see it.
>
These flags are changed from different contexts without any locking and you can end
up with wrong values since these are not atomic ops. We need to move to atomic ops
to guarantee consistent results. It is not only multi_dst issue, it's a problem
for all of them, it's just not critical today since you'll end up with wrong
flag values in such cases, but with multi_dst it will be important because the union
pointer will have to be treated different based on the multi_dst value.
>>> Making it fit into the net_bridge_mdb_entry seems to be harder.
>>>
>>
>> But it is the correct abstraction from bridge POV, so please stop trying to change
>> the FDB code and try to keep to the multicast code.
> We are planning on letting the net_bridge_port_or_list union use the
> net_bridge_port_group structure, which will mean that we can re-use the
> br_multicast_flood function (if we change the signatire to accept the ports
> instead of the entry).
>
That sounds great, definitely a step in the right direction.
>>>> As a bonus, existing drivers could benefit from it, as MDB entries are already
>>>> notified by MAC.
>>> Not sure I follow. When FDB entries are added, it also generates notification
>>> events.
>>>
>>
>> Could you please show fdb event with multiple ports ?
> We will get to that. Maybe this is an argument for converting to mdb. We have
> not looked into the details of this yet.
>
I can see a few potential problems, the important thing here would be to keep
backwards compatibility.
>>>>> It seems that it can be added to the existing implementation with out adding
>>>>> significant complexity.
>>>>>
>>>>> It will be easy to offload in HW.
>>>>>
>>>>> I do not believe that it will be a performance issue, if this is a concern then
>>>>> we may have to do a bit of benchmarking, or we can make it a configuration
>>>>> option.
>>>>>
>>>>> Long story short, we (Horatiu and I) learned a lot from the discussion here, and
>>>>> I think we should try do a new patch with the learning we got. Then it is easier
>>>>> to see what it actually means to the exiting code, complexity, exiting drivers,
>>>>> performance, default behavioral, backwards compatibly, and other valid concerns.
>>>>>
>>>>> If the patch is no good, and cannot be fixed, then we will go back and look
>>>>> further into alternative solutions.
>>>> Overall, I tend to agree with Nik. I think your use case is too specific
>>>> to justify the amount of changes you want to make in the bridge driver.
>>>> We also provided other alternatives. That being said, you're more than
>>>> welcome to send the patches and we can continue the discussion then.
>>> Okay, good to know. I'm not sure I agree that the alternative solutions really
>>> solves the issue this is trying to solve, nor do I agree that this is specific
>>> to our needs.
>>>
>>> But lets take a look at a new patch, and see what is the amount of changes we
>>> are talking about. Without having the patch it is really hard to know for sure.
>> Please keep in mind that this case is the exception, not the norm, thus it should
>> not under any circumstance affect the standard deployments.
> Understood - no surprises.
>
Great, thanks again. Will continue discussing when the new patch arrives.
Cheers,
Nik
^ permalink raw reply
* RE: [PATCH] rtw88: pci: Use general byte arrays as the elements of RX ring
From: David Laight @ 2019-07-30 9:48 UTC (permalink / raw)
To: 'Stanislaw Gruszka', Jian-Hong Pan
Cc: Yan-Hsuan Chuang, Kalle Valo, David S . Miller,
linux-wireless@vger.kernel.org, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, linux@endlessm.com,
stable@vger.kernel.org
In-Reply-To: <20190730093533.GC3174@redhat.com>
From: Stanislaw Gruszka
> Sent: 30 July 2019 10:36
...
> > + len = pkt_stat.pkt_len + pkt_offset;
> > + skb = dev_alloc_skb(len);
> > + if (WARN_ONCE(!skb, "rx routine starvation\n"))
> > goto next_rp;
> >
> > /* put the DMA data including rx_desc from phy to new skb */
> > - skb_put_data(new, skb->data, new_len);
> > + skb_put_data(skb, rx_desc, len);
>
> Coping big packets it quite inefficient. What drivers usually do is
> copy only for small packets and for big ones allocate new rx buf
> (drop packet alloc if fail) and pas old buf to network stack via
> skb_add_rx_frag(). See iwlmvm as example.
If you have to do iommu setup/teardown then the breakeven point
for (not) copying may be surprisingly large.
You do need to do the measurements on a range of hardware.
Coping is also likely to affect the L1 cache - unless you can
copy quickly without polluting the cache.
It is all 'swings and roundabouts'.
David
-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)
^ permalink raw reply
* [PATCH] net: phy: fixed_phy: print gpio error only if gpio node is present
From: Hubert Feurstein @ 2019-07-30 9:46 UTC (permalink / raw)
To: netdev, linux-kernel
Cc: Hubert Feurstein, Andrew Lunn, Florian Fainelli, Heiner Kallweit,
David S. Miller
It is perfectly ok to not have an gpio attached to the fixed-link node. So
the driver should not throw an error message when the gpio is missing.
Signed-off-by: Hubert Feurstein <h.feurstein@gmail.com>
---
drivers/net/phy/fixed_phy.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/net/phy/fixed_phy.c b/drivers/net/phy/fixed_phy.c
index 3ffe46df249e..7c5265fd2b94 100644
--- a/drivers/net/phy/fixed_phy.c
+++ b/drivers/net/phy/fixed_phy.c
@@ -216,8 +216,10 @@ static struct gpio_desc *fixed_phy_get_gpiod(struct device_node *np)
if (IS_ERR(gpiod)) {
if (PTR_ERR(gpiod) == -EPROBE_DEFER)
return gpiod;
- pr_err("error getting GPIO for fixed link %pOF, proceed without\n",
- fixed_link_node);
+
+ if (PTR_ERR(gpiod) != -ENOENT)
+ pr_err("error getting GPIO for fixed link %pOF, proceed without\n",
+ fixed_link_node);
gpiod = NULL;
}
--
2.22.0
^ permalink raw reply related
* [PATCH net-next v4 0/4] enetc: Add mdio bus driver for the PCIe MDIO endpoint
From: Claudiu Manoil @ 2019-07-30 9:45 UTC (permalink / raw)
To: David S . Miller
Cc: andrew, Rob Herring, Li Yang, alexandru.marginean, netdev,
devicetree, linux-arm-kernel, linux-kernel
First patch fixes a sparse issue and cleans up accessors to avoid
casting to __iomem.
Second patch just registers the PCIe endpoint device containing
the MDIO registers as a standalone MDIO bus driver, to allow
an alternative way to control the MDIO bus. The same code used
by the ENETC ports (eth controllers) to manage MDIO via local
registers applies and is reused.
Bindings are provided for the new MDIO node, similarly to ENETC
port nodes bindings.
Last patch enables the ENETC port 1 and its RGMII PHY on the
LS1028A QDS board, where the MDIO muxing configuration relies
on the MDIO support provided in the first patch.
Changes since v0:
v1 - fixed mdio bus allocation
v2 - cleaned up accessors to avoid casting
v3 - fixed spelling (mostly commit message)
v4 - fixed err path check blunder
Claudiu Manoil (4):
enetc: Clean up local mdio bus allocation
enetc: Add mdio bus driver for the PCIe MDIO endpoint
dt-bindings: net: fsl: enetc: Add bindings for the central MDIO PCIe
endpoint
arm64: dts: fsl: ls1028a: Enable eth port1 on the ls1028a QDS board
.../devicetree/bindings/net/fsl-enetc.txt | 42 +++-
.../boot/dts/freescale/fsl-ls1028a-qds.dts | 40 ++++
.../arm64/boot/dts/freescale/fsl-ls1028a.dtsi | 6 +
.../net/ethernet/freescale/enetc/enetc_mdio.c | 190 +++++++++++++-----
.../net/ethernet/freescale/enetc/enetc_pf.c | 5 +-
5 files changed, 232 insertions(+), 51 deletions(-)
--
2.17.1
^ permalink raw reply
* [PATCH net-next v4 2/4] enetc: Add mdio bus driver for the PCIe MDIO endpoint
From: Claudiu Manoil @ 2019-07-30 9:45 UTC (permalink / raw)
To: David S . Miller
Cc: andrew, Rob Herring, Li Yang, alexandru.marginean, netdev,
devicetree, linux-arm-kernel, linux-kernel
In-Reply-To: <1564479919-18835-1-git-send-email-claudiu.manoil@nxp.com>
ENETC ports can manage the MDIO bus via local register
interface. However there's also a centralized way
to manage the MDIO bus, via the MDIO PCIe endpoint
device integrated by the same root complex that also
integrates the ENETC ports (eth controllers).
Depending on board design and use case, centralized
access to MDIO may be better than using local ENETC
port registers. For instance, on the LS1028A QDS board
where MDIO muxing is required. Also, the LS1028A on-chip
switch doesn't have a local MDIO register interface.
The current patch registers the above PCIe endpoint as a
separate MDIO bus and provides a driver for it by re-using
the code used for local MDIO access. It also allows the
ENETC port PHYs to be managed by this driver if the local
"mdio" node is missing from the ENETC port node.
Signed-off-by: Claudiu Manoil <claudiu.manoil@nxp.com>
---
v1 - fixed mdio bus allocation
- requested only BAR0 region, as it's the only one used by the driver
v2 - reworked accessors as per Andrew Lunn's request
v3 - none
v4 - err path check fix
.../net/ethernet/freescale/enetc/enetc_mdio.c | 98 +++++++++++++++++++
.../net/ethernet/freescale/enetc/enetc_pf.c | 5 +-
2 files changed, 102 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_mdio.c b/drivers/net/ethernet/freescale/enetc/enetc_mdio.c
index 05094601ece8..d2a0f910af9b 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_mdio.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_mdio.c
@@ -195,3 +195,101 @@ void enetc_mdio_remove(struct enetc_pf *pf)
if (pf->mdio)
mdiobus_unregister(pf->mdio);
}
+
+#define ENETC_MDIO_DEV_ID 0xee01
+#define ENETC_MDIO_DEV_NAME "FSL PCIe IE Central MDIO"
+#define ENETC_MDIO_BUS_NAME ENETC_MDIO_DEV_NAME " Bus"
+#define ENETC_MDIO_DRV_NAME ENETC_MDIO_DEV_NAME " driver"
+#define ENETC_MDIO_DRV_ID "fsl_enetc_mdio"
+
+static int enetc_pci_mdio_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ struct enetc_mdio_priv *mdio_priv;
+ struct device *dev = &pdev->dev;
+ struct enetc_hw *hw;
+ struct mii_bus *bus;
+ int err;
+
+ hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL);
+ if (!hw)
+ return -ENOMEM;
+
+ bus = devm_mdiobus_alloc_size(dev, sizeof(*mdio_priv));
+ if (!bus)
+ return -ENOMEM;
+
+ bus->name = ENETC_MDIO_BUS_NAME;
+ bus->read = enetc_mdio_read;
+ bus->write = enetc_mdio_write;
+ bus->parent = dev;
+ mdio_priv = bus->priv;
+ mdio_priv->hw = hw;
+ snprintf(bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev));
+
+ pcie_flr(pdev);
+ err = pci_enable_device_mem(pdev);
+ if (err) {
+ dev_err(dev, "device enable failed\n");
+ return err;
+ }
+
+ err = pci_request_region(pdev, 0, ENETC_MDIO_DRV_ID);
+ if (err) {
+ dev_err(dev, "pci_request_region failed\n");
+ goto err_pci_mem_reg;
+ }
+
+ hw->port = pci_iomap(pdev, 0, 0);
+ if (!hw->port) {
+ err = -ENXIO;
+ dev_err(dev, "iomap failed\n");
+ goto err_ioremap;
+ }
+
+ err = of_mdiobus_register(bus, dev->of_node);
+ if (err)
+ goto err_mdiobus_reg;
+
+ pci_set_drvdata(pdev, bus);
+
+ return 0;
+
+err_mdiobus_reg:
+ iounmap(mdio_priv->hw->port);
+err_ioremap:
+ pci_release_mem_regions(pdev);
+err_pci_mem_reg:
+ pci_disable_device(pdev);
+
+ return err;
+}
+
+static void enetc_pci_mdio_remove(struct pci_dev *pdev)
+{
+ struct mii_bus *bus = pci_get_drvdata(pdev);
+ struct enetc_mdio_priv *mdio_priv;
+
+ mdiobus_unregister(bus);
+ mdio_priv = bus->priv;
+ iounmap(mdio_priv->hw->port);
+ pci_release_mem_regions(pdev);
+ pci_disable_device(pdev);
+}
+
+static const struct pci_device_id enetc_pci_mdio_id_table[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_MDIO_DEV_ID) },
+ { 0, } /* End of table. */
+};
+MODULE_DEVICE_TABLE(pci, enetc_mdio_id_table);
+
+static struct pci_driver enetc_pci_mdio_driver = {
+ .name = ENETC_MDIO_DRV_ID,
+ .id_table = enetc_pci_mdio_id_table,
+ .probe = enetc_pci_mdio_probe,
+ .remove = enetc_pci_mdio_remove,
+};
+module_pci_driver(enetc_pci_mdio_driver);
+
+MODULE_DESCRIPTION(ENETC_MDIO_DRV_NAME);
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index 258b3cb38a6f..7d6513ff8507 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -750,6 +750,7 @@ static int enetc_of_get_phy(struct enetc_ndev_priv *priv)
{
struct enetc_pf *pf = enetc_si_priv(priv->si);
struct device_node *np = priv->dev->of_node;
+ struct device_node *mdio_np;
int err;
if (!np) {
@@ -773,7 +774,9 @@ static int enetc_of_get_phy(struct enetc_ndev_priv *priv)
priv->phy_node = of_node_get(np);
}
- if (!of_phy_is_fixed_link(np)) {
+ mdio_np = of_get_child_by_name(np, "mdio");
+ if (mdio_np) {
+ of_node_put(mdio_np);
err = enetc_mdio_probe(pf);
if (err) {
of_node_put(priv->phy_node);
--
2.17.1
^ permalink raw reply related
* [PATCH net-next v4 3/4] dt-bindings: net: fsl: enetc: Add bindings for the central MDIO PCIe endpoint
From: Claudiu Manoil @ 2019-07-30 9:45 UTC (permalink / raw)
To: David S . Miller
Cc: andrew, Rob Herring, Li Yang, alexandru.marginean, netdev,
devicetree, linux-arm-kernel, linux-kernel
In-Reply-To: <1564479919-18835-1-git-send-email-claudiu.manoil@nxp.com>
The on-chip PCIe root complex that integrates the ENETC ethernet
controllers also integrates a PCIe endpoint for the MDIO controller
providing for centralized control of the ENETC mdio bus.
Add bindings for this "central" MDIO Integrated PCIe Endpoint.
Signed-off-by: Claudiu Manoil <claudiu.manoil@nxp.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
v1 - none
v2 - none
v3 - fixed spelling (commit message mostly)
v4 - none
.../devicetree/bindings/net/fsl-enetc.txt | 42 +++++++++++++++++--
1 file changed, 39 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/fsl-enetc.txt b/Documentation/devicetree/bindings/net/fsl-enetc.txt
index 25fc687419db..b7034ccbc1bd 100644
--- a/Documentation/devicetree/bindings/net/fsl-enetc.txt
+++ b/Documentation/devicetree/bindings/net/fsl-enetc.txt
@@ -11,7 +11,9 @@ Required properties:
to parent node bindings.
- compatible : Should be "fsl,enetc".
-1) The ENETC external port is connected to a MDIO configurable phy:
+1. The ENETC external port is connected to a MDIO configurable phy
+
+1.1. Using the local ENETC Port MDIO interface
In this case, the ENETC node should include a "mdio" sub-node
that in turn should contain the "ethernet-phy" node describing the
@@ -47,8 +49,42 @@ Example:
};
};
-2) The ENETC port is an internal port or has a fixed-link external
-connection:
+1.2. Using the central MDIO PCIe endpoint device
+
+In this case, the mdio node should be defined as another PCIe
+endpoint node, at the same level with the ENETC port nodes.
+
+Required properties:
+
+- reg : Specifies PCIe Device Number and Function
+ Number of the ENETC endpoint device, according
+ to parent node bindings.
+- compatible : Should be "fsl,enetc-mdio".
+
+The remaining required mdio bus properties are standard, their bindings
+already defined in Documentation/devicetree/bindings/net/mdio.txt.
+
+Example:
+
+ ethernet@0,0 {
+ compatible = "fsl,enetc";
+ reg = <0x000000 0 0 0 0>;
+ phy-handle = <&sgmii_phy0>;
+ phy-connection-type = "sgmii";
+ };
+
+ mdio@0,3 {
+ compatible = "fsl,enetc-mdio";
+ reg = <0x000300 0 0 0 0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ sgmii_phy0: ethernet-phy@2 {
+ reg = <0x2>;
+ };
+ };
+
+2. The ENETC port is an internal port or has a fixed-link external
+connection
In this case, the ENETC port node defines a fixed link connection,
as specified by Documentation/devicetree/bindings/net/fixed-link.txt.
--
2.17.1
^ permalink raw reply related
* [PATCH net-next v4 4/4] arm64: dts: fsl: ls1028a: Enable eth port1 on the ls1028a QDS board
From: Claudiu Manoil @ 2019-07-30 9:45 UTC (permalink / raw)
To: David S . Miller
Cc: andrew, Rob Herring, Li Yang, alexandru.marginean, netdev,
devicetree, linux-arm-kernel, linux-kernel
In-Reply-To: <1564479919-18835-1-git-send-email-claudiu.manoil@nxp.com>
LS1028a has one Ethernet management interface. On the QDS board, the
MDIO signals are multiplexed to either on-board AR8035 PHY device or
to 4 PCIe slots allowing for SGMII cards.
To enable the Ethernet ENETC Port 1, which can only be connected to a
RGMII PHY, the multiplexer needs to be configured to route the MDIO to
the AR8035 PHY. The MDIO/MDC routing is controlled by bits 7:4 of FPGA
board config register 0x54, and value 0 selects the on-board RGMII PHY.
The FPGA board config registers are accessible on the i2c bus, at address
0x66.
The PF3 MDIO PCIe integrated endpoint device allows for centralized access
to the MDIO bus. Add the corresponding devicetree node and set it to be
the MDIO bus parent.
Signed-off-by: Alex Marginean <alexandru.marginean@nxp.com>
Signed-off-by: Claudiu Manoil <claudiu.manoil@nxp.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
v1-v4 - none
.../boot/dts/freescale/fsl-ls1028a-qds.dts | 40 +++++++++++++++++++
.../arm64/boot/dts/freescale/fsl-ls1028a.dtsi | 6 +++
2 files changed, 46 insertions(+)
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds.dts b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds.dts
index de6ef39f3118..663c4b728c07 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds.dts
@@ -85,6 +85,26 @@
system-clock-frequency = <25000000>;
};
};
+
+ mdio-mux {
+ compatible = "mdio-mux-multiplexer";
+ mux-controls = <&mux 0>;
+ mdio-parent-bus = <&enetc_mdio_pf3>;
+ #address-cells=<1>;
+ #size-cells = <0>;
+
+ /* on-board RGMII PHY */
+ mdio@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+
+ qds_phy1: ethernet-phy@5 {
+ /* Atheros 8035 */
+ reg = <5>;
+ };
+ };
+ };
};
&duart0 {
@@ -164,6 +184,26 @@
};
};
};
+
+ fpga@66 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,ls1028aqds-fpga", "fsl,fpga-qixis-i2c",
+ "simple-mfd";
+ reg = <0x66>;
+
+ mux: mux-controller {
+ compatible = "reg-mux";
+ #mux-control-cells = <1>;
+ mux-reg-masks = <0x54 0xf0>; /* 0: reg 0x54, bits 7:4 */
+ };
+ };
+
+};
+
+&enetc_port1 {
+ phy-handle = <&qds_phy1>;
+ phy-connection-type = "rgmii-id";
};
&sai1 {
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi
index 7975519b4f56..de71153fda00 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi
@@ -536,6 +536,12 @@
compatible = "fsl,enetc";
reg = <0x000100 0 0 0 0>;
};
+ enetc_mdio_pf3: mdio@0,3 {
+ compatible = "fsl,enetc-mdio";
+ reg = <0x000300 0 0 0 0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
ethernet@0,4 {
compatible = "fsl,enetc-ptp";
reg = <0x000400 0 0 0 0>;
--
2.17.1
^ permalink raw reply related
* [PATCH net-next v4 1/4] enetc: Clean up local mdio bus allocation
From: Claudiu Manoil @ 2019-07-30 9:45 UTC (permalink / raw)
To: David S . Miller
Cc: andrew, Rob Herring, Li Yang, alexandru.marginean, netdev,
devicetree, linux-arm-kernel, linux-kernel
In-Reply-To: <1564479919-18835-1-git-send-email-claudiu.manoil@nxp.com>
What's needed is basically a pointer to the mdio registers.
This is one way to store it inside bus->priv allocated space,
without upsetting sparse.
Reworked accessors to avoid __iomem casting.
Used devm_* variant to further clean up the init error /
remove paths.
Fixes following sparse warning:
warning: incorrect type in assignment (different address spaces)
expected void *priv
got struct enetc_mdio_regs [noderef] <asn:2>*[assigned] regs
Fixes: ebfcb23d62ab ("enetc: Add ENETC PF level external MDIO support")
Signed-off-by: Claudiu Manoil <claudiu.manoil@nxp.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
v1 - added this patch
v2 - reworked accessors as per Andrew Lunn's request
v3 - cleaned up commit message
v4 - none
.../net/ethernet/freescale/enetc/enetc_mdio.c | 94 +++++++++----------
1 file changed, 46 insertions(+), 48 deletions(-)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_mdio.c b/drivers/net/ethernet/freescale/enetc/enetc_mdio.c
index 77b9cd10ba2b..05094601ece8 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_mdio.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_mdio.c
@@ -8,16 +8,22 @@
#include "enetc_pf.h"
-struct enetc_mdio_regs {
- u32 mdio_cfg; /* MDIO configuration and status */
- u32 mdio_ctl; /* MDIO control */
- u32 mdio_data; /* MDIO data */
- u32 mdio_addr; /* MDIO address */
+#define ENETC_MDIO_REG_OFFSET 0x1c00
+#define ENETC_MDIO_CFG 0x0 /* MDIO configuration and status */
+#define ENETC_MDIO_CTL 0x4 /* MDIO control */
+#define ENETC_MDIO_DATA 0x8 /* MDIO data */
+#define ENETC_MDIO_ADDR 0xc /* MDIO address */
+
+#define enetc_mdio_rd(hw, off) \
+ enetc_port_rd(hw, ENETC_##off + ENETC_MDIO_REG_OFFSET)
+#define enetc_mdio_wr(hw, off, val) \
+ enetc_port_wr(hw, ENETC_##off + ENETC_MDIO_REG_OFFSET, val)
+#define enetc_mdio_rd_reg(off) enetc_mdio_rd(hw, off)
+
+struct enetc_mdio_priv {
+ struct enetc_hw *hw;
};
-#define bus_to_enetc_regs(bus) (struct enetc_mdio_regs __iomem *)((bus)->priv)
-
-#define ENETC_MDIO_REG_OFFSET 0x1c00
#define ENETC_MDC_DIV 258
#define MDIO_CFG_CLKDIV(x) ((((x) >> 1) & 0xff) << 8)
@@ -33,18 +39,19 @@ struct enetc_mdio_regs {
#define MDIO_DATA(x) ((x) & 0xffff)
#define TIMEOUT 1000
-static int enetc_mdio_wait_complete(struct enetc_mdio_regs __iomem *regs)
+static int enetc_mdio_wait_complete(struct enetc_hw *hw)
{
u32 val;
- return readx_poll_timeout(enetc_rd_reg, ®s->mdio_cfg, val,
+ return readx_poll_timeout(enetc_mdio_rd_reg, MDIO_CFG, val,
!(val & MDIO_CFG_BSY), 10, 10 * TIMEOUT);
}
static int enetc_mdio_write(struct mii_bus *bus, int phy_id, int regnum,
u16 value)
{
- struct enetc_mdio_regs __iomem *regs = bus_to_enetc_regs(bus);
+ struct enetc_mdio_priv *mdio_priv = bus->priv;
+ struct enetc_hw *hw = mdio_priv->hw;
u32 mdio_ctl, mdio_cfg;
u16 dev_addr;
int ret;
@@ -59,29 +66,29 @@ static int enetc_mdio_write(struct mii_bus *bus, int phy_id, int regnum,
mdio_cfg &= ~MDIO_CFG_ENC45;
}
- enetc_wr_reg(®s->mdio_cfg, mdio_cfg);
+ enetc_mdio_wr(hw, MDIO_CFG, mdio_cfg);
- ret = enetc_mdio_wait_complete(regs);
+ ret = enetc_mdio_wait_complete(hw);
if (ret)
return ret;
/* set port and dev addr */
mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr);
- enetc_wr_reg(®s->mdio_ctl, mdio_ctl);
+ enetc_mdio_wr(hw, MDIO_CTL, mdio_ctl);
/* set the register address */
if (regnum & MII_ADDR_C45) {
- enetc_wr_reg(®s->mdio_addr, regnum & 0xffff);
+ enetc_mdio_wr(hw, MDIO_ADDR, regnum & 0xffff);
- ret = enetc_mdio_wait_complete(regs);
+ ret = enetc_mdio_wait_complete(hw);
if (ret)
return ret;
}
/* write the value */
- enetc_wr_reg(®s->mdio_data, MDIO_DATA(value));
+ enetc_mdio_wr(hw, MDIO_DATA, MDIO_DATA(value));
- ret = enetc_mdio_wait_complete(regs);
+ ret = enetc_mdio_wait_complete(hw);
if (ret)
return ret;
@@ -90,7 +97,8 @@ static int enetc_mdio_write(struct mii_bus *bus, int phy_id, int regnum,
static int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
{
- struct enetc_mdio_regs __iomem *regs = bus_to_enetc_regs(bus);
+ struct enetc_mdio_priv *mdio_priv = bus->priv;
+ struct enetc_hw *hw = mdio_priv->hw;
u32 mdio_ctl, mdio_cfg;
u16 dev_addr, value;
int ret;
@@ -104,41 +112,41 @@ static int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
mdio_cfg &= ~MDIO_CFG_ENC45;
}
- enetc_wr_reg(®s->mdio_cfg, mdio_cfg);
+ enetc_mdio_wr(hw, MDIO_CFG, mdio_cfg);
- ret = enetc_mdio_wait_complete(regs);
+ ret = enetc_mdio_wait_complete(hw);
if (ret)
return ret;
/* set port and device addr */
mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr);
- enetc_wr_reg(®s->mdio_ctl, mdio_ctl);
+ enetc_mdio_wr(hw, MDIO_CTL, mdio_ctl);
/* set the register address */
if (regnum & MII_ADDR_C45) {
- enetc_wr_reg(®s->mdio_addr, regnum & 0xffff);
+ enetc_mdio_wr(hw, MDIO_ADDR, regnum & 0xffff);
- ret = enetc_mdio_wait_complete(regs);
+ ret = enetc_mdio_wait_complete(hw);
if (ret)
return ret;
}
/* initiate the read */
- enetc_wr_reg(®s->mdio_ctl, mdio_ctl | MDIO_CTL_READ);
+ enetc_mdio_wr(hw, MDIO_CTL, mdio_ctl | MDIO_CTL_READ);
- ret = enetc_mdio_wait_complete(regs);
+ ret = enetc_mdio_wait_complete(hw);
if (ret)
return ret;
/* return all Fs if nothing was there */
- if (enetc_rd_reg(®s->mdio_cfg) & MDIO_CFG_RD_ER) {
+ if (enetc_mdio_rd(hw, MDIO_CFG) & MDIO_CFG_RD_ER) {
dev_dbg(&bus->dev,
"Error while reading PHY%d reg at %d.%hhu\n",
phy_id, dev_addr, regnum);
return 0xffff;
}
- value = enetc_rd_reg(®s->mdio_data) & 0xffff;
+ value = enetc_mdio_rd(hw, MDIO_DATA) & 0xffff;
return value;
}
@@ -146,12 +154,12 @@ static int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
int enetc_mdio_probe(struct enetc_pf *pf)
{
struct device *dev = &pf->si->pdev->dev;
- struct enetc_mdio_regs __iomem *regs;
+ struct enetc_mdio_priv *mdio_priv;
struct device_node *np;
struct mii_bus *bus;
- int ret;
+ int err;
- bus = mdiobus_alloc_size(sizeof(regs));
+ bus = devm_mdiobus_alloc_size(dev, sizeof(*mdio_priv));
if (!bus)
return -ENOMEM;
@@ -159,41 +167,31 @@ int enetc_mdio_probe(struct enetc_pf *pf)
bus->read = enetc_mdio_read;
bus->write = enetc_mdio_write;
bus->parent = dev;
+ mdio_priv = bus->priv;
+ mdio_priv->hw = &pf->si->hw;
snprintf(bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev));
- /* store the enetc mdio base address for this bus */
- regs = pf->si->hw.port + ENETC_MDIO_REG_OFFSET;
- bus->priv = regs;
-
np = of_get_child_by_name(dev->of_node, "mdio");
if (!np) {
dev_err(dev, "MDIO node missing\n");
- ret = -EINVAL;
- goto err_registration;
+ return -EINVAL;
}
- ret = of_mdiobus_register(bus, np);
- if (ret) {
+ err = of_mdiobus_register(bus, np);
+ if (err) {
of_node_put(np);
dev_err(dev, "cannot register MDIO bus\n");
- goto err_registration;
+ return err;
}
of_node_put(np);
pf->mdio = bus;
return 0;
-
-err_registration:
- mdiobus_free(bus);
-
- return ret;
}
void enetc_mdio_remove(struct enetc_pf *pf)
{
- if (pf->mdio) {
+ if (pf->mdio)
mdiobus_unregister(pf->mdio);
- mdiobus_free(pf->mdio);
- }
}
--
2.17.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox