All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC] phylink: support for devices with MAC sharing SFP cage & PHY (e.g. Turris Omnia)
@ 2018-12-30  8:25 Klaus Kudielka
  2018-12-30  9:51 ` Andrew Lunn
  0 siblings, 1 reply; 10+ messages in thread
From: Klaus Kudielka @ 2018-12-30  8:25 UTC (permalink / raw)
  To: netdev
  Cc: Andrew Lunn, Florian Fainelli, Heiner Kallweit, Russell King,
	Uwe Kleine-König, Tomas Hlavacek

Hello,

I own a Turris Omnia, which has basic support included in the
Linux kernel (armada-385-turris-omnia.dts).

Apart from the 88E1514 PHY specified for eth2, the device also
features an SFP cage, which uses the same SGMII of the Armada
385 SoC (a 2:1 multiplexer is driven by the MOD_DEF0 signal).

Details can be found on page 5 of
https://doc.turris.cz/doc/_media/rtrom01-schema.pdf

As far as I understand the situation, phylink does not support
such an architecture at the moment. This may be the reason why
the SFP cage was never specified in the Turris Omnia DTS.

Questions:
- Is anybody already working on a solution?
- If not, would something like the patch below be acceptable?
- Any other suggestions, how to get this supported?

Summary of the patch, which is based on the device tree
published by Tomas (and my interpretation of phylink.c):

I'm specifying *both* the SFP cage and the PHY in the node of
the eth2 MAC. In phylink_of_connect, if SFP module is already
present: Ignore any PHY specified by the devicetree. After
SFP removal, restore the original (device tree based)
configuration, which was determined by phylink_create et al.
(I don't think that this would harm the generic use case)

With this, "hot" insertion and removal work, as long as the
network interface is down. I tested this successfully on my
Turris Omnia, on a relatively recent openwrt-master
(4.14 kernel). SFP module is a TP-LINK TL-SM321B.

Insertion/removal in the "up" state would require more
work. If this is considered necessary, I can give it a try.

I am sorry, the patch is against the 4.14 (openwrt) kernel,
but you get the basic idea.

--- a/arch/arm/boot/dts/armada-385-turris-omnia.dts
+++ b/arch/arm/boot/dts/armada-385-turris-omnia.dts
@@ -115,6 +115,16 @@
              };
          };
      };
+
+    sfp: sfp {
+        compatible = "sff,sfp";
+        i2c-bus = <&i2csfp>;
+        tx-fault-gpios = <&pcawan 0 GPIO_ACTIVE_HIGH>;
+        tx-disable-gpios = <&pcawan 1 GPIO_ACTIVE_HIGH>;
+        rate-select0-gpios = <&pcawan 2 GPIO_ACTIVE_HIGH>;
+        los-gpios = <&pcawan 3 GPIO_ACTIVE_HIGH>;
+        mod-def0-gpios = <&pcawan 4 GPIO_ACTIVE_LOW>;
+    };
  };

  /* Connected to 88E6176 switch, port 6 */
@@ -148,6 +158,7 @@
      status = "okay";
      phy-mode = "sgmii";
      phy = <&phy1>;
+    sfp = <&sfp>;
  };

  &i2c0 {
@@ -210,7 +221,7 @@
              /* routed to PCIe2 connector (CN62A) */
          };

-        i2c@4 {
+        i2csfp: i2c@4 {
              #address-cells = <1>;
              #size-cells = <0>;
              reg = <4>;
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -58,6 +58,12 @@ struct phylink {
      bool mac_link_dropped;

      struct sfp_bus *sfp_bus;
+
+    /* Things to remember across a module insertion/removal cycle */
+    u8 default_an_mode;
+    u8 default_port;
+    struct phylink_link_state default_config;
+    bool sfp_module_present;
  };

  static inline void linkmode_zero(unsigned long *dst)
@@ -680,6 +686,10 @@ int phylink_of_phy_connect(struct phylin
      if (pl->link_an_mode == MLO_AN_FIXED)
          return 0;

+    /* If SFP module present, we do not need a separate PHY */
+    if (pl->sfp_module_present)
+        return 0;
+
      phy_node = of_parse_phandle(dn, "phy-handle", 0);
      if (!phy_node)
          phy_node = of_parse_phandle(dn, "phy", 0);
@@ -1371,6 +1381,11 @@ static int phylink_sfp_module_insert(voi
      if (mode == MLO_AN_8023Z && pl->phydev)
          return -EINVAL;

+    pl->default_an_mode = pl->link_an_mode;
+    pl->default_port = pl->link_port;
+    pl->default_config = pl->link_config;
+    pl->sfp_module_present = true;
+
      changed = !bitmap_equal(pl->supported, support,
                  __ETHTOOL_LINK_MODE_MASK_NBITS);
      if (changed) {
@@ -1399,6 +1414,16 @@ static int phylink_sfp_module_insert(voi
      return ret;
  }

+static void phylink_sfp_module_remove(void *upstream)
+{
+    struct phylink *pl = upstream;
+
+    pl->link_an_mode = pl->default_an_mode;
+    pl->link_port = pl->default_port;
+    pl->link_config = pl->default_config;
+    pl->sfp_module_present = false;
+}
+
  static void phylink_sfp_link_down(void *upstream)
  {
      struct phylink *pl = upstream;
@@ -1432,6 +1457,7 @@ static void phylink_sfp_disconnect_phy(v

  static const struct sfp_upstream_ops sfp_phylink_ops = {
      .module_insert = phylink_sfp_module_insert,
+    .module_remove = phylink_sfp_module_remove,
      .link_up = phylink_sfp_link_up,
      .link_down = phylink_sfp_link_down,
      .connect_phy = phylink_sfp_connect_phy,

^ permalink raw reply	[flat|nested] 10+ messages in thread
* [RFC] phylink: support for devices with MAC sharing SFP cage & PHY (e.g. Turris Omnia)?
@ 2018-12-28 11:14 Klaus Kudielka
  2018-12-28 23:28 ` Andrew Lunn
  0 siblings, 1 reply; 10+ messages in thread
From: Klaus Kudielka @ 2018-12-28 11:14 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: Tomas Hlavacek, uwe

Hello,

I own a Turris Omnia, which has basic support included in the
Linux kernel (armada-385-turris-omnia.dts).

Apart from the 88E1514 PHY specified for eth2, the device also
features an SFP cage, which uses the same SGMII of the Armada
385 SoC, using a 2:1 multiplexer driven by the MOD_DEF0 signal.
Details can be found on page 5 of
https://doc.turris.cz/doc/_media/rtrom01-schema.pdf.

As far as I understand the situation, phylink does not support
such an architecture at the moment, which is the reason why the
SFP cage was never specified in the Turris Omnia's DTS.

Questions:
- Is anybody already working on a solution?
- If not, would something like the patch below be acceptable?
- Any other suggestions, how to get this supported?

Summary of the patch below, whis is based on device tree
published by Tomas (and my interpretation of phylink.c):

I'm specifying *both* the SFP cage and the PHY in the node of
the eth2 MAC. In phylink_of_connect, if SFP module is already
present: Ignore any PHY specified by the devicetree. After
SFP removal, restore the original (device tree based)
configuration, which was determined by phylink_create et al.
(I don't think that this would harm the generic use case)

With this, "hot" insertion and removal work, as long as the
network interface is down. I tested this successfully on my
Turris Omnia, on a relatively recent openwrt-master
(4.14 kernel). SFP module is a TP-LINK TL-SM321B.

"Hot" insertion/removal in the "up" state would require more
work.

I am sorry, the patch below is against the 4.14 (openwrt)
kernel, but you get the basic idea.

--- a/arch/arm/boot/dts/armada-385-turris-omnia.dts
+++ b/arch/arm/boot/dts/armada-385-turris-omnia.dts
@@ -115,6 +115,16 @@
              };
          };
      };
+
+    sfp: sfp {
+        compatible = "sff,sfp";
+        i2c-bus = <&i2csfp>;
+        tx-fault-gpios = <&pcawan 0 GPIO_ACTIVE_HIGH>;
+        tx-disable-gpios = <&pcawan 1 GPIO_ACTIVE_HIGH>;
+        rate-select0-gpios = <&pcawan 2 GPIO_ACTIVE_HIGH>;
+        los-gpios = <&pcawan 3 GPIO_ACTIVE_HIGH>;
+        mod-def0-gpios = <&pcawan 4 GPIO_ACTIVE_LOW>;
+    };
  };

  /* Connected to 88E6176 switch, port 6 */
@@ -148,6 +158,7 @@
      status = "okay";
      phy-mode = "sgmii";
      phy = <&phy1>;
+    sfp = <&sfp>;
  };

  &i2c0 {
@@ -210,7 +221,7 @@
              /* routed to PCIe2 connector (CN62A) */
          };

-        i2c@4 {
+        i2csfp: i2c@4 {
              #address-cells = <1>;
              #size-cells = <0>;
              reg = <4>;
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -58,6 +58,12 @@ struct phylink {
      bool mac_link_dropped;

      struct sfp_bus *sfp_bus;
+
+    /* Things to remember across a module insertion/removal cycle */
+    u8 default_an_mode;
+    u8 default_port;
+    struct phylink_link_state default_config;
+    bool sfp_module_present;
  };

  static inline void linkmode_zero(unsigned long *dst)
@@ -680,6 +686,10 @@ int phylink_of_phy_connect(struct phylin
      if (pl->link_an_mode == MLO_AN_FIXED)
          return 0;

+    /* If SFP module present, we do not need a separate PHY */
+    if (pl->sfp_module_present)
+        return 0;
+
      phy_node = of_parse_phandle(dn, "phy-handle", 0);
      if (!phy_node)
          phy_node = of_parse_phandle(dn, "phy", 0);
@@ -1371,6 +1381,11 @@ static int phylink_sfp_module_insert(voi
      if (mode == MLO_AN_8023Z && pl->phydev)
          return -EINVAL;

+    pl->default_an_mode = pl->link_an_mode;
+    pl->default_port = pl->link_port;
+    pl->default_config = pl->link_config;
+    pl->sfp_module_present = true;
+
      changed = !bitmap_equal(pl->supported, support,
                  __ETHTOOL_LINK_MODE_MASK_NBITS);
      if (changed) {
@@ -1399,6 +1414,16 @@ static int phylink_sfp_module_insert(voi
      return ret;
  }

+static void phylink_sfp_module_remove(void *upstream)
+{
+    struct phylink *pl = upstream;
+
+    pl->link_an_mode = pl->default_an_mode;
+    pl->link_port = pl->default_port;
+    pl->link_config = pl->default_config;
+    pl->sfp_module_present = false;
+}
+
  static void phylink_sfp_link_down(void *upstream)
  {
      struct phylink *pl = upstream;
@@ -1432,6 +1457,7 @@ static void phylink_sfp_disconnect_phy(v

  static const struct sfp_upstream_ops sfp_phylink_ops = {
      .module_insert = phylink_sfp_module_insert,
+    .module_remove = phylink_sfp_module_remove,
      .link_up = phylink_sfp_link_up,
      .link_down = phylink_sfp_link_down,
      .connect_phy = phylink_sfp_connect_phy,


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2019-01-04  9:45 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-12-30  8:25 [RFC] phylink: support for devices with MAC sharing SFP cage & PHY (e.g. Turris Omnia) Klaus Kudielka
2018-12-30  9:51 ` Andrew Lunn
2018-12-30 22:35   ` Florian Fainelli
2018-12-30 22:41     ` Andrew Lunn
2019-01-04  9:45     ` Russell King - ARM Linux
2018-12-31 11:24   ` Klaus Kudielka
2018-12-31 17:43     ` Andrew Lunn
2019-01-04  6:26       ` Klaus Kudielka
  -- strict thread matches above, loose matches on Subject: below --
2018-12-28 11:14 [RFC] phylink: support for devices with MAC sharing SFP cage & PHY (e.g. Turris Omnia)? Klaus Kudielka
2018-12-28 23:28 ` Andrew Lunn

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.