phydev->n_ports--;
}
+static int phy_setup_sfp_port(struct phy_device *phydev)
+{
+ struct phy_port *port = phy_port_alloc();
+ int ret;
+
+ if (!port)
+ return -ENOMEM;
+
+ port->parent_type = PHY_PORT_PHY;
+ port->phy = phydev;
+
+ /* The PHY is a media converter, the port connected to the SFP cage
+ * is a MII port.
+ */
+ port->is_mii = true;
+
+ /* The port->supported and port->interfaces list will be populated
+ * when attaching the port to the phydev.
+ */
+ ret = phy_add_port(phydev, port);
+ if (ret)
+ phy_port_destroy(port);
+
+ return ret;
+}
+
/**
* phy_sfp_probe - probe for a SFP cage attached to this PHY device
* @phydev: Pointer to phy_device
ret = sfp_bus_add_upstream(bus, phydev, ops);
sfp_bus_put(bus);
}
+
+ if (!ret && phydev->sfp_bus)
+ ret = phy_setup_sfp_port(phydev);
+
return ret;
}
EXPORT_SYMBOL(phy_sfp_probe);
__ETHTOOL_LINK_MODE_MASK_NBITS)
port->pairs = max_t(int, port->pairs,
ethtool_linkmode_n_pairs(mode));
+
+ /* Serdes ports supported through SFP may not have any medium set,
+ * as they will output PHY_INTERFACE_MODE_XXX modes. In that case, derive
+ * the supported list based on these interfaces
+ */
+ if (port->is_mii && !port->mediums) {
+ unsigned long interface, link_caps = 0;
+
+ /* Get each interface's caps */
+ for_each_set_bit(interface, port->interfaces,
+ PHY_INTERFACE_MODE_MAX)
+ link_caps |= phy_caps_from_interface(interface);
+
+ phy_caps_linkmodes(link_caps, port->supported);
+ }
}
EXPORT_SYMBOL_GPL(phy_port_update_supported);