mirror of
https://github.com/torvalds/linux.git
synced 2026-05-28 09:04:39 +02:00
Merge branch 'net-rework-sfp-capability-parsing-and-quirks'
Russell King says: ==================== net: rework SFP capability parsing and quirks The original SPF module parsing was implemented prior to gaining any quirks, and was designed such that the upstream calls the parsing functions to get the translated capabilities of the module. SFP quirks were then added to cope with modules that didn't correctly fill out their ID EEPROM. The quirk function was called from sfp_parse_support() to allow quirks to modify the ethtool link mode masks. Using just ethtool link mode masks eventually lead to difficulties determining the correct phy_interface_t mode, so a bitmap of these modes were added - needing both the upstream API and quirks to be updated. We have had significantly more SFP module quirks added since, some which are modifying the ID EEPROM as a way of influencing the data we provide to the upstream - for example, sfp_fixup_10gbaset_30m() changes id.base.connector so we report PORT_TP. This could be done more cleanly if the quirks had access to the parsed SFP port. In order to improve flexibility, and to simplify some of the upstream code, we group all module capabilities into a single structure that the upstream can access via sfp_module_get_caps(). This will allow the module capabilities to be expanded if required without reworking all the infrastructure and upstreams again. In this series, we rework the SFP code to use the capability structure and then rework all the upstream implementations, finally removing the old kernel internal APIs. ==================== Link: https://patch.msgid.link/aMnaoPjIuzEAsESZ@shell.armlinux.org.uk Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
6710ab7558
|
|
@ -475,21 +475,20 @@ static int mv2222_config_init(struct phy_device *phydev)
|
|||
|
||||
static int mv2222_sfp_insert(void *upstream, const struct sfp_eeprom_id *id)
|
||||
{
|
||||
DECLARE_PHY_INTERFACE_MASK(interfaces);
|
||||
struct phy_device *phydev = upstream;
|
||||
const struct sfp_module_caps *caps;
|
||||
phy_interface_t sfp_interface;
|
||||
struct mv2222_data *priv;
|
||||
struct device *dev;
|
||||
int ret;
|
||||
|
||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(sfp_supported) = { 0, };
|
||||
|
||||
priv = phydev->priv;
|
||||
dev = &phydev->mdio.dev;
|
||||
|
||||
sfp_parse_support(phydev->sfp_bus, id, sfp_supported, interfaces);
|
||||
phydev->port = sfp_parse_port(phydev->sfp_bus, id, sfp_supported);
|
||||
sfp_interface = sfp_select_interface(phydev->sfp_bus, sfp_supported);
|
||||
caps = sfp_get_module_caps(phydev->sfp_bus);
|
||||
|
||||
phydev->port = caps->port;
|
||||
sfp_interface = sfp_select_interface(phydev->sfp_bus, caps->link_modes);
|
||||
|
||||
dev_info(dev, "%s SFP module inserted\n", phy_modes(sfp_interface));
|
||||
|
||||
|
|
@ -502,7 +501,7 @@ static int mv2222_sfp_insert(void *upstream, const struct sfp_eeprom_id *id)
|
|||
}
|
||||
|
||||
priv->line_interface = sfp_interface;
|
||||
linkmode_and(priv->supported, phydev->supported, sfp_supported);
|
||||
linkmode_and(priv->supported, phydev->supported, caps->link_modes);
|
||||
|
||||
ret = mv2222_config_line(phydev);
|
||||
if (ret < 0)
|
||||
|
|
|
|||
|
|
@ -3600,20 +3600,18 @@ static int marvell_probe(struct phy_device *phydev)
|
|||
|
||||
static int m88e1510_sfp_insert(void *upstream, const struct sfp_eeprom_id *id)
|
||||
{
|
||||
DECLARE_PHY_INTERFACE_MASK(interfaces);
|
||||
struct phy_device *phydev = upstream;
|
||||
const struct sfp_module_caps *caps;
|
||||
phy_interface_t interface;
|
||||
struct device *dev;
|
||||
int oldpage;
|
||||
int ret = 0;
|
||||
u16 mode;
|
||||
|
||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(supported) = { 0, };
|
||||
|
||||
dev = &phydev->mdio.dev;
|
||||
|
||||
sfp_parse_support(phydev->sfp_bus, id, supported, interfaces);
|
||||
interface = sfp_select_interface(phydev->sfp_bus, supported);
|
||||
caps = sfp_get_module_caps(phydev->sfp_bus);
|
||||
interface = sfp_select_interface(phydev->sfp_bus, caps->link_modes);
|
||||
|
||||
dev_info(dev, "%s SFP module inserted\n", phy_modes(interface));
|
||||
|
||||
|
|
|
|||
|
|
@ -466,12 +466,11 @@ static int mv3310_set_edpd(struct phy_device *phydev, u16 edpd)
|
|||
static int mv3310_sfp_insert(void *upstream, const struct sfp_eeprom_id *id)
|
||||
{
|
||||
struct phy_device *phydev = upstream;
|
||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(support) = { 0, };
|
||||
DECLARE_PHY_INTERFACE_MASK(interfaces);
|
||||
const struct sfp_module_caps *caps;
|
||||
phy_interface_t iface;
|
||||
|
||||
sfp_parse_support(phydev->sfp_bus, id, support, interfaces);
|
||||
iface = sfp_select_interface(phydev->sfp_bus, support);
|
||||
caps = sfp_get_module_caps(phydev->sfp_bus);
|
||||
iface = sfp_select_interface(phydev->sfp_bus, caps->link_modes);
|
||||
|
||||
if (iface != PHY_INTERFACE_MODE_10GBASER) {
|
||||
dev_err(&phydev->mdio.dev, "incompatible SFP module inserted\n");
|
||||
|
|
|
|||
|
|
@ -3750,17 +3750,18 @@ static int phylink_sfp_config_optical(struct phylink *pl)
|
|||
static int phylink_sfp_module_insert(void *upstream,
|
||||
const struct sfp_eeprom_id *id)
|
||||
{
|
||||
const struct sfp_module_caps *caps;
|
||||
struct phylink *pl = upstream;
|
||||
|
||||
ASSERT_RTNL();
|
||||
|
||||
linkmode_zero(pl->sfp_support);
|
||||
phy_interface_zero(pl->sfp_interfaces);
|
||||
sfp_parse_support(pl->sfp_bus, id, pl->sfp_support, pl->sfp_interfaces);
|
||||
pl->sfp_port = sfp_parse_port(pl->sfp_bus, id, pl->sfp_support);
|
||||
caps = sfp_get_module_caps(pl->sfp_bus);
|
||||
phy_interface_copy(pl->sfp_interfaces, caps->interfaces);
|
||||
linkmode_copy(pl->sfp_support, caps->link_modes);
|
||||
pl->sfp_may_have_phy = caps->may_have_phy;
|
||||
pl->sfp_port = caps->port;
|
||||
|
||||
/* If this module may have a PHY connecting later, defer until later */
|
||||
pl->sfp_may_have_phy = sfp_may_have_phy(pl->sfp_bus, id);
|
||||
if (pl->sfp_may_have_phy)
|
||||
return 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -771,10 +771,10 @@ static int at8031_register_regulators(struct phy_device *phydev)
|
|||
|
||||
static int at8031_sfp_insert(void *upstream, const struct sfp_eeprom_id *id)
|
||||
{
|
||||
struct phy_device *phydev = upstream;
|
||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(phy_support);
|
||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(sfp_support);
|
||||
DECLARE_PHY_INTERFACE_MASK(interfaces);
|
||||
struct phy_device *phydev = upstream;
|
||||
const struct sfp_module_caps *caps;
|
||||
phy_interface_t iface;
|
||||
|
||||
linkmode_zero(phy_support);
|
||||
|
|
@ -784,12 +784,11 @@ static int at8031_sfp_insert(void *upstream, const struct sfp_eeprom_id *id)
|
|||
phylink_set(phy_support, Pause);
|
||||
phylink_set(phy_support, Asym_Pause);
|
||||
|
||||
linkmode_zero(sfp_support);
|
||||
sfp_parse_support(phydev->sfp_bus, id, sfp_support, interfaces);
|
||||
caps = sfp_get_module_caps(phydev->sfp_bus);
|
||||
/* Some modules support 10G modes as well as others we support.
|
||||
* Mask out non-supported modes so the correct interface is picked.
|
||||
*/
|
||||
linkmode_and(sfp_support, phy_support, sfp_support);
|
||||
linkmode_and(sfp_support, phy_support, caps->link_modes);
|
||||
|
||||
if (linkmode_empty(sfp_support)) {
|
||||
dev_err(&phydev->mdio.dev, "incompatible SFP module inserted\n");
|
||||
|
|
|
|||
|
|
@ -646,13 +646,12 @@ static int qca807x_phy_package_config_init_once(struct phy_device *phydev)
|
|||
static int qca807x_sfp_insert(void *upstream, const struct sfp_eeprom_id *id)
|
||||
{
|
||||
struct phy_device *phydev = upstream;
|
||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(support) = { 0, };
|
||||
const struct sfp_module_caps *caps;
|
||||
phy_interface_t iface;
|
||||
int ret;
|
||||
DECLARE_PHY_INTERFACE_MASK(interfaces);
|
||||
|
||||
sfp_parse_support(phydev->sfp_bus, id, support, interfaces);
|
||||
iface = sfp_select_interface(phydev->sfp_bus, support);
|
||||
caps = sfp_get_module_caps(phydev->sfp_bus);
|
||||
iface = sfp_select_interface(phydev->sfp_bus, caps->link_modes);
|
||||
|
||||
dev_info(&phydev->mdio.dev, "%s SFP module inserted\n", phy_modes(iface));
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ struct sfp_bus {
|
|||
const struct sfp_socket_ops *socket_ops;
|
||||
struct device *sfp_dev;
|
||||
struct sfp *sfp;
|
||||
const struct sfp_quirk *sfp_quirk;
|
||||
|
||||
const struct sfp_upstream_ops *upstream_ops;
|
||||
void *upstream;
|
||||
|
|
@ -30,24 +29,18 @@ struct sfp_bus {
|
|||
|
||||
bool registered;
|
||||
bool started;
|
||||
|
||||
struct sfp_module_caps caps;
|
||||
};
|
||||
|
||||
/**
|
||||
* sfp_parse_port() - Parse the EEPROM base ID, setting the port type
|
||||
* @bus: a pointer to the &struct sfp_bus structure for the sfp module
|
||||
* @id: a pointer to the module's &struct sfp_eeprom_id
|
||||
* @support: optional pointer to an array of unsigned long for the
|
||||
* ethtool support mask
|
||||
*
|
||||
* Parse the EEPROM identification given in @id, and return one of
|
||||
* %PORT_TP, %PORT_FIBRE or %PORT_OTHER. If @support is non-%NULL,
|
||||
* also set the ethtool %ETHTOOL_LINK_MODE_xxx_BIT corresponding with
|
||||
* the connector type.
|
||||
*
|
||||
* If the port type is not known, returns %PORT_OTHER.
|
||||
*/
|
||||
int sfp_parse_port(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
|
||||
unsigned long *support)
|
||||
const struct sfp_module_caps *sfp_get_module_caps(struct sfp_bus *bus)
|
||||
{
|
||||
return &bus->caps;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sfp_get_module_caps);
|
||||
|
||||
static void sfp_module_parse_port(struct sfp_bus *bus,
|
||||
const struct sfp_eeprom_id *id)
|
||||
{
|
||||
int port;
|
||||
|
||||
|
|
@ -91,34 +84,26 @@ int sfp_parse_port(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
|
|||
break;
|
||||
}
|
||||
|
||||
if (support) {
|
||||
switch (port) {
|
||||
case PORT_FIBRE:
|
||||
phylink_set(support, FIBRE);
|
||||
break;
|
||||
switch (port) {
|
||||
case PORT_FIBRE:
|
||||
phylink_set(bus->caps.link_modes, FIBRE);
|
||||
break;
|
||||
|
||||
case PORT_TP:
|
||||
phylink_set(support, TP);
|
||||
break;
|
||||
}
|
||||
case PORT_TP:
|
||||
phylink_set(bus->caps.link_modes, TP);
|
||||
break;
|
||||
}
|
||||
|
||||
return port;
|
||||
bus->caps.port = port;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sfp_parse_port);
|
||||
|
||||
/**
|
||||
* sfp_may_have_phy() - indicate whether the module may have a PHY
|
||||
* @bus: a pointer to the &struct sfp_bus structure for the sfp module
|
||||
* @id: a pointer to the module's &struct sfp_eeprom_id
|
||||
*
|
||||
* Parse the EEPROM identification given in @id, and return whether
|
||||
* this module may have a PHY.
|
||||
*/
|
||||
bool sfp_may_have_phy(struct sfp_bus *bus, const struct sfp_eeprom_id *id)
|
||||
static void sfp_module_parse_may_have_phy(struct sfp_bus *bus,
|
||||
const struct sfp_eeprom_id *id)
|
||||
{
|
||||
if (id->base.e1000_base_t)
|
||||
return true;
|
||||
if (id->base.e1000_base_t) {
|
||||
bus->caps.may_have_phy = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (id->base.phys_id != SFF8024_ID_DWDM_SFP) {
|
||||
switch (id->base.extended_cc) {
|
||||
|
|
@ -126,30 +111,20 @@ bool sfp_may_have_phy(struct sfp_bus *bus, const struct sfp_eeprom_id *id)
|
|||
case SFF8024_ECC_10GBASE_T_SR:
|
||||
case SFF8024_ECC_5GBASE_T:
|
||||
case SFF8024_ECC_2_5GBASE_T:
|
||||
return true;
|
||||
bus->caps.may_have_phy = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
bus->caps.may_have_phy = false;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sfp_may_have_phy);
|
||||
|
||||
/**
|
||||
* sfp_parse_support() - Parse the eeprom id for supported link modes
|
||||
* @bus: a pointer to the &struct sfp_bus structure for the sfp module
|
||||
* @id: a pointer to the module's &struct sfp_eeprom_id
|
||||
* @support: pointer to an array of unsigned long for the ethtool support mask
|
||||
* @interfaces: pointer to an array of unsigned long for phy interface modes
|
||||
* mask
|
||||
*
|
||||
* Parse the EEPROM identification information and derive the supported
|
||||
* ethtool link modes for the module.
|
||||
*/
|
||||
void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
|
||||
unsigned long *support, unsigned long *interfaces)
|
||||
static void sfp_module_parse_support(struct sfp_bus *bus,
|
||||
const struct sfp_eeprom_id *id)
|
||||
{
|
||||
unsigned long *interfaces = bus->caps.interfaces;
|
||||
unsigned long *modes = bus->caps.link_modes;
|
||||
unsigned int br_min, br_nom, br_max;
|
||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(modes) = { 0, };
|
||||
|
||||
/* Decode the bitrate information to MBd */
|
||||
br_min = br_nom = br_max = 0;
|
||||
|
|
@ -338,13 +313,21 @@ void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
|
|||
phylink_set(modes, Autoneg);
|
||||
phylink_set(modes, Pause);
|
||||
phylink_set(modes, Asym_Pause);
|
||||
|
||||
if (bus->sfp_quirk && bus->sfp_quirk->modes)
|
||||
bus->sfp_quirk->modes(id, modes, interfaces);
|
||||
|
||||
linkmode_or(support, support, modes);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sfp_parse_support);
|
||||
|
||||
static void sfp_init_module(struct sfp_bus *bus,
|
||||
const struct sfp_eeprom_id *id,
|
||||
const struct sfp_quirk *quirk)
|
||||
{
|
||||
memset(&bus->caps, 0, sizeof(bus->caps));
|
||||
|
||||
sfp_module_parse_support(bus, id);
|
||||
sfp_module_parse_port(bus, id);
|
||||
sfp_module_parse_may_have_phy(bus, id);
|
||||
|
||||
if (quirk && quirk->support)
|
||||
quirk->support(id, &bus->caps);
|
||||
}
|
||||
|
||||
/**
|
||||
* sfp_select_interface() - Select appropriate phy_interface_t mode
|
||||
|
|
@ -794,7 +777,7 @@ int sfp_module_insert(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
|
|||
const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus);
|
||||
int ret = 0;
|
||||
|
||||
bus->sfp_quirk = quirk;
|
||||
sfp_init_module(bus, id, quirk);
|
||||
|
||||
if (ops && ops->module_insert)
|
||||
ret = ops->module_insert(bus->upstream, id);
|
||||
|
|
@ -809,8 +792,6 @@ void sfp_module_remove(struct sfp_bus *bus)
|
|||
|
||||
if (ops && ops->module_remove)
|
||||
ops->module_remove(bus->upstream);
|
||||
|
||||
bus->sfp_quirk = NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sfp_module_remove);
|
||||
|
||||
|
|
|
|||
|
|
@ -440,45 +440,44 @@ static void sfp_fixup_rollball_cc(struct sfp *sfp)
|
|||
}
|
||||
|
||||
static void sfp_quirk_2500basex(const struct sfp_eeprom_id *id,
|
||||
unsigned long *modes,
|
||||
unsigned long *interfaces)
|
||||
struct sfp_module_caps *caps)
|
||||
{
|
||||
linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseX_Full_BIT, modes);
|
||||
__set_bit(PHY_INTERFACE_MODE_2500BASEX, interfaces);
|
||||
linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseX_Full_BIT,
|
||||
caps->link_modes);
|
||||
__set_bit(PHY_INTERFACE_MODE_2500BASEX, caps->interfaces);
|
||||
}
|
||||
|
||||
static void sfp_quirk_disable_autoneg(const struct sfp_eeprom_id *id,
|
||||
unsigned long *modes,
|
||||
unsigned long *interfaces)
|
||||
struct sfp_module_caps *caps)
|
||||
{
|
||||
linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, modes);
|
||||
linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, caps->link_modes);
|
||||
}
|
||||
|
||||
static void sfp_quirk_oem_2_5g(const struct sfp_eeprom_id *id,
|
||||
unsigned long *modes,
|
||||
unsigned long *interfaces)
|
||||
struct sfp_module_caps *caps)
|
||||
{
|
||||
/* Copper 2.5G SFP */
|
||||
linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, modes);
|
||||
__set_bit(PHY_INTERFACE_MODE_2500BASEX, interfaces);
|
||||
sfp_quirk_disable_autoneg(id, modes, interfaces);
|
||||
linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
|
||||
caps->link_modes);
|
||||
__set_bit(PHY_INTERFACE_MODE_2500BASEX, caps->interfaces);
|
||||
sfp_quirk_disable_autoneg(id, caps);
|
||||
}
|
||||
|
||||
static void sfp_quirk_ubnt_uf_instant(const struct sfp_eeprom_id *id,
|
||||
unsigned long *modes,
|
||||
unsigned long *interfaces)
|
||||
struct sfp_module_caps *caps)
|
||||
{
|
||||
/* Ubiquiti U-Fiber Instant module claims that support all transceiver
|
||||
* types including 10G Ethernet which is not truth. So clear all claimed
|
||||
* modes and set only one mode which module supports: 1000baseX_Full.
|
||||
*/
|
||||
linkmode_zero(modes);
|
||||
linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, modes);
|
||||
linkmode_zero(caps->link_modes);
|
||||
linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT,
|
||||
caps->link_modes);
|
||||
}
|
||||
|
||||
#define SFP_QUIRK(_v, _p, _m, _f) \
|
||||
{ .vendor = _v, .part = _p, .modes = _m, .fixup = _f, }
|
||||
#define SFP_QUIRK_M(_v, _p, _m) SFP_QUIRK(_v, _p, _m, NULL)
|
||||
#define SFP_QUIRK(_v, _p, _s, _f) \
|
||||
{ .vendor = _v, .part = _p, .support = _s, .fixup = _f, }
|
||||
#define SFP_QUIRK_S(_v, _p, _s) SFP_QUIRK(_v, _p, _s, NULL)
|
||||
#define SFP_QUIRK_F(_v, _p, _f) SFP_QUIRK(_v, _p, NULL, _f)
|
||||
|
||||
static const struct sfp_quirk sfp_quirks[] = {
|
||||
|
|
@ -514,7 +513,7 @@ static const struct sfp_quirk sfp_quirks[] = {
|
|||
|
||||
// HG MXPD-483II-F 2.5G supports 2500Base-X, but incorrectly reports
|
||||
// 2600MBd in their EERPOM
|
||||
SFP_QUIRK_M("HG GENUINE", "MXPD-483II", sfp_quirk_2500basex),
|
||||
SFP_QUIRK_S("HG GENUINE", "MXPD-483II", sfp_quirk_2500basex),
|
||||
|
||||
// Huawei MA5671A can operate at 2500base-X, but report 1.2GBd NRZ in
|
||||
// their EEPROM
|
||||
|
|
@ -523,9 +522,9 @@ static const struct sfp_quirk sfp_quirks[] = {
|
|||
|
||||
// Lantech 8330-262D-E can operate at 2500base-X, but incorrectly report
|
||||
// 2500MBd NRZ in their EEPROM
|
||||
SFP_QUIRK_M("Lantech", "8330-262D-E", sfp_quirk_2500basex),
|
||||
SFP_QUIRK_S("Lantech", "8330-262D-E", sfp_quirk_2500basex),
|
||||
|
||||
SFP_QUIRK_M("UBNT", "UF-INSTANT", sfp_quirk_ubnt_uf_instant),
|
||||
SFP_QUIRK_S("UBNT", "UF-INSTANT", sfp_quirk_ubnt_uf_instant),
|
||||
|
||||
// Walsun HXSX-ATR[CI]-1 don't identify as copper, and use the
|
||||
// Rollball protocol to talk to the PHY.
|
||||
|
|
@ -538,9 +537,9 @@ static const struct sfp_quirk sfp_quirks[] = {
|
|||
SFP_QUIRK_F("OEM", "SFP-GE-T", sfp_fixup_ignore_tx_fault),
|
||||
|
||||
SFP_QUIRK_F("OEM", "SFP-10G-T", sfp_fixup_rollball_cc),
|
||||
SFP_QUIRK_M("OEM", "SFP-2.5G-T", sfp_quirk_oem_2_5g),
|
||||
SFP_QUIRK_M("OEM", "SFP-2.5G-BX10-D", sfp_quirk_2500basex),
|
||||
SFP_QUIRK_M("OEM", "SFP-2.5G-BX10-U", sfp_quirk_2500basex),
|
||||
SFP_QUIRK_S("OEM", "SFP-2.5G-T", sfp_quirk_oem_2_5g),
|
||||
SFP_QUIRK_S("OEM", "SFP-2.5G-BX10-D", sfp_quirk_2500basex),
|
||||
SFP_QUIRK_S("OEM", "SFP-2.5G-BX10-U", sfp_quirk_2500basex),
|
||||
SFP_QUIRK_F("OEM", "RTSFP-10", sfp_fixup_rollball_cc),
|
||||
SFP_QUIRK_F("OEM", "RTSFP-10G", sfp_fixup_rollball_cc),
|
||||
SFP_QUIRK_F("Turris", "RTSFP-2.5G", sfp_fixup_rollball),
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ struct sfp;
|
|||
struct sfp_quirk {
|
||||
const char *vendor;
|
||||
const char *part;
|
||||
void (*modes)(const struct sfp_eeprom_id *id, unsigned long *modes,
|
||||
unsigned long *interfaces);
|
||||
void (*support)(const struct sfp_eeprom_id *id,
|
||||
struct sfp_module_caps *caps);
|
||||
void (*fixup)(struct sfp *sfp);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -169,6 +169,11 @@ static inline bool phy_interface_empty(const unsigned long *intf)
|
|||
return bitmap_empty(intf, PHY_INTERFACE_MODE_MAX);
|
||||
}
|
||||
|
||||
static inline void phy_interface_copy(unsigned long *d, const unsigned long *s)
|
||||
{
|
||||
bitmap_copy(d, s, PHY_INTERFACE_MODE_MAX);
|
||||
}
|
||||
|
||||
static inline unsigned int phy_interface_weight(const unsigned long *intf)
|
||||
{
|
||||
return bitmap_weight(intf, PHY_INTERFACE_MODE_MAX);
|
||||
|
|
|
|||
|
|
@ -521,6 +521,28 @@ struct ethtool_eeprom;
|
|||
struct ethtool_modinfo;
|
||||
struct sfp_bus;
|
||||
|
||||
/**
|
||||
* struct sfp_module_caps - sfp module capabilities
|
||||
* @interfaces: bitmap of interfaces that the module may support
|
||||
* @link_modes: bitmap of ethtool link modes that the module may support
|
||||
*/
|
||||
struct sfp_module_caps {
|
||||
DECLARE_PHY_INTERFACE_MASK(interfaces);
|
||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(link_modes);
|
||||
/**
|
||||
* @may_have_phy: indicate whether the module may have an ethernet PHY
|
||||
* There is no way to be sure that a module has a PHY as the EEPROM
|
||||
* doesn't contain this information. When set, this does not mean that
|
||||
* the module definitely has a PHY.
|
||||
*/
|
||||
bool may_have_phy;
|
||||
/**
|
||||
* @port: one of ethtool %PORT_* definitions, parsed from the module
|
||||
* EEPROM, or %PORT_OTHER if the port type is not known.
|
||||
*/
|
||||
u8 port;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sfp_upstream_ops - upstream operations structure
|
||||
* @attach: called when the sfp socket driver is bound to the upstream
|
||||
|
|
@ -554,11 +576,7 @@ struct sfp_upstream_ops {
|
|||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_SFP)
|
||||
int sfp_parse_port(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
|
||||
unsigned long *support);
|
||||
bool sfp_may_have_phy(struct sfp_bus *bus, const struct sfp_eeprom_id *id);
|
||||
void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
|
||||
unsigned long *support, unsigned long *interfaces);
|
||||
const struct sfp_module_caps *sfp_get_module_caps(struct sfp_bus *bus);
|
||||
phy_interface_t sfp_select_interface(struct sfp_bus *bus,
|
||||
const unsigned long *link_modes);
|
||||
|
||||
|
|
@ -578,24 +596,10 @@ int sfp_bus_add_upstream(struct sfp_bus *bus, void *upstream,
|
|||
void sfp_bus_del_upstream(struct sfp_bus *bus);
|
||||
const char *sfp_get_name(struct sfp_bus *bus);
|
||||
#else
|
||||
static inline int sfp_parse_port(struct sfp_bus *bus,
|
||||
const struct sfp_eeprom_id *id,
|
||||
unsigned long *support)
|
||||
{
|
||||
return PORT_OTHER;
|
||||
}
|
||||
|
||||
static inline bool sfp_may_have_phy(struct sfp_bus *bus,
|
||||
const struct sfp_eeprom_id *id)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void sfp_parse_support(struct sfp_bus *bus,
|
||||
const struct sfp_eeprom_id *id,
|
||||
unsigned long *support,
|
||||
unsigned long *interfaces)
|
||||
static inline const struct sfp_module_caps *
|
||||
sfp_get_module_caps(struct sfp_bus *bus)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline phy_interface_t sfp_select_interface(struct sfp_bus *bus,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user