]> Gentwo Git Trees - linux/.git/commitdiff
fbnic: Replace use of internal PCS w/ Designware XPCS
authorAlexander Duyck <alexanderduyck@fb.com>
Fri, 21 Nov 2025 16:40:52 +0000 (08:40 -0800)
committerPaolo Abeni <pabeni@redhat.com>
Thu, 27 Nov 2025 09:41:31 +0000 (10:41 +0100)
As we have exposed the PCS registers via the SWMII we can now start looking
at connecting the XPCS driver to those registers and let it mange the PCS
instead of us doing it directly from the fbnic driver.

For now this just gets us the ability to detect link. The hope is in the
future to add some of the vendor specific registers to begin enabling XPCS
configuration of the interface.

Signed-off-by: Alexander Duyck <alexanderduyck@fb.com>
Link: https://patch.msgid.link/176374325295.959489.14521115864034905277.stgit@ahduyck-xeon-server.home.arpa
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
drivers/net/ethernet/meta/Kconfig
drivers/net/ethernet/meta/fbnic/fbnic_irq.c
drivers/net/ethernet/meta/fbnic/fbnic_netdev.c
drivers/net/ethernet/meta/fbnic/fbnic_netdev.h
drivers/net/ethernet/meta/fbnic/fbnic_phylink.c

index dff51f23d295ec9730a7c846145c616cc8e2cb7f..ca5c7ac2a5bc2242eda5c0f249106cc88014aaaa 100644 (file)
@@ -26,6 +26,7 @@ config FBNIC
        depends on PTP_1588_CLOCK_OPTIONAL
        select NET_DEVLINK
        select PAGE_POOL
+       select PCS_XPCS
        select PHYLINK
        select PLDMFW
        help
index 9b068b82f30a08c0f5a84f17a9273754b8085b37..02e8b0b257fed832ecffe2bc43e86d5da0eb2743 100644 (file)
@@ -133,7 +133,7 @@ static irqreturn_t fbnic_mac_msix_intr(int __always_unused irq, void *data)
 
        /* Record link down events */
        if (!fbd->mac->get_link(fbd, fbn->aui, fbn->fec))
-               phylink_pcs_change(&fbn->phylink_pcs, false);
+               phylink_pcs_change(fbn->pcs, false);
 
        return IRQ_HANDLED;
 }
index 65318a5b466e4cd139ddbac557117cb73b9e4786..81c9d5c9a4b2c0e5f42022a595f2e4d368e057f6 100644 (file)
@@ -697,10 +697,7 @@ void fbnic_reset_queues(struct fbnic_net *fbn,
  **/
 void fbnic_netdev_free(struct fbnic_dev *fbd)
 {
-       struct fbnic_net *fbn = netdev_priv(fbd->netdev);
-
-       if (fbn->phylink)
-               phylink_destroy(fbn->phylink);
+       fbnic_phylink_destroy(fbd->netdev);
 
        free_netdev(fbd->netdev);
        fbd->netdev = NULL;
@@ -802,7 +799,7 @@ struct net_device *fbnic_netdev_alloc(struct fbnic_dev *fbd)
 
        netif_tx_stop_all_queues(netdev);
 
-       if (fbnic_phylink_init(netdev)) {
+       if (fbnic_phylink_create(netdev)) {
                fbnic_netdev_free(fbd);
                return NULL;
        }
index deab789b2a6cb31d60b5185f671fdca4355079f0..9129a658f8fad3cb5e8bb5288bc64f34f4cdf93b 100644 (file)
@@ -44,7 +44,7 @@ struct fbnic_net {
 
        struct phylink *phylink;
        struct phylink_config phylink_config;
-       struct phylink_pcs phylink_pcs;
+       struct phylink_pcs *pcs;
 
        u8 aui;
        u8 fec;
@@ -108,6 +108,8 @@ int fbnic_phylink_ethtool_ksettings_get(struct net_device *netdev,
                                        struct ethtool_link_ksettings *cmd);
 int fbnic_phylink_get_fecparam(struct net_device *netdev,
                               struct ethtool_fecparam *fecparam);
+int fbnic_phylink_create(struct net_device *netdev);
+void fbnic_phylink_destroy(struct net_device *netdev);
 int fbnic_phylink_init(struct net_device *netdev);
 void fbnic_phylink_pmd_training_complete_notify(struct net_device *netdev);
 bool fbnic_check_split_frames(struct bpf_prog *prog,
index 20f88c8dcc79a5229902b46f829969efd621b6fd..09c5225111be3702e3e8bc44ab2b919b03a594ee 100644 (file)
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 /* Copyright (c) Meta Platforms, Inc. and affiliates. */
 
+#include <linux/pcs/pcs-xpcs.h>
 #include <linux/phy.h>
 #include <linux/phylink.h>
 
@@ -101,56 +102,6 @@ int fbnic_phylink_get_fecparam(struct net_device *netdev,
        return 0;
 }
 
-static struct fbnic_net *
-fbnic_pcs_to_net(struct phylink_pcs *pcs)
-{
-       return container_of(pcs, struct fbnic_net, phylink_pcs);
-}
-
-static void
-fbnic_phylink_pcs_get_state(struct phylink_pcs *pcs, unsigned int neg_mode,
-                           struct phylink_link_state *state)
-{
-       struct fbnic_net *fbn = fbnic_pcs_to_net(pcs);
-       struct fbnic_dev *fbd = fbn->fbd;
-
-       switch (fbn->aui) {
-       case FBNIC_AUI_25GAUI:
-               state->speed = SPEED_25000;
-               break;
-       case FBNIC_AUI_LAUI2:
-       case FBNIC_AUI_50GAUI1:
-               state->speed = SPEED_50000;
-               break;
-       case FBNIC_AUI_100GAUI2:
-               state->speed = SPEED_100000;
-               break;
-       default:
-               state->link = 0;
-               return;
-       }
-
-       state->duplex = DUPLEX_FULL;
-
-       state->link = (fbd->pmd_state == FBNIC_PMD_SEND_DATA) &&
-                     (rd32(fbd, FBNIC_PCS(MDIO_STAT1, 0)) &
-                      MDIO_STAT1_LSTATUS);
-}
-
-static int
-fbnic_phylink_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
-                        phy_interface_t interface,
-                        const unsigned long *advertising,
-                        bool permit_pause_to_mac)
-{
-       return 0;
-}
-
-static const struct phylink_pcs_ops fbnic_phylink_pcs_ops = {
-       .pcs_config = fbnic_phylink_pcs_config,
-       .pcs_get_state = fbnic_phylink_pcs_get_state,
-};
-
 static struct phylink_pcs *
 fbnic_phylink_mac_select_pcs(struct phylink_config *config,
                             phy_interface_t interface)
@@ -158,7 +109,7 @@ fbnic_phylink_mac_select_pcs(struct phylink_config *config,
        struct net_device *netdev = to_net_dev(config->dev);
        struct fbnic_net *fbn = netdev_priv(netdev);
 
-       return &fbn->phylink_pcs;
+       return fbn->pcs;
 }
 
 static int
@@ -232,13 +183,33 @@ static const struct phylink_mac_ops fbnic_phylink_mac_ops = {
        .mac_link_up = fbnic_phylink_mac_link_up,
 };
 
-int fbnic_phylink_init(struct net_device *netdev)
+/**
+ * fbnic_phylink_create - Phylink device creation
+ * @netdev: Network Device struct to attach phylink device
+ *
+ * Initialize and attach a phylink instance to the device. The phylink
+ * device will make use of the netdev struct to track carrier and will
+ * eventually be used to expose the current state of the MAC and PCS
+ * setup.
+ *
+ * Return: 0 on success, negative on failure
+ **/
+int fbnic_phylink_create(struct net_device *netdev)
 {
        struct fbnic_net *fbn = netdev_priv(netdev);
        struct fbnic_dev *fbd = fbn->fbd;
+       struct phylink_pcs *pcs;
        struct phylink *phylink;
+       int err;
+
+       pcs = xpcs_create_pcs_mdiodev(fbd->mdio_bus, 0);
+       if (IS_ERR(pcs)) {
+               err = PTR_ERR(pcs);
+               dev_err(fbd->dev, "Failed to create PCS device: %d\n", err);
+               return err;
+       }
 
-       fbn->phylink_pcs.ops = &fbnic_phylink_pcs_ops;
+       fbn->pcs = pcs;
 
        fbn->phylink_config.dev = &netdev->dev;
        fbn->phylink_config.type = PHYLINK_NETDEV;
@@ -261,14 +232,35 @@ int fbnic_phylink_init(struct net_device *netdev)
        phylink = phylink_create(&fbn->phylink_config, NULL,
                                 fbnic_phylink_select_interface(fbn->aui),
                                 &fbnic_phylink_mac_ops);
-       if (IS_ERR(phylink))
-               return PTR_ERR(phylink);
+       if (IS_ERR(phylink)) {
+               err = PTR_ERR(phylink);
+               dev_err(netdev->dev.parent,
+                       "Failed to create Phylink interface, err: %d\n", err);
+               xpcs_destroy_pcs(pcs);
+               return err;
+       }
 
        fbn->phylink = phylink;
 
        return 0;
 }
 
+/**
+ * fbnic_phylink_destroy - Teardown phylink related interfaces
+ * @netdev: Network Device struct containing phylink device
+ *
+ * Detach and free resources related to phylink interface.
+ **/
+void fbnic_phylink_destroy(struct net_device *netdev)
+{
+       struct fbnic_net *fbn = netdev_priv(netdev);
+
+       if (fbn->phylink)
+               phylink_destroy(fbn->phylink);
+       if (fbn->pcs)
+               xpcs_destroy_pcs(fbn->pcs);
+}
+
 /**
  * fbnic_phylink_pmd_training_complete_notify - PMD training complete notifier
  * @netdev: Netdev struct phylink device attached to
@@ -315,5 +307,5 @@ void fbnic_phylink_pmd_training_complete_notify(struct net_device *netdev)
                    FBNIC_PMD_SEND_DATA) != FBNIC_PMD_LINK_READY)
                return;
 
-       phylink_pcs_change(&fbn->phylink_pcs, false);
+       phylink_pcs_change(fbn->pcs, false);
 }