cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
947 Views
Registered: ‎02-05-2020

GMII-to-RGMII driver overwrites PHY driver's priv struct

Jump to solution

I'm having a problem with a Linux 4.14.0 system that contains a Micrel KSZ9031 ethernet PHY and the Xillinx GMII-to-RGMII IP.  The problem happens at boot time.  The Micrel driver's probe function is called and allocates a private struct and stores its pointer in the "priv" field of its phy_device struct.  Then the GMII-to-RGMII driver's probe function is called.  It calls of_parse_phandle(..."phy-handle"...) to get the Micrel driver's device tree node and then calls of_phy_find_device() on that node, which returns a pointer to the Micrel driver's phy_device struct.  The GMII-to-RGMII driver then stores a pointer to its private struct into the priv field of the Micrel's driver's phy_device, overwriting the Micrel's pointer, which is now lost.  I don't get it.  How is this supposed to work?

Here is the relevant portion of the device tree:

ethernet@e000b000 {
   #address-cells = <0x1>;
   #size-cells = <0x0>;
   compatible = "cdns,zynq-gem", "cdns,gem";
   reg = <0xe000b000 0x1000>;
   status = "okay";
   interrupts = <0x0 0x16 0x4>;
   clocks = <0x1 0x1e 0x1 0x1e 0x1 0xd>;
   clock-names = "pclk", "hclk", "tx_clk";
   phy-handle = <0xc>;
   gmii2rgmii-phy-handle = <0xd>;
   phy-mode = "gmii";

   mdio {
      #address-cells = <0x1>;
      #size-cells = <0x0>;

      phy@1 {
         device_type = "ethernet-phy";
         reg = <0x1>;
         linux,phandle = <0xc>;
         phandle = <0xc>;
      };

      phy@9 {
         compatible = "xlnx,gmii-to-rgmii-1.0";
         device_type = "ethernet-phy";
         phy-handle = <0xc>;
         reg = <0x9>;
         linux,phandle = <0xd>;
         phandle = <0xd>;
      };
   };
};

 

0 Kudos
1 Solution

Accepted Solutions
824 Views
Registered: ‎02-05-2020
7 Replies
nanz
Moderator
Moderator
872 Views
Registered: ‎08-25-2009

Hi david.d.beal@medtronic.com ,

Can you please try to reverse the phy node and gmii-to-rgmii node in device tree and see what happens?


-------------------------------------------------------------------------------------------

Don’t forget to reply, kudo, and accept as solution.

If starting with Versal take a look at our Versal Design Process Hub and our Versal Blogs and our Versal Ethernet Sticky Note.

-------------------------------------------------------------------------------------------
0 Kudos
simon.beaudoin
Adventurer
Adventurer
860 Views
Registered: ‎05-08-2018

It's been some time since I had my nose deep inside ethernet/device-tree stuff. Buf if I'm not mistaken, it looks like you are telling linux that there exists an ethernet interface, and for that interface, there exists an mdio bus, and for that mdio bus, there are two PHYs connected to it. Hierarchically, that's how I read it. Conceptually, there are not two PHYs : there is your Micrel PHY and that's it. But, your PHY, which is RGMII, is connected to the IP's GMII port through a GMII-to-RGMII converter. Hierarchcally, and in my opinion logically, your PHY node should be nested in the GMII-to-RGMII node. Maybe check that avenue? Check for each node's documentation in the linux repo, often all the information you need to setup a given device-tree node is there along with exemples. I'm no expert on the subject, that's just my 2cents

 

0 Kudos
840 Views
Registered: ‎02-05-2020

Hello nanz!  Thank you for your suggestion.  I swapped the order of the two phy sections, like so:

mdio {
   #address-cells = <0x1>;
   #size-cells = <0x0>;
   phy@9 {
      compatible = "xlnx,gmii-to-rgmii-1.0";
      device_type = "ethernet-phy";
      phy-handle = <0xc>;
      reg = <0x9>;
      linux,phandle = <0xd>;
      phandle = <0xd>;
   };
   phy@1 {
      device_type = "ethernet-phy";
      reg = <0x1>;
      linux,phandle = <0xc>;
      phandle = <0xc>;
   };

};

The result is that the gmii-to-rgmii driver's probe function runs first and its of_phy_find_device() function fails, because the Micrel's probe function has not yet run.  So the gmii-to-rgmii driver's probe function returns EPROBE_DEFER.  Later, the gmii-to-rgmii driver's probe function runs again, its of_phy_find_device() function succeeds, and it clobbers the Micrel's priv pointer as before.  No improvement.

0 Kudos
832 Views
Registered: ‎02-05-2020

Hello Simon!  Thank you for your suggestion.  I tried nesting the Micrel's PHY section inside the GMII_to-RGMII's section like this:

mdio {
   #address-cells = <0x1>;
   #size-cells = <0x0>;
   phy@1 {
      device_type = "ethernet-phy";
      reg = <0x1>;
      linux,phandle = <0xc>;
      phandle = <0xc>;
      phy@9 {
         compatible = "xlnx,gmii-to-rgmii-1.0";
         device_type = "ethernet-phy";
         phy-handle = <0xc>;
         reg = <0x9>;
         linux,phandle = <0xd>;
         phandle = <0xd>;
      };
   };
};

The result is that the GMII-to-RGMII driver's probe function never runs.  Neither does its read_status() function, which means that the GMII-to-RGMII converter will not be set to the proper bit rate to match that of the Micrel PHY.

0 Kudos
825 Views
Registered: ‎02-05-2020
simon.beaudoin
Adventurer
Adventurer
800 Views
Registered: ‎05-08-2018

Yep, it looks like it's the thing! From my experience with zynq fpgas and embedded linux, kernel code is pretty stable. Drivers on their hand are in constant evolution. They tend to be of high quality, but several improvements keep coming. It's always good to have the instinct of going on github and look at what peoples report and pull request. Several issues are discussed there and not here. I had several bugs fixed this way. Digging into code on xilinx linux github has now become more or less of a habit for me. Thats experience I suppose! 

0 Kudos
769 Views
Registered: ‎02-05-2020

Yep, this patch fixes the problem.

0 Kudos