* Re: [PATCH net-next v2] net: openvswitch: Set OvS recirc_id from tc chain index
From: Paul Blakey @ 2019-08-25 14:11 UTC (permalink / raw)
To: David Miller
Cc: pshelar@ovn.org, netdev@vger.kernel.org, jpettit@nicira.com,
simon.horman@netronome.com, marcelo.leitner@gmail.com,
Vlad Buslov, Jiri Pirko, Roi Dayan, Yossi Kuperman, Rony Efraim,
Oz Shlomo
In-Reply-To: <20190821.205735.2069656948701231785.davem@davemloft.net>
On 8/22/2019 6:57 AM, David Miller wrote:
> From: Paul Blakey <paulb@mellanox.com>
> Date: Tue, 20 Aug 2019 15:30:51 +0300
>
>> @@ -4050,6 +4060,9 @@ enum skb_ext_id {
>> #ifdef CONFIG_XFRM
>> SKB_EXT_SEC_PATH,
>> #endif
>> +#if IS_ENABLED(CONFIG_NET_TC_SKB_EXT)
>> + TC_SKB_EXT,
>> +#endif
>> SKB_EXT_NUM, /* must be last */
>> };
> Sorry, no.
>
> The SKB extensions are not a dumping ground for people to use when they can't
> figure out another more reasonable place to put their values. Try to use
> the normal cb[], and if you can't you must explain in exhaustive detail
> why you cannot in any way whatsoever make that work.
>
> Again, SKB extensions are not a dumping ground.
Hi,
The general context of this skb extension patch is hardware offload of
multi chain rules.
This patch shows only one usage of this extension which is by tc -> OvS
miss path.
But we also plan to reuse this extension to pass information from
HW/Driver -> tc miss path.
In tc multi chain rules scenarios, some of the rules might be offloaded
and some not (e.g skip_hw, unsupported rules by HW, vxlan encapsulation,
offload order, etc).
Therefore, HW can miss at any point of the processing chain.
SW will need to continue processing in correct tc chain where the HW
left off, as HW might have modified the packet and updated stats for it.
This scenario can reuse this tc SKB extension to restore the tc chain.
Skb control block acts a scratchpad area for storing temporary
information and isn't suppose
to be used to pass around information between different layers of
processing.
HW/Driver -> tc - >OvS are different layers, and not necessarily
processing the packet one after another.
There can be bridges, tunnel devices, VLAN devices, Netfilter
(Conntrack) and a host of other entities processing the packet in between
so we can't guarantee the control block integrity between this main
processing entities (HW/Driver, Tc, Ovs).
So if we'll use the control block, it will restrict such use cases.
For example, the napi API which we use, uses the control block and comes
right after our driver layer.
This will overwrite any usage of CB by us.
Thanks,
Paul B.
^ permalink raw reply
* Re: [PATCHv2 1/1] net: rds: add service level support in rds-info
From: Zhu Yanjun @ 2019-08-25 14:11 UTC (permalink / raw)
To: David Miller
Cc: santosh.shilimkar, netdev, linux-rdma, rds-devel, gerd.rausch
In-Reply-To: <20190824.165851.1817456673626840850.davem@davemloft.net>
On 2019/8/25 7:58, David Miller wrote:
> From: Zhu Yanjun <yanjun.zhu@oracle.com>
> Date: Fri, 23 Aug 2019 21:04:16 -0400
>
>> diff --git a/include/uapi/linux/rds.h b/include/uapi/linux/rds.h
>> index fd6b5f6..cba368e 100644
>> --- a/include/uapi/linux/rds.h
>> +++ b/include/uapi/linux/rds.h
>> @@ -250,6 +250,7 @@ struct rds_info_rdma_connection {
>> __u32 rdma_mr_max;
>> __u32 rdma_mr_size;
>> __u8 tos;
>> + __u8 sl;
>> __u32 cache_allocs;
>> };
> I'm applying this, but I am once again severely disappointed in how
> RDS development is being handled.
>
> >From the Fixes: commit:
>
> Since rds.h in rds-tools is not related with the kernel rds.h,
> the change in kernel rds.h does not affect rds-tools.
>
> This is the height of arrogance and shows a lack of understanding of
> what user ABI requirements are all about.
>
> It is possible for other userland components to be built by other
> people, outside of your controlled eco-system and tools, that use
> these interfaces.
>
> And you cannot control that.
>
> Therefore you cannot make arbitrary changes to UABI data strucures
> just because the tool you use and maintain is not effected by it.
>
> Please stop making these incredibly incompatible user interface
> changes in the RDS stack.
>
> I am, from this point forward, going to be extra strict on RDS stack
> changes especially in this area.
OK. It is up to you to decide to merge this commit or not.
Zhu Yanjun
>
>
^ permalink raw reply
* tx_fixup cdc_ether to mimic cdc_ncm tx behavior
From: Roee Kashi @ 2019-08-25 13:17 UTC (permalink / raw)
To: netdev
Hi,
I ported from Intel based modem chipset (cdc_ncm) to a Qualcomm's one
(cdc_ether), and encountered a major difference between the two.
cdc_ncm had a nice "feature" (which probably wasn't the original
purpose): when trying to transmit more than the module's capacity,
tx_fixup would return NULL skb, hence fd buffer would remain full,
causing sendto/select to block until modem is available.
It's quite useful when sending UDP datagrams through an LTE link for
example, since the module provides a dynamic and reliable information
in real-time regarding its *incapability* of sending the datagram.
For example:
If my LTE link max upload bandwidth is 30Mbps, and i'll try with
cdc_ncm to transmit above that, the send/select would block until
modem is available, so the actual bandwidth would be 30Mbps with ~0%
packet loss.
with cdc_ncm: `iperf -u -c xxx -b 60Mbps` would report a TX bandwidth
~30Mbps with ~0% loss.
with cdc_ether, even though the modem is unable to transmit the
packet, nothing holds the tx flow: select continue and return fd as
available for tx, even though the modem's buffer is full.
with cdc_ether: `iperf -u -c xxx -b 60Mbps` would report a TX
bandwidth ~60Mbps with ~50% loss.
the difference between cdc_ncm and cdc_ether for this matter, is the
'cdc_ncm_tx_fixup' in cdc_ncm, documented as:
/*
* The Ethernet API we are using does not support transmitting
* multiple Ethernet frames in a single call. This driver will
* accumulate multiple Ethernet frames and send out a larger
* USB frame when the USB buffer is full or when a single jiffies
* timeout happens.
*/
This fixup adds this useful side-effect to cdc_ncm, and I wonder how
to extend this specific behavior to cdc_ether as well, per flag.
What exactly in cdc_ncm: cdc_ncm_fill_tx_frame, causing this behavior,
and what is the community approach about adopting the described
cdc_ncm behavior?
(qmi_wwan behaves the same as cdc_ether)
Cheers,
Roee.
^ permalink raw reply
* Re: [PATCH net-next v2 0/3] net: dsa: mt7530: Convert to PHYLINK and add support for port 5
From: René van Dorst @ 2019-08-25 13:15 UTC (permalink / raw)
To: Russell King - ARM Linux admin
Cc: Sean Wang, Andrew Lunn, Vivien Didelot, Florian Fainelli,
David S . Miller, Matthias Brugger, Frank Wunderlich, netdev,
linux-mips, linux-mediatek, John Crispin, linux-arm-kernel
In-Reply-To: <20190824222935.GG13294@shell.armlinux.org.uk>
Hi Russell,
Quoting Russell King - ARM Linux admin <linux@armlinux.org.uk>:
> On Wed, Aug 21, 2019 at 04:45:44PM +0200, René van Dorst wrote:
>> 1. net: dsa: mt7530: Convert to PHYLINK API
>> This patch converts mt7530 to PHYLINK API.
>> 2. dt-bindings: net: dsa: mt7530: Add support for port 5
>> 3. net: dsa: mt7530: Add support for port 5
>> These 2 patches adding support for port 5 of the switch.
>>
>> v1->v2:
>> * Mostly phylink improvements after review.
>> rfc -> v1:
>> * Mostly phylink improvements after review.
>> * Drop phy isolation patches. Adds no value for now.
>> René van Dorst (3):
>> net: dsa: mt7530: Convert to PHYLINK API
>> dt-bindings: net: dsa: mt7530: Add support for port 5
>> net: dsa: mt7530: Add support for port 5
>>
>> .../devicetree/bindings/net/dsa/mt7530.txt | 218 ++++++++++
>> drivers/net/dsa/mt7530.c | 371 +++++++++++++++---
>> drivers/net/dsa/mt7530.h | 61 ++-
>> 3 files changed, 577 insertions(+), 73 deletions(-)
>
> Having looked through this set of patches, I don't see anything
> from the phylink point of view that concerns me. So, for the
> series from the phylink perspective:
>
> Acked-by: Russell King <rmk+kernel@armlinux.org.uk>
Thanks and thanks for reviewing.
Greats,
René
>
> Thanks.
>
> I did notice a dev_info() in patch 3 that you may like to consider
> whether they should be printed at info level or debug level. You
> may keep my ack on the patch when fixing that.
>
> I haven't considered whether the patch passes davem's style
> requirements for networking code; what I spotted did look like
> the declarations were upside-down christmas tree.
>
> --
> 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
* Re: [PATCH net-next v2 3/3] net: dsa: mt7530: Add support for port 5
From: René van Dorst @ 2019-08-25 12:48 UTC (permalink / raw)
To: David Miller
Cc: sean.wang, andrew, vivien.didelot, f.fainelli, matthias.bgg,
netdev, linux-arm-kernel, linux-mediatek, john, linux-mips,
frank-w
In-Reply-To: <20190824.161912.1377369658338940538.davem@davemloft.net>
Hi David,
Quoting David Miller <davem@davemloft.net>:
> From: René van Dorst <opensource@vdorst.com>
> Date: Wed, 21 Aug 2019 16:45:47 +0200
>
>> + dev_info(ds->dev, "Setup P5, HWTRAP=0x%x, intf_sel=%s, phy-mode=%s\n",
>> + val, p5_intf_modes(priv->p5_intf_sel), phy_modes(interface));
>
> This is debugging, at best. Please make this a debugging message or
> remove it entirely.
I change it to a debug message.
If there is nothing else I send a new version with this change also
add the tags ack-by Russell King and tested-by Frank Wunderlich.
Greats,
René
^ permalink raw reply
* Re: [PATCH net-next v3 2/3] net: ethernet: mediatek: Re-add support SGMII
From: René van Dorst @ 2019-08-25 11:41 UTC (permalink / raw)
To: Russell King - ARM Linux admin
Cc: John Crispin, Sean Wang, Nelson Chang, David S . Miller,
Matthias Brugger, netdev, linux-arm-kernel, linux-mediatek,
linux-mips, Frank Wunderlich, Stefan Roese
In-Reply-To: <20190824133225.GE13294@shell.armlinux.org.uk>
Hi Russell,
Quoting Russell King - ARM Linux admin <linux@armlinux.org.uk>:
> Hi René,
>
> On Sat, Aug 24, 2019 at 01:11:17PM +0000, René van Dorst wrote:
>> Hi Russell,
>>
>> Mediatek calls it Turbo RGMII. It is a overclock version of RGMII mode.
>> It is used between first GMAC and port 6 of the mt7530 switch. Can be used
>> with
>> an internal and an external mt7530 switch.
>>
>> TRGMII speed are:
>> * mt7621: 1200Mbit
>> * mt7623: 2000Mbit and 2600Mbit.
>>
>> I think that TRGMII is only used in a fixed-link situation in combination
>> with a
>> mt7530 switch and running and maximum speed/full duplex. So reporting
>> 1000baseT_Full seems to me the right option.
>
> I think we can ignore this one for the purposes of merging this patch
> set, since this seems to be specific to this setup. Neither 1000BaseT
> nor 1000BaseX fit very well, but we have to choose something.
>
>> PHY_INTERFACE_MODE_GMII:
>> 10baseT_Half
>> 10baseT_Full
>> 100baseT_Half
>> 100baseT_Full
>> 1000baseT_Half
>> 1000baseT_Full
>
> I think GMII can be connected to a PHY that can convert to 1000BaseX, so
> should probably include that here too.
>
Thanks for reviewing.
I shall add that too.
I send v4 today.
Greats,
René
> Thanks.
>
> --
> 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
* Re: [PATCH 1/3] net: Add HW_BRIDGE offload feature
From: Horatiu Vultur @ 2019-08-25 10:44 UTC (permalink / raw)
To: Florian Fainelli
Cc: Andrew Lunn, roopa, nikolay, davem, UNGLinuxDriver,
alexandre.belloni, allan.nielsen, netdev, linux-kernel, bridge
In-Reply-To: <afde1b82-2e4c-5b93-ff31-83cb80a0f7bd@gmail.com>
The 08/23/2019 16:30, Florian Fainelli wrote:
> External E-Mail
>
>
> On 8/23/19 5:39 AM, Horatiu Vultur wrote:
> > The 08/22/2019 22:08, Andrew Lunn wrote:
> >> External E-Mail
> >>
> >>
> >>> +/* Determin if the SW bridge can be offloaded to HW. Return true if all
> >>> + * the interfaces of the bridge have the feature NETIF_F_HW_SWITCHDEV set
> >>> + * and have the same netdev_ops.
> >>> + */
> >>
> >> Hi Horatiu
> >>
> >> Why do you need these restrictions. The HW bridge should be able to
> >> learn that a destination MAC address can be reached via the SW
> >> bridge. The software bridge can then forward it out the correct
> >> interface.
> >>
> >> Or are you saying your hardware cannot learn from frames which come
> >> from the CPU?
> >>
> >> Andrew
> >>
> > Hi Andrew,
> >
> > I do not believe that our HW can learn from frames which comes from the
> > CPU, at least not in the way they are injected today. But in case of Ocelot
> > (and the next chip we are working on), we have other issues in mixing with
> > foreign interfaces which is why we have the check in
> > ocelot_netdevice_dev_check.
> >
> > More important, as we responded to Nikolay, we properly introduced this
> > restriction for the wrong reasons.
> >
> > In SW bridge I will remove all these restrictions and only set ports in
> > promisc mode only if NETIF_F_HW_BRIDGE is not set.
> > Then in the network driver I can see if a foreign interface is added to
> > the bridge, and when that happens I can set the port in promisc mode.
> > Then the frames will be flooded to the SW bridge which eventually will
> > send to the foreign interface.
>
> Is that really necessary?
From what I see, it seems to be necessary.
> Is not the skb->fwd_offload_mark as well as
> the phys_switch_id supposed to tell that information to the bridge already?
Yes, the bridge is using the fwd_offload_mark to know that it should or
should not forward the frame. But in case that the network driver knows
that the SW bridge will not do anything with the frame, then there is no
point to send the frame to SW bridge just to use CPU cycles for dropping
the frame.
> --
> Florian
--
/Horatiu
^ permalink raw reply
* Re: Regresion with dsa_port_disable
From: Marek Behun @ 2019-08-25 8:35 UTC (permalink / raw)
To: Vivien Didelot; +Cc: Andrew Lunn, netdev
In-Reply-To: <20190824205349.GB27859@t480s.localdomain>
On Sat, 24 Aug 2019 20:53:49 -0400
Vivien Didelot <vivien.didelot@gmail.com> wrote:
> OK I think you meant info->ops->serdes_irq_free and
> info->ops->serdes_irq_setup, otherwise it's confusing.
>
> I think I know what's going on, I'll look into it soon.
Either dsa_port_setup is calling dsa_port_disable for
DSA_PORT_TYPE_UNUSED and this causes that, or, as line
Workqueue: events deferred_probe_work_func
suggests, probe is deferred, dsa_tree_setup calls
dsa_tree_teardown_switches, and thus dsa_port_disable is called.
We should add a check into dsa_port_disable if that port was successfuly
enabled, or something like that.
^ permalink raw reply
* Re: [PATCH net-next] MAINTAINERS: Add phylink keyword to SFF/SFP/SFP+ MODULE SUPPORT
From: Sergei Shtylyov @ 2019-08-25 8:07 UTC (permalink / raw)
To: Andrew Lunn, David Miller; +Cc: Russell King, netdev
In-Reply-To: <20190824223454.15932-1-andrew@lunn.ch>
Hello!
On 25.08.2019 1:34, Andrew Lunn wrote:
> Russell king
King, with capital K. :-)
> maintains phylink, as part of the SFP module support.
> However, much of the review work is about drivers swapping from phylib
> to phylink. Such changes don't make changes to the phylink core, and
> so the F: rules in MAINTAINERS don't match. Add a K:, keywork rule,
Keyword?
> which hopefully get_maintainers will match against for patches to MAC
> drivers swapping to phylink.
>
> Signed-off-by: Andrew Lunn <andrew@lunn.ch>
[...]
MBR, Sergei
^ permalink raw reply
* Re: [PATCH RFC net-next 0/3] Multi-CPU DSA support
From: Marek Behun @ 2019-08-25 7:13 UTC (permalink / raw)
To: Florian Fainelli
Cc: netdev, Andrew Lunn, Vivien Didelot, David Ahern,
Stephen Hemminger, Chris Healy, Vladimir Oltean
In-Reply-To: <a7fed8ab-60f3-a30c-5634-fd89e4daf44d@gmail.com>
On Sat, 24 Aug 2019 13:04:04 -0700
Florian Fainelli <f.fainelli@gmail.com> wrote:
> Now, the 4.9 kernel behavior actually works just fine because eth1 is
> not a special interface, so no tagging is expected, and "wifi", although
> it supports DSA tagging, represents another side of the CPU/host network
> stack, so you never have to inject frames into the switch, because you
> can use eth1 to do that and let MAC learning do its job to forward to
> the correct port of the switch.
Hi Florian,
Sorry, I am having trouble understanding what you mean in the
paragraph I quoted above (and paragraphs afterwards).
eth0 and eth1 are interfaces created by an ethernet driver.
wlan0 is an interface created by wireless driver.
wifi is a slave interface created by DSA for port 5 on the switch.
eth1 is DSA slave or a DSA master connected to port 5?
How does DSA handle two interfaces with same reg property?
Marek
^ permalink raw reply
* Re: [PATCH RFC net-next 0/3] Multi-CPU DSA support
From: Marek Behun @ 2019-08-25 4:19 UTC (permalink / raw)
To: Andrew Lunn
Cc: netdev, Vivien Didelot, Florian Fainelli, David Ahern,
Stephen Hemminger
In-Reply-To: <20190824152407.GA8251@lunn.ch>
On Sat, 24 Aug 2019 17:24:07 +0200
Andrew Lunn <andrew@lunn.ch> wrote:
> That is a new idea. Interesting.
>
> I would like to look around and see what else uses this "lan1@eth0"
> concept. We need to ensure it is not counter intuitive in general,
> when you consider all possible users.
There are not many users of ndo_get_iflink besides DSA slave:
ip6_gre, ip6_vti, sit, ip6_tunnel
ip_gte, ip_vti, ipmr, ipip,
macsec, macvlan, veth
ipvlan
ipoib
and a few other. What these have in common is that all these interfaces
are linked somehow to another interfacem, ie. a macvlan interface eth0.1
is linked to it's master interface eth0. All of these are virtual
interfaces.
Marek
^ permalink raw reply
* Re: [PATCH RFC net-next 0/3] Multi-CPU DSA support
From: Marek Behun @ 2019-08-25 4:08 UTC (permalink / raw)
To: Florian Fainelli
Cc: netdev, Andrew Lunn, Vivien Didelot, David Ahern,
Stephen Hemminger, Chris Healy, Vladimir Oltean
In-Reply-To: <20190824230121.35a3d59b@nic.cz>
On Sat, 24 Aug 2019 23:01:21 +0200
Marek Behun <marek.behun@nic.cz> wrote:
> the documentation would became weird to users.
... would become weird ...
>
> We are *already* using the iflink property to report which CPU device
> is used as CPU destination port for a given switch slave interface. So
> why to use that for changing this, also?
... why NOT to use that for chaning this also?
>
> If you think that iflink should not be used for this, and other agree,
... and others agree with you,
^ permalink raw reply
* [PATCH net-next v3 3/6] net: dsa: mv88e6xxx: create serdes_get_lane chip operation
From: Marek Behún @ 2019-08-25 3:59 UTC (permalink / raw)
To: netdev
Cc: Andrew Lunn, Vivien Didelot, Florian Fainelli, Vladimir Oltean,
Marek Behún
In-Reply-To: <20190825035915.13112-1-marek.behun@nic.cz>
Create a serdes_get_lane() method in the mv88e6xxx operations structure.
Use it instead of calling the different implementations.
Also change the methods so that their return value is used only for
error. The lane number is put into a place referred to by a pointer
given as argument. If the port does not have a lane, put -1 there.
Lanes are phy addresses, so use s8 as their type.
Signed-off-by: Marek Behún <marek.behun@nic.cz>
---
drivers/net/dsa/mv88e6xxx/chip.c | 6 ++
drivers/net/dsa/mv88e6xxx/chip.h | 3 +
drivers/net/dsa/mv88e6xxx/port.c | 14 ++--
drivers/net/dsa/mv88e6xxx/serdes.c | 130 +++++++++++++++--------------
drivers/net/dsa/mv88e6xxx/serdes.h | 20 ++++-
5 files changed, 99 insertions(+), 74 deletions(-)
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index ec4274d71145..5a3fff1971b9 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -3255,6 +3255,7 @@ static const struct mv88e6xxx_ops mv88e6190_ops = {
.vtu_getnext = mv88e6390_g1_vtu_getnext,
.vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
.serdes_power = mv88e6390_serdes_power,
+ .serdes_get_lane = mv88e6390_serdes_get_lane,
.serdes_irq_setup = mv88e6390_serdes_irq_setup,
.serdes_irq_free = mv88e6390_serdes_irq_free,
.gpio_ops = &mv88e6352_gpio_ops,
@@ -3301,6 +3302,7 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = {
.vtu_getnext = mv88e6390_g1_vtu_getnext,
.vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
.serdes_power = mv88e6390x_serdes_power,
+ .serdes_get_lane = mv88e6390x_serdes_get_lane,
.serdes_irq_setup = mv88e6390x_serdes_irq_setup,
.serdes_irq_free = mv88e6390x_serdes_irq_free,
.gpio_ops = &mv88e6352_gpio_ops,
@@ -3347,6 +3349,7 @@ static const struct mv88e6xxx_ops mv88e6191_ops = {
.vtu_getnext = mv88e6390_g1_vtu_getnext,
.vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
.serdes_power = mv88e6390_serdes_power,
+ .serdes_get_lane = mv88e6390_serdes_get_lane,
.serdes_irq_setup = mv88e6390_serdes_irq_setup,
.serdes_irq_free = mv88e6390_serdes_irq_free,
.avb_ops = &mv88e6390_avb_ops,
@@ -3483,6 +3486,7 @@ static const struct mv88e6xxx_ops mv88e6290_ops = {
.vtu_getnext = mv88e6390_g1_vtu_getnext,
.vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
.serdes_power = mv88e6390_serdes_power,
+ .serdes_get_lane = mv88e6390_serdes_get_lane,
.serdes_irq_setup = mv88e6390_serdes_irq_setup,
.serdes_irq_free = mv88e6390_serdes_irq_free,
.gpio_ops = &mv88e6352_gpio_ops,
@@ -3800,6 +3804,7 @@ static const struct mv88e6xxx_ops mv88e6390_ops = {
.vtu_getnext = mv88e6390_g1_vtu_getnext,
.vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
.serdes_power = mv88e6390_serdes_power,
+ .serdes_get_lane = mv88e6390_serdes_get_lane,
.serdes_irq_setup = mv88e6390_serdes_irq_setup,
.serdes_irq_free = mv88e6390_serdes_irq_free,
.gpio_ops = &mv88e6352_gpio_ops,
@@ -3850,6 +3855,7 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = {
.vtu_getnext = mv88e6390_g1_vtu_getnext,
.vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
.serdes_power = mv88e6390x_serdes_power,
+ .serdes_get_lane = mv88e6390x_serdes_get_lane,
.serdes_irq_setup = mv88e6390x_serdes_irq_setup,
.serdes_irq_free = mv88e6390x_serdes_irq_free,
.gpio_ops = &mv88e6352_gpio_ops,
diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
index a406be2f5652..15d0c9f00f54 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.h
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
@@ -443,6 +443,9 @@ struct mv88e6xxx_ops {
/* Power on/off a SERDES interface */
int (*serdes_power)(struct mv88e6xxx_chip *chip, int port, bool on);
+ /* SERDES lane mapping */
+ int (*serdes_get_lane)(struct mv88e6xxx_chip *chip, int port, s8 *lane);
+
/* SERDES interrupt handling */
int (*serdes_irq_setup)(struct mv88e6xxx_chip *chip, int port);
void (*serdes_irq_free)(struct mv88e6xxx_chip *chip, int port);
diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c
index c95cdb73e5a2..6a1fa5c72fdb 100644
--- a/drivers/net/dsa/mv88e6xxx/port.c
+++ b/drivers/net/dsa/mv88e6xxx/port.c
@@ -395,7 +395,7 @@ phy_interface_t mv88e6390x_port_max_speed_mode(int port)
int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
phy_interface_t mode)
{
- int lane;
+ s8 lane;
u16 cmode;
u16 reg;
int err;
@@ -434,9 +434,9 @@ int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
if (cmode == chip->ports[port].cmode)
return 0;
- lane = mv88e6390x_serdes_get_lane(chip, port);
- if (lane < 0 && lane != -ENODEV)
- return lane;
+ err = mv88e6xxx_serdes_get_lane(chip, port, &lane);
+ if (err)
+ return err;
if (lane >= 0) {
if (chip->ports[port].serdes_irq) {
@@ -466,9 +466,9 @@ int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
chip->ports[port].cmode = cmode;
- lane = mv88e6390x_serdes_get_lane(chip, port);
- if (lane < 0)
- return lane;
+ err = mv88e6xxx_serdes_get_lane(chip, port, &lane);
+ if (err)
+ return err;
err = mv88e6390x_serdes_power(chip, port, true);
if (err)
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c
index 678aaba3d019..a9209465e06b 100644
--- a/drivers/net/dsa/mv88e6xxx/serdes.c
+++ b/drivers/net/dsa/mv88e6xxx/serdes.c
@@ -286,36 +286,33 @@ void mv88e6352_serdes_irq_free(struct mv88e6xxx_chip *chip, int port)
chip->ports[port].serdes_irq = 0;
}
-/* Return the SERDES lane address a port is using. Only Ports 9 and 10
- * have SERDES lanes. Returns -ENODEV if a port does not have a lane.
- */
-static int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
+int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port, s8 *lane)
{
u8 cmode = chip->ports[port].cmode;
+ *lane = -1;
+
switch (port) {
case 9:
if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
- return MV88E6390_PORT9_LANE0;
- return -ENODEV;
+ *lane = MV88E6390_PORT9_LANE0;
+ break;
case 10:
if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
- return MV88E6390_PORT10_LANE0;
- return -ENODEV;
+ *lane = MV88E6390_PORT10_LANE0;
+ break;
default:
- return -ENODEV;
+ break;
}
+
+ return *lane == -1 ? -ENODEV : 0;
}
-/* Return the SERDES lane address a port is using. Ports 9 and 10 can
- * use multiple lanes. If so, return the first lane the port uses.
- * Returns -ENODEV if a port does not have a lane.
- */
-int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
+int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port, s8 *lane)
{
u8 cmode_port9, cmode_port10, cmode_port;
@@ -323,76 +320,80 @@ int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
cmode_port10 = chip->ports[10].cmode;
cmode_port = chip->ports[port].cmode;
+ *lane = -1;
+
switch (port) {
case 2:
if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X)
- return MV88E6390_PORT9_LANE1;
- return -ENODEV;
+ *lane = MV88E6390_PORT9_LANE1;
+ break;
case 3:
if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X)
- return MV88E6390_PORT9_LANE2;
- return -ENODEV;
+ *lane = MV88E6390_PORT9_LANE2;
+ break;
case 4:
if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X)
- return MV88E6390_PORT9_LANE3;
- return -ENODEV;
+ *lane = MV88E6390_PORT9_LANE3;
+ break;
case 5:
if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X)
- return MV88E6390_PORT10_LANE1;
- return -ENODEV;
+ *lane = MV88E6390_PORT10_LANE1;
+ break;
case 6:
if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X)
- return MV88E6390_PORT10_LANE2;
- return -ENODEV;
+ *lane = MV88E6390_PORT10_LANE2;
+ break;
case 7:
if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X)
- return MV88E6390_PORT10_LANE3;
- return -ENODEV;
+ *lane = MV88E6390_PORT10_LANE3;
+ break;
case 9:
if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
cmode_port9 == MV88E6XXX_PORT_STS_CMODE_XAUI ||
cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
- return MV88E6390_PORT9_LANE0;
- return -ENODEV;
+ *lane = MV88E6390_PORT9_LANE0;
+ break;
case 10:
if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
cmode_port10 == MV88E6XXX_PORT_STS_CMODE_XAUI ||
cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
- return MV88E6390_PORT10_LANE0;
- return -ENODEV;
+ *lane = MV88E6390_PORT10_LANE0;
+ break;
default:
- return -ENODEV;
+ break;
}
+
+ return *lane == -1 ? -ENODEV : 0;
}
/* Set the power on/off for 10GBASE-R and 10GBASE-X4/X2 */
-static int mv88e6390_serdes_power_10g(struct mv88e6xxx_chip *chip, int lane,
+static int mv88e6390_serdes_power_10g(struct mv88e6xxx_chip *chip, s8 lane,
bool on)
{
u16 val, new_val;
@@ -419,7 +420,7 @@ static int mv88e6390_serdes_power_10g(struct mv88e6xxx_chip *chip, int lane,
}
/* Set the power on/off for SGMII and 1000Base-X */
-static int mv88e6390_serdes_power_sgmii(struct mv88e6xxx_chip *chip, int lane,
+static int mv88e6390_serdes_power_sgmii(struct mv88e6xxx_chip *chip, s8 lane,
bool on)
{
u16 val, new_val;
@@ -445,7 +446,7 @@ static int mv88e6390_serdes_power_sgmii(struct mv88e6xxx_chip *chip, int lane,
}
static int mv88e6390_serdes_power_lane(struct mv88e6xxx_chip *chip, int port,
- int lane, bool on)
+ s8 lane, bool on)
{
u8 cmode = chip->ports[port].cmode;
@@ -464,14 +465,14 @@ static int mv88e6390_serdes_power_lane(struct mv88e6xxx_chip *chip, int port,
int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
{
- int lane;
-
- lane = mv88e6390_serdes_get_lane(chip, port);
- if (lane == -ENODEV)
- return 0;
+ s8 lane;
+ int err;
+ err = mv88e6xxx_serdes_get_lane(chip, port, &lane);
+ if (err)
+ return err;
if (lane < 0)
- return lane;
+ return 0;
switch (port) {
case 9 ... 10:
@@ -483,14 +484,14 @@ int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
int mv88e6390x_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
{
- int lane;
-
- lane = mv88e6390x_serdes_get_lane(chip, port);
- if (lane == -ENODEV)
- return 0;
+ s8 lane;
+ int err;
+ err = mv88e6xxx_serdes_get_lane(chip, port, &lane);
+ if (err)
+ return err;
if (lane < 0)
- return lane;
+ return 0;
switch (port) {
case 2 ... 4:
@@ -503,7 +504,7 @@ int mv88e6390x_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
}
static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip,
- int port, int lane)
+ int port, s8 lane)
{
u8 cmode = chip->ports[port].cmode;
struct dsa_switch *ds = chip->ds;
@@ -570,7 +571,7 @@ static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip,
}
static int mv88e6390_serdes_irq_enable_sgmii(struct mv88e6xxx_chip *chip,
- int lane)
+ s8 lane)
{
return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
MV88E6390_SGMII_INT_ENABLE,
@@ -579,14 +580,14 @@ static int mv88e6390_serdes_irq_enable_sgmii(struct mv88e6xxx_chip *chip,
}
static int mv88e6390_serdes_irq_disable_sgmii(struct mv88e6xxx_chip *chip,
- int lane)
+ s8 lane)
{
return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
MV88E6390_SGMII_INT_ENABLE, 0);
}
int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port,
- int lane)
+ s8 lane)
{
u8 cmode = chip->ports[port].cmode;
int err = 0;
@@ -602,7 +603,7 @@ int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port,
}
int mv88e6390_serdes_irq_disable(struct mv88e6xxx_chip *chip, int port,
- int lane)
+ s8 lane)
{
u8 cmode = chip->ports[port].cmode;
int err = 0;
@@ -618,7 +619,7 @@ int mv88e6390_serdes_irq_disable(struct mv88e6xxx_chip *chip, int port,
}
static int mv88e6390_serdes_irq_status_sgmii(struct mv88e6xxx_chip *chip,
- int lane, u16 *status)
+ s8 lane, u16 *status)
{
int err;
@@ -635,10 +636,10 @@ static irqreturn_t mv88e6390_serdes_thread_fn(int irq, void *dev_id)
irqreturn_t ret = IRQ_NONE;
u8 cmode = port->cmode;
u16 status;
- int lane;
int err;
+ s8 lane;
- lane = mv88e6390x_serdes_get_lane(chip, port->port);
+ mv88e6xxx_serdes_get_lane(chip, port->port, &lane);
mv88e6xxx_reg_lock(chip);
@@ -663,16 +664,14 @@ static irqreturn_t mv88e6390_serdes_thread_fn(int irq, void *dev_id)
int mv88e6390x_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port)
{
- int lane;
int err;
+ s8 lane;
- lane = mv88e6390x_serdes_get_lane(chip, port);
-
- if (lane == -ENODEV)
- return 0;
-
+ err = mv88e6xxx_serdes_get_lane(chip, port, &lane);
+ if (err)
+ return err;
if (lane < 0)
- return lane;
+ return 0;
chip->ports[port].serdes_irq = irq_find_mapping(chip->g2_irq.domain,
port);
@@ -711,11 +710,14 @@ int mv88e6390_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port)
void mv88e6390x_serdes_irq_free(struct mv88e6xxx_chip *chip, int port)
{
- int lane = mv88e6390x_serdes_get_lane(chip, port);
+ int err;
+ s8 lane;
- if (lane == -ENODEV)
+ err = mv88e6xxx_serdes_get_lane(chip, port, &lane);
+ if (err) {
+ dev_err(chip->dev, "Unable to free SERDES irq: %d\n", err);
return;
-
+ }
if (lane < 0)
return;
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.h b/drivers/net/dsa/mv88e6xxx/serdes.h
index ff5b94439335..1ddb8fb3aab9 100644
--- a/drivers/net/dsa/mv88e6xxx/serdes.h
+++ b/drivers/net/dsa/mv88e6xxx/serdes.h
@@ -74,7 +74,21 @@
#define MV88E6390_SGMII_PHY_STATUS_SPD_DPL_VALID BIT(11)
#define MV88E6390_SGMII_PHY_STATUS_LINK BIT(10)
-int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port);
+/* Put the SERDES lane address a port is using into *lane. If a port has
+ * multiple lanes, should put the first lane the port is using. If a port does
+ * not have a lane, put -1 into *lane.
+ */
+static inline int mv88e6xxx_serdes_get_lane(struct mv88e6xxx_chip *chip,
+ int port, s8 *lane)
+{
+ if (!chip->info->ops->serdes_get_lane)
+ return -EOPNOTSUPP;
+
+ return chip->info->ops->serdes_get_lane(chip, port, lane);
+}
+
+int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port, s8 *lane);
+int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port, s8 *lane);
int mv88e6341_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on);
int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on);
int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on);
@@ -89,9 +103,9 @@ int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip,
int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
uint64_t *data);
int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port,
- int lane);
+ s8 lane);
int mv88e6390_serdes_irq_disable(struct mv88e6xxx_chip *chip, int port,
- int lane);
+ s8 lane);
int mv88e6352_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port);
void mv88e6352_serdes_irq_free(struct mv88e6xxx_chip *chip, int port);
--
2.21.0
^ permalink raw reply related
* [PATCH net-next v3 6/6] net: dsa: mv88e6xxx: fully support SERDES on Topaz family
From: Marek Behún @ 2019-08-25 3:59 UTC (permalink / raw)
To: netdev
Cc: Andrew Lunn, Vivien Didelot, Florian Fainelli, Vladimir Oltean,
Marek Behún
In-Reply-To: <20190825035915.13112-1-marek.behun@nic.cz>
Currently we support SERDES on the Topaz family in a limited way: no
IRQs and the cmode is not writable, thus the mode is determined by
strapping pins.
Marvell's examples though show how to make cmode writable on port 5 and
support SGMII autonegotiation. It is done by writing hidden registers,
for which we already have code.
This patch adds support for making the cmode for the SERDES port
writable on the Topaz family, and enables cmode setting and SERDES IRQs.
Tested on Turris Mox.
Signed-off-by: Marek Behún <marek.behun@nic.cz>
---
drivers/net/dsa/mv88e6xxx/chip.c | 6 +++
drivers/net/dsa/mv88e6xxx/port.c | 76 +++++++++++++++++++++++++-------
drivers/net/dsa/mv88e6xxx/port.h | 4 ++
3 files changed, 71 insertions(+), 15 deletions(-)
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 202ccce65b1c..6525075f6bd3 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -2913,6 +2913,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_set_cmode = mv88e6341_port_set_cmode,
.port_setup_message_port = mv88e6xxx_setup_message_port,
.stats_snapshot = mv88e6390_g1_stats_snapshot,
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
@@ -2929,6 +2930,8 @@ static const struct mv88e6xxx_ops mv88e6141_ops = {
.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
.serdes_power = mv88e6390_serdes_power,
.serdes_get_lane = mv88e6341_serdes_get_lane,
+ .serdes_irq_setup = mv88e6390_serdes_irq_setup,
+ .serdes_irq_free = mv88e6390_serdes_irq_free,
.gpio_ops = &mv88e6352_gpio_ops,
.phylink_validate = mv88e6341_phylink_validate,
};
@@ -3608,6 +3611,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_set_cmode = mv88e6341_port_set_cmode,
.port_setup_message_port = mv88e6xxx_setup_message_port,
.stats_snapshot = mv88e6390_g1_stats_snapshot,
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
@@ -3624,6 +3628,8 @@ static const struct mv88e6xxx_ops mv88e6341_ops = {
.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
.serdes_power = mv88e6390_serdes_power,
.serdes_get_lane = mv88e6341_serdes_get_lane,
+ .serdes_irq_setup = mv88e6390_serdes_irq_setup,
+ .serdes_irq_free = mv88e6390_serdes_irq_free,
.gpio_ops = &mv88e6352_gpio_ops,
.avb_ops = &mv88e6390_avb_ops,
.ptp_ops = &mv88e6352_ptp_ops,
diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c
index 7183c94a92ec..908b95434b4d 100644
--- a/drivers/net/dsa/mv88e6xxx/port.c
+++ b/drivers/net/dsa/mv88e6xxx/port.c
@@ -392,17 +392,37 @@ phy_interface_t mv88e6390x_port_max_speed_mode(int port)
return PHY_INTERFACE_MODE_NA;
}
-int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
- phy_interface_t mode)
+static int mv88e6341_port_force_writable_cmode(struct mv88e6xxx_chip *chip,
+ int port)
+{
+ int err, addr;
+ u16 reg, bits;
+
+ addr = chip->info->port_base_addr + port;
+
+ err = mv88e6xxx_port_hidden_read(chip, 0x7, addr, 0, ®);
+ if (err)
+ return err;
+
+ bits = MV88E6341_PORT_RESERVED_1A_FORCE_CMODE |
+ MV88E6341_PORT_RESERVED_1A_SGMII_AN;
+
+ if ((reg & bits) == bits)
+ return 0;
+
+ reg |= bits;
+ return mv88e6xxx_port_hidden_write(chip, 0x7, addr, 0, reg);
+}
+
+static int mv88e6xxx_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
+ phy_interface_t mode, bool allow_over_2500,
+ bool make_cmode_writable)
{
s8 lane;
u16 cmode;
u16 reg;
int err;
- if (port != 9 && port != 10)
- return -EOPNOTSUPP;
-
/* Default to a slow mode, so freeing up SERDES interfaces for
* other ports which might use them for SFPs.
*/
@@ -421,9 +441,13 @@ int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
break;
case PHY_INTERFACE_MODE_XGMII:
case PHY_INTERFACE_MODE_XAUI:
+ if (!allow_over_2500)
+ return -EINVAL;
cmode = MV88E6XXX_PORT_STS_CMODE_XAUI;
break;
case PHY_INTERFACE_MODE_RXAUI:
+ if (!allow_over_2500)
+ return -EINVAL;
cmode = MV88E6XXX_PORT_STS_CMODE_RXAUI;
break;
default:
@@ -457,6 +481,12 @@ int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
if (err)
return err;
+ if (make_cmode_writable) {
+ err = mv88e6341_port_force_writable_cmode(chip, port);
+ if (err)
+ return err;
+ }
+
reg &= ~MV88E6XXX_PORT_STS_CMODE_MASK;
reg |= cmode;
@@ -484,21 +514,37 @@ int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
return 0;
}
+int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
+ phy_interface_t mode)
+{
+ if (port != 9 && port != 10)
+ return -EOPNOTSUPP;
+
+ return mv88e6xxx_port_set_cmode(chip, port, mode, true, false);
+}
+
int mv88e6390_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
phy_interface_t mode)
{
- switch (mode) {
- case PHY_INTERFACE_MODE_NA:
+ if (port != 9 && port != 10)
+ return -EOPNOTSUPP;
+
+ if (mode == PHY_INTERFACE_MODE_NA)
+ return 0;
+
+ return mv88e6xxx_port_set_cmode(chip, port, mode, false, false);
+}
+
+int mv88e6341_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
+ phy_interface_t mode)
+{
+ if (port != 5)
+ return -EOPNOTSUPP;
+
+ if (mode == PHY_INTERFACE_MODE_NA)
return 0;
- case PHY_INTERFACE_MODE_XGMII:
- case PHY_INTERFACE_MODE_XAUI:
- case PHY_INTERFACE_MODE_RXAUI:
- return -EINVAL;
- default:
- break;
- }
- return mv88e6390x_port_set_cmode(chip, port, mode);
+ return mv88e6xxx_port_set_cmode(chip, port, mode, false, true);
}
int mv88e6185_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode)
diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h
index 04550cb3c3b3..4b7289a1fd8b 100644
--- a/drivers/net/dsa/mv88e6xxx/port.h
+++ b/drivers/net/dsa/mv88e6xxx/port.h
@@ -269,6 +269,8 @@
#define MV88E6XXX_PORT_RESERVED_1A_BLOCK_SHIFT 10
#define MV88E6XXX_PORT_RESERVED_1A_CTRL_PORT 0x04
#define MV88E6XXX_PORT_RESERVED_1A_DATA_PORT 0x05
+#define MV88E6341_PORT_RESERVED_1A_FORCE_CMODE 0x8000
+#define MV88E6341_PORT_RESERVED_1A_SGMII_AN 0x2000
int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port, int reg,
u16 *val);
@@ -334,6 +336,8 @@ int mv88e6097_port_pause_limit(struct mv88e6xxx_chip *chip, int port, u8 in,
u8 out);
int mv88e6390_port_pause_limit(struct mv88e6xxx_chip *chip, int port, u8 in,
u8 out);
+int mv88e6341_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
+ phy_interface_t mode);
int mv88e6390_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
phy_interface_t mode);
int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
--
2.21.0
^ permalink raw reply related
* [PATCH net-next v3 4/6] net: dsa: mv88e6xxx: simplify SERDES code for Topaz and Peridot
From: Marek Behún @ 2019-08-25 3:59 UTC (permalink / raw)
To: netdev
Cc: Andrew Lunn, Vivien Didelot, Florian Fainelli, Vladimir Oltean,
Marek Behún
In-Reply-To: <20190825035915.13112-1-marek.behun@nic.cz>
By adding an additional serdes_get_lane implementation (for Topaz), we
can merge the implementations of other SERDES functions (powering and
IRQs). We can skip checking port numbers, since the serdes_get_lane()
methods inform if there is no lane on a port or if the lane cannot be
used for given cmode.
Signed-off-by: Marek Behún <marek.behun@nic.cz>
---
drivers/net/dsa/mv88e6xxx/chip.c | 18 ++---
drivers/net/dsa/mv88e6xxx/port.c | 4 +-
drivers/net/dsa/mv88e6xxx/serdes.c | 104 ++++++++---------------------
drivers/net/dsa/mv88e6xxx/serdes.h | 7 +-
4 files changed, 42 insertions(+), 91 deletions(-)
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 5a3fff1971b9..202ccce65b1c 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -2927,7 +2927,8 @@ static const struct mv88e6xxx_ops mv88e6141_ops = {
.reset = mv88e6352_g1_reset,
.vtu_getnext = mv88e6352_g1_vtu_getnext,
.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
- .serdes_power = mv88e6341_serdes_power,
+ .serdes_power = mv88e6390_serdes_power,
+ .serdes_get_lane = mv88e6341_serdes_get_lane,
.gpio_ops = &mv88e6352_gpio_ops,
.phylink_validate = mv88e6341_phylink_validate,
};
@@ -3301,10 +3302,10 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = {
.rmu_disable = mv88e6390_g1_rmu_disable,
.vtu_getnext = mv88e6390_g1_vtu_getnext,
.vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
- .serdes_power = mv88e6390x_serdes_power,
+ .serdes_power = mv88e6390_serdes_power,
.serdes_get_lane = mv88e6390x_serdes_get_lane,
- .serdes_irq_setup = mv88e6390x_serdes_irq_setup,
- .serdes_irq_free = mv88e6390x_serdes_irq_free,
+ .serdes_irq_setup = mv88e6390_serdes_irq_setup,
+ .serdes_irq_free = mv88e6390_serdes_irq_free,
.gpio_ops = &mv88e6352_gpio_ops,
.phylink_validate = mv88e6390x_phylink_validate,
};
@@ -3621,7 +3622,8 @@ static const struct mv88e6xxx_ops mv88e6341_ops = {
.reset = mv88e6352_g1_reset,
.vtu_getnext = mv88e6352_g1_vtu_getnext,
.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
- .serdes_power = mv88e6341_serdes_power,
+ .serdes_power = mv88e6390_serdes_power,
+ .serdes_get_lane = mv88e6341_serdes_get_lane,
.gpio_ops = &mv88e6352_gpio_ops,
.avb_ops = &mv88e6390_avb_ops,
.ptp_ops = &mv88e6352_ptp_ops,
@@ -3854,10 +3856,10 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = {
.rmu_disable = mv88e6390_g1_rmu_disable,
.vtu_getnext = mv88e6390_g1_vtu_getnext,
.vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
- .serdes_power = mv88e6390x_serdes_power,
+ .serdes_power = mv88e6390_serdes_power,
.serdes_get_lane = mv88e6390x_serdes_get_lane,
- .serdes_irq_setup = mv88e6390x_serdes_irq_setup,
- .serdes_irq_free = mv88e6390x_serdes_irq_free,
+ .serdes_irq_setup = mv88e6390_serdes_irq_setup,
+ .serdes_irq_free = mv88e6390_serdes_irq_free,
.gpio_ops = &mv88e6352_gpio_ops,
.avb_ops = &mv88e6390_avb_ops,
.ptp_ops = &mv88e6352_ptp_ops,
diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c
index 6a1fa5c72fdb..d20be5327640 100644
--- a/drivers/net/dsa/mv88e6xxx/port.c
+++ b/drivers/net/dsa/mv88e6xxx/port.c
@@ -445,7 +445,7 @@ int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
return err;
}
- err = mv88e6390x_serdes_power(chip, port, false);
+ err = mv88e6390_serdes_power(chip, port, false);
if (err)
return err;
}
@@ -470,7 +470,7 @@ int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
if (err)
return err;
- err = mv88e6390x_serdes_power(chip, port, true);
+ err = mv88e6390_serdes_power(chip, port, true);
if (err)
return err;
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c
index a9209465e06b..1946ccb6694c 100644
--- a/drivers/net/dsa/mv88e6xxx/serdes.c
+++ b/drivers/net/dsa/mv88e6xxx/serdes.c
@@ -286,6 +286,23 @@ void mv88e6352_serdes_irq_free(struct mv88e6xxx_chip *chip, int port)
chip->ports[port].serdes_irq = 0;
}
+int mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port, s8 *lane)
+{
+ u8 cmode = chip->ports[port].cmode;
+
+ *lane = -1;
+
+ if (port != 5)
+ return 0;
+
+ if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
+ cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
+ cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
+ *lane = MV88E6341_PORT5_LANE;
+
+ return 0;
+}
+
int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port, s8 *lane)
{
u8 cmode = chip->ports[port].cmode;
@@ -445,26 +462,9 @@ static int mv88e6390_serdes_power_sgmii(struct mv88e6xxx_chip *chip, s8 lane,
return err;
}
-static int mv88e6390_serdes_power_lane(struct mv88e6xxx_chip *chip, int port,
- s8 lane, bool on)
-{
- u8 cmode = chip->ports[port].cmode;
-
- switch (cmode) {
- case MV88E6XXX_PORT_STS_CMODE_SGMII:
- case MV88E6XXX_PORT_STS_CMODE_1000BASE_X:
- case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
- return mv88e6390_serdes_power_sgmii(chip, lane, on);
- case MV88E6XXX_PORT_STS_CMODE_XAUI:
- case MV88E6XXX_PORT_STS_CMODE_RXAUI:
- return mv88e6390_serdes_power_10g(chip, lane, on);
- }
-
- return 0;
-}
-
int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
{
+ u8 cmode = chip->ports[port].cmode;
s8 lane;
int err;
@@ -474,30 +474,14 @@ int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
if (lane < 0)
return 0;
- switch (port) {
- case 9 ... 10:
- return mv88e6390_serdes_power_lane(chip, port, lane, on);
- }
-
- return 0;
-}
-
-int mv88e6390x_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
-{
- s8 lane;
- int err;
-
- err = mv88e6xxx_serdes_get_lane(chip, port, &lane);
- if (err)
- return err;
- if (lane < 0)
- return 0;
-
- switch (port) {
- case 2 ... 4:
- case 5 ... 7:
- case 9 ... 10:
- return mv88e6390_serdes_power_lane(chip, port, lane, on);
+ switch (cmode) {
+ case MV88E6XXX_PORT_STS_CMODE_SGMII:
+ case MV88E6XXX_PORT_STS_CMODE_1000BASE_X:
+ case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
+ return mv88e6390_serdes_power_sgmii(chip, lane, on);
+ case MV88E6XXX_PORT_STS_CMODE_XAUI:
+ case MV88E6XXX_PORT_STS_CMODE_RXAUI:
+ return mv88e6390_serdes_power_10g(chip, lane, on);
}
return 0;
@@ -662,7 +646,7 @@ static irqreturn_t mv88e6390_serdes_thread_fn(int irq, void *dev_id)
return ret;
}
-int mv88e6390x_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port)
+int mv88e6390_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port)
{
int err;
s8 lane;
@@ -700,15 +684,7 @@ int mv88e6390x_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port)
return mv88e6390_serdes_irq_enable(chip, port, lane);
}
-int mv88e6390_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port)
-{
- if (port < 9)
- return 0;
-
- return mv88e6390x_serdes_irq_setup(chip, port);
-}
-
-void mv88e6390x_serdes_irq_free(struct mv88e6xxx_chip *chip, int port)
+void mv88e6390_serdes_irq_free(struct mv88e6xxx_chip *chip, int port)
{
int err;
s8 lane;
@@ -732,27 +708,3 @@ void mv88e6390x_serdes_irq_free(struct mv88e6xxx_chip *chip, int port)
chip->ports[port].serdes_irq = 0;
}
-
-void mv88e6390_serdes_irq_free(struct mv88e6xxx_chip *chip, int port)
-{
- if (port < 9)
- return;
-
- mv88e6390x_serdes_irq_free(chip, port);
-}
-
-int mv88e6341_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
-{
- u8 cmode = chip->ports[port].cmode;
-
- if (port != 5)
- return 0;
-
- if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
- cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
- cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
- return mv88e6390_serdes_power_sgmii(chip, MV88E6341_ADDR_SERDES,
- on);
-
- return 0;
-}
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.h b/drivers/net/dsa/mv88e6xxx/serdes.h
index 1ddb8fb3aab9..7fded708b05d 100644
--- a/drivers/net/dsa/mv88e6xxx/serdes.h
+++ b/drivers/net/dsa/mv88e6xxx/serdes.h
@@ -28,7 +28,7 @@
#define MV88E6352_SERDES_INT_STATUS 0x13
-#define MV88E6341_ADDR_SERDES 0x15
+#define MV88E6341_PORT5_LANE 0x15
#define MV88E6390_PORT9_LANE0 0x09
#define MV88E6390_PORT9_LANE1 0x12
@@ -87,16 +87,13 @@ static inline int mv88e6xxx_serdes_get_lane(struct mv88e6xxx_chip *chip,
return chip->info->ops->serdes_get_lane(chip, port, lane);
}
+int mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port, s8 *lane);
int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port, s8 *lane);
int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port, s8 *lane);
-int mv88e6341_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on);
int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on);
int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on);
-int mv88e6390x_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on);
int mv88e6390_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port);
void mv88e6390_serdes_irq_free(struct mv88e6xxx_chip *chip, int port);
-int mv88e6390x_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port);
-void mv88e6390x_serdes_irq_free(struct mv88e6xxx_chip *chip, int port);
int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port);
int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip,
int port, uint8_t *data);
--
2.21.0
^ permalink raw reply related
* [PATCH net-next v3 2/6] net: dsa: mv88e6xxx: update code operating on hidden registers
From: Marek Behún @ 2019-08-25 3:59 UTC (permalink / raw)
To: netdev
Cc: Andrew Lunn, Vivien Didelot, Florian Fainelli, Vladimir Oltean,
Marek Behún
In-Reply-To: <20190825035915.13112-1-marek.behun@nic.cz>
This patch moves the functions operating on the hidden debug registers
into it's own file, port_hidden.c. The functions prefix is renamed from
mv88e6390_hidden_ to mv88e6xxx_port_hidden_, to be consistent with the
rest of this driver. The macros are prefixed with MV88E6XXX_ prefix, and
are changed not to use the BIT() macro nor bit shifts, since the rest of
the port.h file does not use it.
We also add the support for setting the Block Address field when
operating hidden registers. Marvell's mdio examples for SERDES settings
on Topaz use Block Address 0x7 when reading/writing hidden registers,
and although the specification says that block must be set to 0xf, those
settings are reachable only with Block Address 0x7.
Signed-off-by: Marek Behún <marek.behun@nic.cz>
---
drivers/net/dsa/mv88e6xxx/Makefile | 1 +
drivers/net/dsa/mv88e6xxx/chip.c | 58 +-------------------
drivers/net/dsa/mv88e6xxx/port.h | 22 +++++---
drivers/net/dsa/mv88e6xxx/port_hidden.c | 70 +++++++++++++++++++++++++
4 files changed, 87 insertions(+), 64 deletions(-)
create mode 100644 drivers/net/dsa/mv88e6xxx/port_hidden.c
diff --git a/drivers/net/dsa/mv88e6xxx/Makefile b/drivers/net/dsa/mv88e6xxx/Makefile
index e85755dde90b..aa645ff86f64 100644
--- a/drivers/net/dsa/mv88e6xxx/Makefile
+++ b/drivers/net/dsa/mv88e6xxx/Makefile
@@ -10,6 +10,7 @@ mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_GLOBAL2) += global2_scratch.o
mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_PTP) += hwtstamp.o
mv88e6xxx-objs += phy.o
mv88e6xxx-objs += port.o
+mv88e6xxx-objs += port_hidden.o
mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_PTP) += ptp.o
mv88e6xxx-objs += serdes.o
mv88e6xxx-objs += smi.o
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index d0bf98c10b2b..ec4274d71145 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -2317,60 +2317,6 @@ static int mv88e6xxx_stats_setup(struct mv88e6xxx_chip *chip)
return mv88e6xxx_g1_stats_clear(chip);
}
-/* The mv88e6390 has some hidden registers used for debug and
- * development. The errata also makes use of them.
- */
-static int mv88e6390_hidden_write(struct mv88e6xxx_chip *chip, int port,
- int reg, u16 val)
-{
- u16 ctrl;
- int err;
-
- err = mv88e6xxx_port_write(chip, PORT_RESERVED_1A_DATA_PORT,
- PORT_RESERVED_1A, val);
- if (err)
- return err;
-
- ctrl = PORT_RESERVED_1A_BUSY | PORT_RESERVED_1A_WRITE |
- PORT_RESERVED_1A_BLOCK | port << PORT_RESERVED_1A_PORT_SHIFT |
- reg;
-
- return mv88e6xxx_port_write(chip, PORT_RESERVED_1A_CTRL_PORT,
- PORT_RESERVED_1A, ctrl);
-}
-
-static int mv88e6390_hidden_wait(struct mv88e6xxx_chip *chip)
-{
- int bit = __bf_shf(PORT_RESERVED_1A_BUSY);
-
- return mv88e6xxx_wait_bit(chip, PORT_RESERVED_1A_CTRL_PORT,
- PORT_RESERVED_1A, bit, 0);
-}
-
-
-static int mv88e6390_hidden_read(struct mv88e6xxx_chip *chip, int port,
- int reg, u16 *val)
-{
- u16 ctrl;
- int err;
-
- ctrl = PORT_RESERVED_1A_BUSY | PORT_RESERVED_1A_READ |
- PORT_RESERVED_1A_BLOCK | port << PORT_RESERVED_1A_PORT_SHIFT |
- reg;
-
- err = mv88e6xxx_port_write(chip, PORT_RESERVED_1A_CTRL_PORT,
- PORT_RESERVED_1A, ctrl);
- if (err)
- return err;
-
- err = mv88e6390_hidden_wait(chip);
- if (err)
- return err;
-
- return mv88e6xxx_port_read(chip, PORT_RESERVED_1A_DATA_PORT,
- PORT_RESERVED_1A, val);
-}
-
/* Check if the errata has already been applied. */
static bool mv88e6390_setup_errata_applied(struct mv88e6xxx_chip *chip)
{
@@ -2379,7 +2325,7 @@ static bool mv88e6390_setup_errata_applied(struct mv88e6xxx_chip *chip)
u16 val;
for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
- err = mv88e6390_hidden_read(chip, port, 0, &val);
+ err = mv88e6xxx_port_hidden_read(chip, 0xf, port, 0, &val);
if (err) {
dev_err(chip->dev,
"Error reading hidden register: %d\n", err);
@@ -2412,7 +2358,7 @@ static int mv88e6390_setup_errata(struct mv88e6xxx_chip *chip)
}
for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
- err = mv88e6390_hidden_write(chip, port, 0, 0x01c0);
+ err = mv88e6xxx_port_hidden_write(chip, 0xf, port, 0, 0x01c0);
if (err)
return err;
}
diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h
index 1abf5ea033e2..64c73fd171ee 100644
--- a/drivers/net/dsa/mv88e6xxx/port.h
+++ b/drivers/net/dsa/mv88e6xxx/port.h
@@ -261,14 +261,14 @@
#define MV88E6095_PORT_IEEE_PRIO_REMAP_4567 0x19
/* Offset 0x1a: Magic undocumented errata register */
-#define PORT_RESERVED_1A 0x1a
-#define PORT_RESERVED_1A_BUSY BIT(15)
-#define PORT_RESERVED_1A_WRITE BIT(14)
-#define PORT_RESERVED_1A_READ 0
-#define PORT_RESERVED_1A_PORT_SHIFT 5
-#define PORT_RESERVED_1A_BLOCK (0xf << 10)
-#define PORT_RESERVED_1A_CTRL_PORT 4
-#define PORT_RESERVED_1A_DATA_PORT 5
+#define MV88E6XXX_PORT_RESERVED_1A 0x1a
+#define MV88E6XXX_PORT_RESERVED_1A_BUSY 0x8000
+#define MV88E6XXX_PORT_RESERVED_1A_WRITE 0x4000
+#define MV88E6XXX_PORT_RESERVED_1A_READ 0x0000
+#define MV88E6XXX_PORT_RESERVED_1A_PORT_SHIFT 5
+#define MV88E6XXX_PORT_RESERVED_1A_BLOCK_SHIFT 10
+#define MV88E6XXX_PORT_RESERVED_1A_CTRL_PORT 0x04
+#define MV88E6XXX_PORT_RESERVED_1A_DATA_PORT 0x05
int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port, int reg,
u16 *val);
@@ -353,4 +353,10 @@ int mv88e6095_port_set_upstream_port(struct mv88e6xxx_chip *chip, int port,
int mv88e6xxx_port_disable_learn_limit(struct mv88e6xxx_chip *chip, int port);
int mv88e6xxx_port_disable_pri_override(struct mv88e6xxx_chip *chip, int port);
+int mv88e6xxx_port_hidden_write(struct mv88e6xxx_chip *chip, int block,
+ int port, int reg, u16 val);
+int mv88e6xxx_port_hidden_wait(struct mv88e6xxx_chip *chip);
+int mv88e6xxx_port_hidden_read(struct mv88e6xxx_chip *chip, int block, int port,
+ int reg, u16 *val);
+
#endif /* _MV88E6XXX_PORT_H */
diff --git a/drivers/net/dsa/mv88e6xxx/port_hidden.c b/drivers/net/dsa/mv88e6xxx/port_hidden.c
new file mode 100644
index 000000000000..fc0a45cb4f68
--- /dev/null
+++ b/drivers/net/dsa/mv88e6xxx/port_hidden.c
@@ -0,0 +1,70 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Marvell 88E6xxx Switch Hidden Registers support
+ *
+ * Copyright (c) 2008 Marvell Semiconductor
+ *
+ * Copyright (c) 2019 Andrew Lunn <andrew@lunn.ch>
+ */
+
+#include <linux/bitfield.h>
+
+#include "chip.h"
+#include "port.h"
+
+/* The mv88e6390 and mv88e6341 have some hidden registers used for debug and
+ * development. The errata also makes use of them.
+ */
+int mv88e6xxx_port_hidden_write(struct mv88e6xxx_chip *chip, int block,
+ int port, int reg, u16 val)
+{
+ u16 ctrl;
+ int err;
+
+ err = mv88e6xxx_port_write(chip, MV88E6XXX_PORT_RESERVED_1A_DATA_PORT,
+ MV88E6XXX_PORT_RESERVED_1A, val);
+ if (err)
+ return err;
+
+ ctrl = MV88E6XXX_PORT_RESERVED_1A_BUSY |
+ MV88E6XXX_PORT_RESERVED_1A_WRITE |
+ block << MV88E6XXX_PORT_RESERVED_1A_BLOCK_SHIFT |
+ port << MV88E6XXX_PORT_RESERVED_1A_PORT_SHIFT |
+ reg;
+
+ return mv88e6xxx_port_write(chip, MV88E6XXX_PORT_RESERVED_1A_CTRL_PORT,
+ MV88E6XXX_PORT_RESERVED_1A, ctrl);
+}
+
+int mv88e6xxx_port_hidden_wait(struct mv88e6xxx_chip *chip)
+{
+ int bit = __bf_shf(MV88E6XXX_PORT_RESERVED_1A_BUSY);
+
+ return mv88e6xxx_wait_bit(chip, MV88E6XXX_PORT_RESERVED_1A_CTRL_PORT,
+ MV88E6XXX_PORT_RESERVED_1A, bit, 0);
+}
+
+int mv88e6xxx_port_hidden_read(struct mv88e6xxx_chip *chip, int block, int port,
+ int reg, u16 *val)
+{
+ u16 ctrl;
+ int err;
+
+ ctrl = MV88E6XXX_PORT_RESERVED_1A_BUSY |
+ MV88E6XXX_PORT_RESERVED_1A_READ |
+ block << MV88E6XXX_PORT_RESERVED_1A_BLOCK_SHIFT |
+ port << MV88E6XXX_PORT_RESERVED_1A_PORT_SHIFT |
+ reg;
+
+ err = mv88e6xxx_port_write(chip, MV88E6XXX_PORT_RESERVED_1A_CTRL_PORT,
+ MV88E6XXX_PORT_RESERVED_1A, ctrl);
+ if (err)
+ return err;
+
+ err = mv88e6xxx_port_hidden_wait(chip);
+ if (err)
+ return err;
+
+ return mv88e6xxx_port_read(chip, MV88E6XXX_PORT_RESERVED_1A_DATA_PORT,
+ MV88E6XXX_PORT_RESERVED_1A, val);
+}
--
2.21.0
^ permalink raw reply related
* [PATCH net-next v3 5/6] net: dsa: mv88e6xxx: rename port cmode macro
From: Marek Behún @ 2019-08-25 3:59 UTC (permalink / raw)
To: netdev
Cc: Andrew Lunn, Vivien Didelot, Florian Fainelli, Vladimir Oltean,
Marek Behún
In-Reply-To: <20190825035915.13112-1-marek.behun@nic.cz>
This is a cosmetic update. We are removing the last underscore from
macros MV88E6XXX_PORT_STS_CMODE_100BASE_X and
MV88E6XXX_PORT_STS_CMODE_1000BASE_X. The 2500base-x version does not
have that underscore. Also PHY_INTERFACE_MODE_ macros do not have it
there.
Signed-off-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
drivers/net/dsa/mv88e6xxx/port.c | 4 +--
drivers/net/dsa/mv88e6xxx/port.h | 4 +--
drivers/net/dsa/mv88e6xxx/serdes.c | 48 +++++++++++++++---------------
3 files changed, 28 insertions(+), 28 deletions(-)
diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c
index d20be5327640..7183c94a92ec 100644
--- a/drivers/net/dsa/mv88e6xxx/port.c
+++ b/drivers/net/dsa/mv88e6xxx/port.c
@@ -411,7 +411,7 @@ int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
switch (mode) {
case PHY_INTERFACE_MODE_1000BASEX:
- cmode = MV88E6XXX_PORT_STS_CMODE_1000BASE_X;
+ cmode = MV88E6XXX_PORT_STS_CMODE_1000BASEX;
break;
case PHY_INTERFACE_MODE_SGMII:
cmode = MV88E6XXX_PORT_STS_CMODE_SGMII;
@@ -618,7 +618,7 @@ int mv88e6352_port_link_state(struct mv88e6xxx_chip *chip, int port,
else
state->interface = PHY_INTERFACE_MODE_RGMII;
break;
- case MV88E6XXX_PORT_STS_CMODE_1000BASE_X:
+ case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
state->interface = PHY_INTERFACE_MODE_1000BASEX;
break;
case MV88E6XXX_PORT_STS_CMODE_SGMII:
diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h
index 64c73fd171ee..04550cb3c3b3 100644
--- a/drivers/net/dsa/mv88e6xxx/port.h
+++ b/drivers/net/dsa/mv88e6xxx/port.h
@@ -43,8 +43,8 @@
#define MV88E6XXX_PORT_STS_FLOW_CTL 0x0010
#define MV88E6XXX_PORT_STS_CMODE_MASK 0x000f
#define MV88E6XXX_PORT_STS_CMODE_RGMII 0x0007
-#define MV88E6XXX_PORT_STS_CMODE_100BASE_X 0x0008
-#define MV88E6XXX_PORT_STS_CMODE_1000BASE_X 0x0009
+#define MV88E6XXX_PORT_STS_CMODE_100BASEX 0x0008
+#define MV88E6XXX_PORT_STS_CMODE_1000BASEX 0x0009
#define MV88E6XXX_PORT_STS_CMODE_SGMII 0x000a
#define MV88E6XXX_PORT_STS_CMODE_2500BASEX 0x000b
#define MV88E6XXX_PORT_STS_CMODE_XAUI 0x000c
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c
index 1946ccb6694c..5bb3aea8a008 100644
--- a/drivers/net/dsa/mv88e6xxx/serdes.c
+++ b/drivers/net/dsa/mv88e6xxx/serdes.c
@@ -73,8 +73,8 @@ static bool mv88e6352_port_has_serdes(struct mv88e6xxx_chip *chip, int port)
{
u8 cmode = chip->ports[port].cmode;
- if ((cmode == MV88E6XXX_PORT_STS_CMODE_100BASE_X) ||
- (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X) ||
+ if ((cmode == MV88E6XXX_PORT_STS_CMODE_100BASEX) ||
+ (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX) ||
(cmode == MV88E6XXX_PORT_STS_CMODE_SGMII))
return true;
@@ -295,7 +295,7 @@ int mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port, s8 *lane)
if (port != 5)
return 0;
- if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
+ if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
*lane = MV88E6341_PORT5_LANE;
@@ -311,13 +311,13 @@ int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port, s8 *lane)
switch (port) {
case 9:
- if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
+ if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
*lane = MV88E6390_PORT9_LANE0;
break;
case 10:
- if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
+ if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
*lane = MV88E6390_PORT10_LANE0;
@@ -341,53 +341,53 @@ int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port, s8 *lane)
switch (port) {
case 2:
- if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
+ if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
- if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X)
+ if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
*lane = MV88E6390_PORT9_LANE1;
break;
case 3:
- if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
+ if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
- if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X)
+ if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
*lane = MV88E6390_PORT9_LANE2;
break;
case 4:
- if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
+ if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
- if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X)
+ if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
*lane = MV88E6390_PORT9_LANE3;
break;
case 5:
- if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
+ if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
- if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X)
+ if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
*lane = MV88E6390_PORT10_LANE1;
break;
case 6:
- if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
+ if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
- if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X)
+ if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
*lane = MV88E6390_PORT10_LANE2;
break;
case 7:
- if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
+ if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
- if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X)
+ if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
*lane = MV88E6390_PORT10_LANE3;
break;
case 9:
- if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
+ if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
cmode_port9 == MV88E6XXX_PORT_STS_CMODE_XAUI ||
@@ -395,7 +395,7 @@ int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port, s8 *lane)
*lane = MV88E6390_PORT9_LANE0;
break;
case 10:
- if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
+ if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
cmode_port10 == MV88E6XXX_PORT_STS_CMODE_XAUI ||
@@ -476,7 +476,7 @@ int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
switch (cmode) {
case MV88E6XXX_PORT_STS_CMODE_SGMII:
- case MV88E6XXX_PORT_STS_CMODE_1000BASE_X:
+ case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
return mv88e6390_serdes_power_sgmii(chip, lane, on);
case MV88E6XXX_PORT_STS_CMODE_XAUI:
@@ -535,7 +535,7 @@ static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip,
case MV88E6XXX_PORT_STS_CMODE_SGMII:
mode = PHY_INTERFACE_MODE_SGMII;
break;
- case MV88E6XXX_PORT_STS_CMODE_1000BASE_X:
+ case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
mode = PHY_INTERFACE_MODE_1000BASEX;
break;
case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
@@ -578,7 +578,7 @@ int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port,
switch (cmode) {
case MV88E6XXX_PORT_STS_CMODE_SGMII:
- case MV88E6XXX_PORT_STS_CMODE_1000BASE_X:
+ case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
err = mv88e6390_serdes_irq_enable_sgmii(chip, lane);
}
@@ -594,7 +594,7 @@ int mv88e6390_serdes_irq_disable(struct mv88e6xxx_chip *chip, int port,
switch (cmode) {
case MV88E6XXX_PORT_STS_CMODE_SGMII:
- case MV88E6XXX_PORT_STS_CMODE_1000BASE_X:
+ case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
err = mv88e6390_serdes_irq_disable_sgmii(chip, lane);
}
@@ -629,7 +629,7 @@ static irqreturn_t mv88e6390_serdes_thread_fn(int irq, void *dev_id)
switch (cmode) {
case MV88E6XXX_PORT_STS_CMODE_SGMII:
- case MV88E6XXX_PORT_STS_CMODE_1000BASE_X:
+ case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
err = mv88e6390_serdes_irq_status_sgmii(chip, lane, &status);
if (err)
--
2.21.0
^ permalink raw reply related
* [PATCH net-next v3 0/6] net: dsa: mv88e6xxx: Peridot/Topaz SERDES changes
From: Marek Behún @ 2019-08-25 3:59 UTC (permalink / raw)
To: netdev
Cc: Andrew Lunn, Vivien Didelot, Florian Fainelli, Vladimir Oltean,
Marek Behún
Hello,
this is the third version of changes for the Topaz/Peridot family of
switches. The patches apply on net-next.
Changes since v2:
- per Vivien's request I merged the three different patches operating
on code for hidden registers into one patch (second in this series)
- also per Vivien's request I changed the serdes_get_lane method: its
return value is now used only if error's occur, as the rest of this
drivers functions do. Lane number is put into a place pointed to
by the s8 *lane argument. The error semantics also changed: if there
is no lane on a port, the function should still return 0 and should
put -1 into *lane. Negative error value should be returned only if
a real error occurs, for example when a MDIO read operation failed.
- also per Vivien's request the mv88e6xxx_serdes_get_lane function was
put into serdes.h as static inline, since it is just a wrapper
- the patch that simplified SERDES code for Topaz and Peridot families
was merged into one patch
Marek
Marek Behún (6):
net: dsa: mv88e6xxx: support 2500base-x in SGMII IRQ handler
net: dsa: mv88e6xxx: update code operating on hidden registers
net: dsa: mv88e6xxx: create serdes_get_lane chip operation
net: dsa: mv88e6xxx: simplify SERDES code for Topaz and Peridot
net: dsa: mv88e6xxx: rename port cmode macro
net: dsa: mv88e6xxx: fully support SERDES on Topaz family
drivers/net/dsa/mv88e6xxx/Makefile | 1 +
drivers/net/dsa/mv88e6xxx/chip.c | 88 +++-----
drivers/net/dsa/mv88e6xxx/chip.h | 3 +
drivers/net/dsa/mv88e6xxx/port.c | 98 ++++++---
drivers/net/dsa/mv88e6xxx/port.h | 30 ++-
drivers/net/dsa/mv88e6xxx/port_hidden.c | 70 ++++++
drivers/net/dsa/mv88e6xxx/serdes.c | 275 +++++++++++-------------
drivers/net/dsa/mv88e6xxx/serdes.h | 27 ++-
8 files changed, 333 insertions(+), 259 deletions(-)
create mode 100644 drivers/net/dsa/mv88e6xxx/port_hidden.c
--
2.21.0
^ permalink raw reply
* [PATCH net-next v3 1/6] net: dsa: mv88e6xxx: support 2500base-x in SGMII IRQ handler
From: Marek Behún @ 2019-08-25 3:59 UTC (permalink / raw)
To: netdev
Cc: Andrew Lunn, Vivien Didelot, Florian Fainelli, Vladimir Oltean,
Marek Behún
In-Reply-To: <20190825035915.13112-1-marek.behun@nic.cz>
The mv88e6390_serdes_irq_link_sgmii IRQ handler reads the SERDES PHY
status register to determine speed, among other things. If cmode of the
port is set to 2500base-x, though, the PHY still reports 1000 Mbps (the
PHY register itself does not differentiate between 1000 Mbps and 2500
Mbps - it thinks it is running at 1000 Mbps, although clock is 2.5x
faster).
Look at the cmode and set SPEED_2500 if cmode is set to 2500base-x.
Also tell mv88e6xxx_port_setup_mac the PHY interface mode corresponding
to current cmode in terms of phy_interface_t.
Signed-off-by: Marek Behún <marek.behun@nic.cz>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Florian Fainelli <f.fainelli@gmail.com>
Cc: Vladimir Oltean <olteanv@gmail.com>
Cc: Vivien Didelot <vivien.didelot@gmail.com>
---
drivers/net/dsa/mv88e6xxx/serdes.c | 23 +++++++++++++++++++++--
1 file changed, 21 insertions(+), 2 deletions(-)
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c
index 20c526c2a9ee..678aaba3d019 100644
--- a/drivers/net/dsa/mv88e6xxx/serdes.c
+++ b/drivers/net/dsa/mv88e6xxx/serdes.c
@@ -505,9 +505,11 @@ int mv88e6390x_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip,
int port, int lane)
{
+ u8 cmode = chip->ports[port].cmode;
struct dsa_switch *ds = chip->ds;
int duplex = DUPLEX_UNKNOWN;
int speed = SPEED_UNKNOWN;
+ phy_interface_t mode;
int link, err;
u16 status;
@@ -527,7 +529,10 @@ static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip,
switch (status & MV88E6390_SGMII_PHY_STATUS_SPEED_MASK) {
case MV88E6390_SGMII_PHY_STATUS_SPEED_1000:
- speed = SPEED_1000;
+ if (cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
+ speed = SPEED_2500;
+ else
+ speed = SPEED_1000;
break;
case MV88E6390_SGMII_PHY_STATUS_SPEED_100:
speed = SPEED_100;
@@ -541,8 +546,22 @@ static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip,
}
}
+ switch (cmode) {
+ case MV88E6XXX_PORT_STS_CMODE_SGMII:
+ mode = PHY_INTERFACE_MODE_SGMII;
+ break;
+ case MV88E6XXX_PORT_STS_CMODE_1000BASE_X:
+ mode = PHY_INTERFACE_MODE_1000BASEX;
+ break;
+ case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
+ mode = PHY_INTERFACE_MODE_2500BASEX;
+ break;
+ default:
+ mode = PHY_INTERFACE_MODE_NA;
+ }
+
err = mv88e6xxx_port_setup_mac(chip, port, link, speed, duplex,
- PAUSE_OFF, PHY_INTERFACE_MODE_NA);
+ PAUSE_OFF, mode);
if (err)
dev_err(chip->dev, "can't propagate PHY settings to MAC: %d\n",
err);
--
2.21.0
^ permalink raw reply related
* Re: Regresion with dsa_port_disable
From: Vivien Didelot @ 2019-08-25 0:53 UTC (permalink / raw)
To: Andrew Lunn; +Cc: netdev
In-Reply-To: <20190824231653.GA17726@lunn.ch>
Hi Andrew,
On Sun, 25 Aug 2019 01:16:53 +0200, Andrew Lunn <andrew@lunn.ch> wrote:
> On Sat, Aug 24, 2019 at 07:12:20PM -0400, Vivien Didelot wrote:
> > Hi Andrew,
> >
> > On Sun, 25 Aug 2019 00:53:06 +0200, Andrew Lunn <andrew@lunn.ch> wrote:
> > > I just booted a ZII devel C and got a new warning splat.
> > >
> > > WARNING: CPU: 0 PID: 925 at kernel/irq/manage.c:1708 __free_irq+0xc8/0x2c4
> > > Trying to free already-free IRQ 0
> > > Modules linked in:
> > > CPU: 0 PID: 925 Comm: kworker/0:2 Not tainted 5.3.0-rc5-01151-g7ff758fcdf65 #231
> > > Hardware name: Freescale Vybrid VF5xx/VF6xx (Device Tree)
> > > Workqueue: events deferred_probe_work_func
> > > Backtrace:
> > > [<8010d9e4>] (dump_backtrace) from [<8010dd9c>] (show_stack+0x20/0x24)
> > > r7:8016edf8 r6:00000009 r5:00000000 r4:9ec67944
> > > [<8010dd7c>] (show_stack) from [<8083b03c>] (dump_stack+0x24/0x28)
> > > [<8083b018>] (dump_stack) from [<8011c108>] (__warn.part.3+0xcc/0xf8)
> > > [<8011c03c>] (__warn.part.3) from [<8011c1ac>] (warn_slowpath_fmt+0x78/0x94)
> > > r6:000006ac r5:80a8cbf0 r4:80d07088
> > > [<8011c138>] (warn_slowpath_fmt) from [<8016edf8>] (__free_irq+0xc8/0x2c4)
> > > r3:00000000 r2:80a8cca8
> > > r7:9f486668 r6:9ee25268 r5:9f486600 r4:9ee25268
> > > [<8016ed30>] (__free_irq) from [<8016f07c>] (free_irq+0x38/0x74)
> > > r10:9eeb3600 r9:9e412040 r8:00000009 r7:9ee26040 r6:9ee2404c r5:9ee242c8
> > > r4:9ee25268 r3:00000c00
> > > [<8016f044>] (free_irq) from [<805a244c>] (mv88e6390x_serdes_irq_free+0x68/0x98)
> > > r5:9ee242c8 r4:9ee24040
> > > [<805a23e4>] (mv88e6390x_serdes_irq_free) from [<8059bc94>] (mv88e6xxx_port_disable+0x58/0x98)
> > > r7:9ee26040 r6:00000009 r5:9ee2404c r4:9ee24040
> > > [<8059bc3c>] (mv88e6xxx_port_disable) from [<80806f70>] (dsa_port_disable+0x44/0x50)
> > > r7:9ee26040 r6:9ee26d74 r5:00000009 r4:9ee26040
> > > [<80806f2c>] (dsa_port_disable) from [<80805df0>] (dsa_register_switch+0x964/0xab8)
> > > r5:9efe194c r4:9ee26d38
> > > [<8080548c>] (dsa_register_switch) from [<8059b734>] (mv88e6xxx_probe+0x730/0x778)
> > > r10:80943e64 r9:9fbf77d0 r8:00000000 r7:80d07088 r6:9e410040 r5:00000000
> > > r4:9e40e800
> > > [<8059b004>] (mv88e6xxx_probe) from [<80582da8>] (mdio_probe+0x40/0x64)
> > > r10:00000012 r9:80d5eccc r8:00000000 r7:00000000 r6:8141f358 r5:9e40e800
> > > r4:80d5eccc
> > > [<80582d68>] (mdio_probe) from [<80518858>] (really_probe+0x100/0x2d8)
> > > r5:9e40e800 r4:8141f354
> > >
> > > The previous code was careful to balance mv88e6352_serdes_irq_setup()
> > > with mv88e6390x_serdes_irq_free(). I _think_ your change broke this
> > > balance, and we now try to free an interrupt which was never
> > > allocated.
> >
> > What do you mean by "balance mv88e6352_serdes_irq_setup() with
> > mv88e6390x_serdes_irq_free()"?
>
> Hi Vivien
>
> It never called mv88e6390x_serdes_irq_free() unless
> mv88e6352_serdes_irq_setup() had been called first.
> mv88e6390x_serdes_irq_free() makes the assumption there actually is an
> interrupt to free. I suspect your changes now call
> mv88e6390x_serdes_irq_free() unconditionally.
OK I think you meant info->ops->serdes_irq_free and
info->ops->serdes_irq_setup, otherwise it's confusing.
I think I know what's going on, I'll look into it soon.
Thanks!
^ permalink raw reply
* Re: [net-next 07/14] ice: Rename ethtool private flag for lldp
From: Kirsher, Jeffrey T @ 2019-08-25 0:04 UTC (permalink / raw)
To: David Miller
Cc: jakub.kicinski@netronome.com, Ertman, David M,
netdev@vger.kernel.org, nhorman@redhat.com, sassmann@redhat.com,
Bowers, AndrewX
In-Reply-To: <20190824.164726.357731088137490877.davem@davemloft.net>
> On Aug 24, 2019, at 16:47, David Miller <davem@davemloft.net> wrote:
>
> From: Jakub Kicinski <jakub.kicinski@netronome.com>
> Date: Fri, 23 Aug 2019 18:31:11 -0700
>
>>> On Fri, 23 Aug 2019 16:37:43 -0700, Jeff Kirsher wrote:
>>> From: Dave Ertman <david.m.ertman@intel.com>
>>>
>>> The current flag name of "enable-fw-lldp" is a bit cumbersome.
>>>
>>> Change priv-flag name to "fw-lldp-agent" with a value of on or
>>> off. This is more straight-forward in meaning.
>>>
>>> Signed-off-by: Dave Ertman <david.m.ertman@intel.com>
>>> Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
>>> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
>>
>> Just flagging this for Dave, it was introduced in v5.2 by:
>
> So should we backport the rename into 'net'? Is this a bug fix or just
> making life easier for people?
IMHO, no need to backport.
^ permalink raw reply
* Re: [PATCH net-next] net: phy: sfp: Add labels to hwmon sensors
From: David Miller @ 2019-08-25 0:02 UTC (permalink / raw)
To: andrew; +Cc: rmk+kernel, linux, Chris.Healy, netdev
In-Reply-To: <20190824230417.17657-1-andrew@lunn.ch>
From: Andrew Lunn <andrew@lunn.ch>
Date: Sun, 25 Aug 2019 01:04:17 +0200
> SFPs can report two different power values, the transmit power and the
> receive power. Add labels to make it clear which is which. Also add
> labels to the other sensors, VCC power supply, bias and module
> temperature.
>
> sensors(1) now shows:
>
> sff2-isa-0000
> Adapter: ISA adapter
> VCC: +3.23 V
> temperature: +33.4 C
> TX_power: 276.00 uW
> RX_power: 20.00 uW
> bias: +0.01 A
>
> Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Applied, thanks Andrew.
^ permalink raw reply
* Re: [PATCH] r8152: Set memory to all 0xFFs on failed reg reads
From: David Miller @ 2019-08-25 0:00 UTC (permalink / raw)
To: pmalani; +Cc: hayeswang, grundler, netdev
In-Reply-To: <20190824083619.69139-1-pmalani@chromium.org>
From: Prashant Malani <pmalani@chromium.org>
Date: Sat, 24 Aug 2019 01:36:19 -0700
> get_registers() blindly copies the memory written to by the
> usb_control_msg() call even if the underlying urb failed.
>
> This could lead to junk register values being read by the driver, since
> some indirect callers of get_registers() ignore the return values. One
> example is:
> ocp_read_dword() ignores the return value of generic_ocp_read(), which
> calls get_registers().
>
> So, emulate PCI "Master Abort" behavior by setting the buffer to all
> 0xFFs when usb_control_msg() fails.
>
> This patch is copied from the r8152 driver (v2.12.0) published by
> Realtek (www.realtek.com).
>
> Signed-off-by: Prashant Malani <pmalani@chromium.org>
Hayes, please review.
^ permalink raw reply
* Re: [PATCHv2 1/1] net: rds: add service level support in rds-info
From: David Miller @ 2019-08-24 23:58 UTC (permalink / raw)
To: yanjun.zhu; +Cc: santosh.shilimkar, netdev, linux-rdma, rds-devel, gerd.rausch
In-Reply-To: <1566608656-30836-1-git-send-email-yanjun.zhu@oracle.com>
From: Zhu Yanjun <yanjun.zhu@oracle.com>
Date: Fri, 23 Aug 2019 21:04:16 -0400
> diff --git a/include/uapi/linux/rds.h b/include/uapi/linux/rds.h
> index fd6b5f6..cba368e 100644
> --- a/include/uapi/linux/rds.h
> +++ b/include/uapi/linux/rds.h
> @@ -250,6 +250,7 @@ struct rds_info_rdma_connection {
> __u32 rdma_mr_max;
> __u32 rdma_mr_size;
> __u8 tos;
> + __u8 sl;
> __u32 cache_allocs;
> };
I'm applying this, but I am once again severely disappointed in how
RDS development is being handled.
From the Fixes: commit:
Since rds.h in rds-tools is not related with the kernel rds.h,
the change in kernel rds.h does not affect rds-tools.
This is the height of arrogance and shows a lack of understanding of
what user ABI requirements are all about.
It is possible for other userland components to be built by other
people, outside of your controlled eco-system and tools, that use
these interfaces.
And you cannot control that.
Therefore you cannot make arbitrary changes to UABI data strucures
just because the tool you use and maintain is not effected by it.
Please stop making these incredibly incompatible user interface
changes in the RDS stack.
I am, from this point forward, going to be extra strict on RDS stack
changes especially in this area.
^ permalink raw reply
* Re: [net PATCH] net: route dump netlink NLM_F_MULTI flag missing
From: David Miller @ 2019-08-24 23:50 UTC (permalink / raw)
To: john.fastabend; +Cc: sbrivio, dsahern, netdev
In-Reply-To: <156660549861.5753.7912871726096518275.stgit@john-XPS-13-9370>
From: John Fastabend <john.fastabend@gmail.com>
Date: Fri, 23 Aug 2019 17:11:38 -0700
> An excerpt from netlink(7) man page,
>
> In multipart messages (multiple nlmsghdr headers with associated payload
> in one byte stream) the first and all following headers have the
> NLM_F_MULTI flag set, except for the last header which has the type
> NLMSG_DONE.
>
> but, after (ee28906) there is a missing NLM_F_MULTI flag in the middle of a
> FIB dump. The result is user space applications following above man page
> excerpt may get confused and may stop parsing msg believing something went
> wrong.
>
> In the golang netlink lib [0] the library logic stops parsing believing the
> message is not a multipart message. Found this running Cilium[1] against
> net-next while adding a feature to auto-detect routes. I noticed with
> multiple route tables we no longer could detect the default routes on net
> tree kernels because the library logic was not returning them.
>
> Fix this by handling the fib_dump_info_fnhe() case the same way the
> fib_dump_info() handles it by passing the flags argument through the
> call chain and adding a flags argument to rt_fill_info().
>
> Tested with Cilium stack and auto-detection of routes works again. Also
> annotated libs to dump netlink msgs and inspected NLM_F_MULTI and
> NLMSG_DONE flags look correct after this.
>
> Note: In inet_rtm_getroute() pass rt_fill_info() '0' for flags the same
> as is done for fib_dump_info() so this looks correct to me.
>
> [0] https://github.com/vishvananda/netlink/
> [1] https://github.com/cilium/
>
> Fixes: ee28906fd7a14 ("ipv4: Dump route exceptions if requested")
> Signed-off-by: John Fastabend <john.fastabend@gmail.com>
Applied, thanks John.
^ permalink raw reply
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