}
 EXPORT_SYMBOL(phy_ethtool_get_stats);
 
+/**
+ * phy_ethtool_get_plca_cfg - Get PLCA RS configuration
+ * @phydev: the phy_device struct
+ * @plca_cfg: where to store the retrieved configuration
+ *
+ * Retrieve the PLCA configuration from the PHY. Return 0 on success or a
+ * negative value if an error occurred.
+ */
+int phy_ethtool_get_plca_cfg(struct phy_device *phydev,
+                            struct phy_plca_cfg *plca_cfg)
+{
+       int ret;
+
+       if (!phydev->drv) {
+               ret = -EIO;
+               goto out;
+       }
+
+       if (!phydev->drv->get_plca_cfg) {
+               ret = -EOPNOTSUPP;
+               goto out;
+       }
+
+       mutex_lock(&phydev->lock);
+       ret = phydev->drv->get_plca_cfg(phydev, plca_cfg);
+
+       mutex_unlock(&phydev->lock);
+out:
+       return ret;
+}
+
+/**
+ * plca_check_valid - Check PLCA configuration before enabling
+ * @phydev: the phy_device struct
+ * @plca_cfg: current PLCA configuration
+ * @extack: extack for reporting useful error messages
+ *
+ * Checks whether the PLCA and PHY configuration are consistent and it is safe
+ * to enable PLCA. Returns 0 on success or a negative value if the PLCA or PHY
+ * configuration is not consistent.
+ */
+static int plca_check_valid(struct phy_device *phydev,
+                           const struct phy_plca_cfg *plca_cfg,
+                           struct netlink_ext_ack *extack)
+{
+       int ret = 0;
+
+       if (!linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT1S_P2MP_Half_BIT,
+                              phydev->advertising)) {
+               ret = -EOPNOTSUPP;
+               NL_SET_ERR_MSG(extack,
+                              "Point to Multi-Point mode is not enabled");
+       } else if (plca_cfg->node_id >= 255) {
+               NL_SET_ERR_MSG(extack, "PLCA node ID is not set");
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
+/**
+ * phy_ethtool_set_plca_cfg - Set PLCA RS configuration
+ * @phydev: the phy_device struct
+ * @plca_cfg: new PLCA configuration to apply
+ * @extack: extack for reporting useful error messages
+ *
+ * Sets the PLCA configuration in the PHY. Return 0 on success or a
+ * negative value if an error occurred.
+ */
+int phy_ethtool_set_plca_cfg(struct phy_device *phydev,
+                            const struct phy_plca_cfg *plca_cfg,
+                            struct netlink_ext_ack *extack)
+{
+       struct phy_plca_cfg *curr_plca_cfg;
+       int ret;
+
+       if (!phydev->drv) {
+               ret = -EIO;
+               goto out;
+       }
+
+       if (!phydev->drv->set_plca_cfg ||
+           !phydev->drv->get_plca_cfg) {
+               ret = -EOPNOTSUPP;
+               goto out;
+       }
+
+       curr_plca_cfg = kmalloc(sizeof(*curr_plca_cfg), GFP_KERNEL);
+       if (!curr_plca_cfg) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       mutex_lock(&phydev->lock);
+
+       ret = phydev->drv->get_plca_cfg(phydev, curr_plca_cfg);
+       if (ret)
+               goto out_drv;
+
+       if (curr_plca_cfg->enabled < 0 && plca_cfg->enabled >= 0) {
+               NL_SET_ERR_MSG(extack,
+                              "PHY does not support changing the PLCA 'enable' attribute");
+               ret = -EINVAL;
+               goto out_drv;
+       }
+
+       if (curr_plca_cfg->node_id < 0 && plca_cfg->node_id >= 0) {
+               NL_SET_ERR_MSG(extack,
+                              "PHY does not support changing the PLCA 'local node ID' attribute");
+               ret = -EINVAL;
+               goto out_drv;
+       }
+
+       if (curr_plca_cfg->node_cnt < 0 && plca_cfg->node_cnt >= 0) {
+               NL_SET_ERR_MSG(extack,
+                              "PHY does not support changing the PLCA 'node count' attribute");
+               ret = -EINVAL;
+               goto out_drv;
+       }
+
+       if (curr_plca_cfg->to_tmr < 0 && plca_cfg->to_tmr >= 0) {
+               NL_SET_ERR_MSG(extack,
+                              "PHY does not support changing the PLCA 'TO timer' attribute");
+               ret = -EINVAL;
+               goto out_drv;
+       }
+
+       if (curr_plca_cfg->burst_cnt < 0 && plca_cfg->burst_cnt >= 0) {
+               NL_SET_ERR_MSG(extack,
+                              "PHY does not support changing the PLCA 'burst count' attribute");
+               ret = -EINVAL;
+               goto out_drv;
+       }
+
+       if (curr_plca_cfg->burst_tmr < 0 && plca_cfg->burst_tmr >= 0) {
+               NL_SET_ERR_MSG(extack,
+                              "PHY does not support changing the PLCA 'burst timer' attribute");
+               ret = -EINVAL;
+               goto out_drv;
+       }
+
+       // if enabling PLCA, perform a few sanity checks
+       if (plca_cfg->enabled > 0) {
+               // allow setting node_id concurrently with enabled
+               if (plca_cfg->node_id >= 0)
+                       curr_plca_cfg->node_id = plca_cfg->node_id;
+
+               ret = plca_check_valid(phydev, curr_plca_cfg, extack);
+               if (ret)
+                       goto out_drv;
+       }
+
+       ret = phydev->drv->set_plca_cfg(phydev, plca_cfg);
+
+out_drv:
+       kfree(curr_plca_cfg);
+       mutex_unlock(&phydev->lock);
+out:
+       return ret;
+}
+
+/**
+ * phy_ethtool_get_plca_status - Get PLCA RS status information
+ * @phydev: the phy_device struct
+ * @plca_st: where to store the retrieved status information
+ *
+ * Retrieve the PLCA status information from the PHY. Return 0 on success or a
+ * negative value if an error occurred.
+ */
+int phy_ethtool_get_plca_status(struct phy_device *phydev,
+                               struct phy_plca_status *plca_st)
+{
+       int ret;
+
+       if (!phydev->drv) {
+               ret = -EIO;
+               goto out;
+       }
+
+       if (!phydev->drv->get_plca_status) {
+               ret = -EOPNOTSUPP;
+               goto out;
+       }
+
+       mutex_lock(&phydev->lock);
+       ret = phydev->drv->get_plca_status(phydev, plca_st);
+
+       mutex_unlock(&phydev->lock);
+out:
+       return ret;
+}
+
 /**
  * phy_start_cable_test - Start a cable test
  *