cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Highlighted
530 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
Highlighted
407 Views
Registered: ‎02-05-2020
7 Replies
Highlighted
Moderator
Moderator
455 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."
0 Kudos
Highlighted
Adventurer
Adventurer
443 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
Highlighted
423 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
Highlighted
415 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
Highlighted
408 Views
Registered: ‎02-05-2020
Highlighted
Adventurer
Adventurer
383 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
Highlighted
352 Views
Registered: ‎02-05-2020

Yep, this patch fixes the problem.

0 Kudos