lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <d9fc09066ef374aada6486203ddfe05832ecd977.camel@siemens.com>
Date:   Wed, 8 Feb 2023 08:20:23 +0000
From:   "Valek, Andrej" <andrej.valek@...mens.com>
To:     "andrew@...n.ch" <andrew@...n.ch>
CC:     "vivien.didelot@...il.com" <vivien.didelot@...il.com>,
        "netdev@...r.kernel.org" <netdev@...r.kernel.org>
Subject: Re: DSA mv88e6xxx_probe

Hello Andrew,

I found a problem.
There is a bug in FEC driver which is not handling the MDIO bus
properly. Once this is fixed, then it works exactly like you described.

Many thanks for your support,
Andrej

On Mon, 2023-02-06 at 14:50 +0000, Valek, Andrej wrote:
> Hello again,
> 
> I put some more "debugs" there.
> 
> >         /* assert bus level PHY GPIO reset */
> >         dev_info(&bus->dev, "getting gpiod\n");
> >         gpiod = devm_gpiod_get_optional(&bus->dev, "reset",
> > GPIOD_OUT_HIGH);
> >         if(gpiod) dev_info(&bus->dev, "gpio found1\n");
> >         else dev_info(&bus->dev, "gpio NOT found1\n");
> > 
> >         /*if (IS_ERR(gpiod)) {
> >                 dev_info(&bus->dev, "gpiod error\n");
> >                 err = dev_err_probe(&bus->dev, PTR_ERR(gpiod),
> >                                     "mii_bus %s couldn't get reset
> > GPIO\n",
> >                                     bus->id);
> >                 device_del(&bus->dev);
> >                 return err;
> >         }*/
> > 
> >         if (gpiod) {
> >                 dev_info(&bus->dev, "%p:gpiod found\n", gpiod);
> >                 bus->reset_gpiod = gpiod;
> >                 fsleep(bus->reset_delay_us);
> >                 gpiod_set_value_cansleep(gpiod, 0);
> >                 if (bus->reset_post_delay_us > 0)
> >                         fsleep(bus->reset_post_delay_us);
> >         }
> 
> After that I see messages like:
> > [    1.530251] mdio_bus 5b040000.ethernet-1: device registered
> > [    1.535840] mdio_bus 5b040000.ethernet-1: getting gpiod
> > [    1.541150] mdio_bus 5b040000.ethernet-1: gpio found1
> > [    1.546210] mdio_bus 5b040000.ethernet-1: fffffffffffffdfb:gpiod
> > found
> > [    1.567900] gpiod_set_value_cansleep: invalid GPIO
> > (errorpointer)
> 
> So there is a problem, that function "devm_gpiod_get_optional" is not
> returning the correct pointer.
> 
> Regards,
> Andrej
> 
> On Fri, 2023-02-03 at 14:47 +0000, Valek, Andrej wrote:
> > On Fri, 2023-02-03 at 14:54 +0100, Andrew Lunn wrote:
> > > > > > This looks promising. So I have to just move the "reset-
> > > > > > gpios" DTB
> > > > > > entry from switch to mdio section. But which driver handles
> > > > > > it,
> > > > > > drivers/net/phy/mdio_bus.c,
> > > > > 
> > > > > Yes.
> > > > > 
> > > > > > > mdio {
> > > > > > >         #address-cells = <1>;
> > > > > > >         #size-cells = 0>;
> > > > > > while here is no compatible part... .
> > > > > 
> > > > > It does not need a compatible, because it is part of the FEC,
> > > > > and the
> > > > > FEC has a compatible. Remember this is device tree, sometimes
> > > > > you need
> > > > > to go up the tree towards the root to find the actual device
> > > > > with a
> > > > > compatible.
> > > > > 
> > > > >     Andrew
> > > > I tried put the "reset-gpios" and "reset-delay-us" into
> > > > multiple
> > > > mdio locations, but nothing has been working. DTB looks like
> > > > that:
> > > > 
> > > > > &fec1 {
> > > > >         pinctrl-names = "default";
> > > > >         pinctrl-0 = <&pinctrl_fec1>;
> > > > >         phy-mode = "rgmii-id";
> > > > >         tx-internal-delay-ps = <2000>;
> > > > >         rx-internal-delay-ps = <2000>;
> > > > >         slaves = <1>;                   // use only one emac
> > > > > if
> > > > >         status = "okay";
> > > > >         mac-address = [ 00 00 00 00 00 00 ]; // Filled in by
> > > > > U-
> > > > > Boot
> > > > > 
> > > > >         // #### 3. try ####
> > > > >         //phy-reset-gpios = <&lsio_gpio0 13 GPIO_ACTIVE_LOW>;
> > > > >         //reset-delay-us = <10000>;
> > > > > 
> > > > >         fixed-link {
> > > > >                 speed = <1000>;
> > > > >                 full-duplex;
> > > > >         };
> > > > > 
> > > > >         mdio {
> > > > >                 #address-cells = <1>;
> > > > >                 #size-cells = <0>;
> > > > > 
> > > > >                 // 1. try
> > > > >                 reset-gpios = <&lsio_gpio0 13
> > > > > GPIO_ACTIVE_LOW>;
> > > > >                 reset-delay-us = <10000>;
> > > 
> > > This looks like the correct location. Have you put a printk()
> > > after
> > > https://elixir.bootlin.com/linux/latest/source/drivers/net/phy/mdio_bus.c#L569
> > > to make sure it has found it?
> > > 
> > Yes, I put there multiple printk-s... .
> > >         dev_info(&bus->dev, "device registered\n");
> > > 
> > >         mutex_init(&bus->mdio_lock);
> > >         mutex_init(&bus->shared_lock);
> > > 
> > >         /* assert bus level PHY GPIO reset */
> > >         gpiod = devm_gpiod_get_optional(&bus->dev, "reset",
> > > GPIOD_OUT_HIGH);
> > >         dev_info(&bus->dev, "getting gpiod\n");
> > > 
> > >         if (IS_ERR(gpiod)) {
> > >                 err = dev_err_probe(&bus->dev, PTR_ERR(gpiod),
> > >                                     "mii_bus %s couldn't get
> > > reset
> > > GPIO\n",
> > >                                     bus->id);
> > >                 device_del(&bus->dev);
> > >                 return err;
> > >         } else  if (gpiod) {
> > >                 dev_info(&bus->dev, "gpiod found\n");
> > >                 bus->reset_gpiod = gpiod;
> > >                 fsleep(bus->reset_delay_us);
> > >                 gpiod_set_value_cansleep(gpiod, 0);
> > >                 if (bus->reset_post_delay_us > 0)
> > >                         fsleep(bus->reset_post_delay_us);
> > >         }
> > > 
> > >         if (bus->reset) {
> > >                 dev_info(&bus->dev, "reset found\n");
> > >                 err = bus->reset(bus);
> > 
> > And the output log looks:
> > > [    1.446095] mdio_bus fixed-0: device registered
> > > [    1.450698] mdio_bus fixed-0: getting gpiod
> > > [    1.494870] pps pps0: new PPS source ptp0
> > > [    1.505888] mdio_bus 5b040000.ethernet-1: device registered
> > > [    1.511552] mdio_bus 5b040000.ethernet-1: getting gpiod
> > > [    1.550705] pps pps0: new PPS source ptp0
> > > [    1.561203] mdio_bus 5b050000.ethernet-1: device registered
> > > [    1.566791] mdio_bus 5b050000.ethernet-1: getting gpiod
> > > ...
> > > [    2.568174] fec 5b050000.ethernet eth0: registered PHC device
> > > 0
> > 
> > Sp there are only a "device registered" and "getting gpiod"
> > messages
> > and nor "gpiod found" and "resed found".
> > So now the question is why it didn't find the reset in dtb, or
> > where
> > to place it.
> > 
> > Andrej
> > 
> > > You might also need a post reset delay. I'm not sure the device
> > > will
> > > answer if it is still busy reading the EEPROM. Which is why the
> > > mv88e6xxx hardware reset does some polling before continuing.
> > > 
> > >           Andrew
> > 
> 

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ