Commit e85b1347 authored by Marek Behún's avatar Marek Behún Committed by David S. Miller

net: sfp: create/destroy I2C mdiobus before PHY probe/after PHY release

Instead of configuring the I2C mdiobus when SFP driver is probed,
create/destroy the mdiobus before the PHY is probed for/after it is
released.

This way we can tell the mdio-i2c code which protocol to use for each
SFP transceiver.

Move the code that determines MDIO I2C protocol from
sfp_sm_probe_for_phy() to sfp_sm_mod_probe(), where most of the SFP ID
parsing is done. Don't allocate I2C bus if no PHY is expected.
Signed-off-by: default avatarMarek Behún <kabel@kernel.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 13c8adcf
...@@ -218,6 +218,7 @@ struct sfp { ...@@ -218,6 +218,7 @@ struct sfp {
struct i2c_adapter *i2c; struct i2c_adapter *i2c;
struct mii_bus *i2c_mii; struct mii_bus *i2c_mii;
struct sfp_bus *sfp_bus; struct sfp_bus *sfp_bus;
enum mdio_i2c_proto mdio_protocol;
struct phy_device *mod_phy; struct phy_device *mod_phy;
const struct sff_data *type; const struct sff_data *type;
size_t i2c_block_size; size_t i2c_block_size;
...@@ -530,9 +531,6 @@ static int sfp_i2c_write(struct sfp *sfp, bool a2, u8 dev_addr, void *buf, ...@@ -530,9 +531,6 @@ static int sfp_i2c_write(struct sfp *sfp, bool a2, u8 dev_addr, void *buf,
static int sfp_i2c_configure(struct sfp *sfp, struct i2c_adapter *i2c) static int sfp_i2c_configure(struct sfp *sfp, struct i2c_adapter *i2c)
{ {
struct mii_bus *i2c_mii;
int ret;
if (!i2c_check_functionality(i2c, I2C_FUNC_I2C)) if (!i2c_check_functionality(i2c, I2C_FUNC_I2C))
return -EINVAL; return -EINVAL;
...@@ -540,7 +538,15 @@ static int sfp_i2c_configure(struct sfp *sfp, struct i2c_adapter *i2c) ...@@ -540,7 +538,15 @@ static int sfp_i2c_configure(struct sfp *sfp, struct i2c_adapter *i2c)
sfp->read = sfp_i2c_read; sfp->read = sfp_i2c_read;
sfp->write = sfp_i2c_write; sfp->write = sfp_i2c_write;
i2c_mii = mdio_i2c_alloc(sfp->dev, i2c); return 0;
}
static int sfp_i2c_mdiobus_create(struct sfp *sfp)
{
struct mii_bus *i2c_mii;
int ret;
i2c_mii = mdio_i2c_alloc(sfp->dev, sfp->i2c);
if (IS_ERR(i2c_mii)) if (IS_ERR(i2c_mii))
return PTR_ERR(i2c_mii); return PTR_ERR(i2c_mii);
...@@ -558,6 +564,12 @@ static int sfp_i2c_configure(struct sfp *sfp, struct i2c_adapter *i2c) ...@@ -558,6 +564,12 @@ static int sfp_i2c_configure(struct sfp *sfp, struct i2c_adapter *i2c)
return 0; return 0;
} }
static void sfp_i2c_mdiobus_destroy(struct sfp *sfp)
{
mdiobus_unregister(sfp->i2c_mii);
sfp->i2c_mii = NULL;
}
/* Interface */ /* Interface */
static int sfp_read(struct sfp *sfp, bool a2, u8 addr, void *buf, size_t len) static int sfp_read(struct sfp *sfp, bool a2, u8 addr, void *buf, size_t len)
{ {
...@@ -1674,6 +1686,14 @@ static void sfp_sm_fault(struct sfp *sfp, unsigned int next_state, bool warn) ...@@ -1674,6 +1686,14 @@ static void sfp_sm_fault(struct sfp *sfp, unsigned int next_state, bool warn)
} }
} }
static int sfp_sm_add_mdio_bus(struct sfp *sfp)
{
if (sfp->mdio_protocol != MDIO_I2C_NONE)
return sfp_i2c_mdiobus_create(sfp);
return 0;
}
/* Probe a SFP for a PHY device if the module supports copper - the PHY /* Probe a SFP for a PHY device if the module supports copper - the PHY
* normally sits at I2C bus address 0x56, and may either be a clause 22 * normally sits at I2C bus address 0x56, and may either be a clause 22
* or clause 45 PHY. * or clause 45 PHY.
...@@ -1689,19 +1709,19 @@ static int sfp_sm_probe_for_phy(struct sfp *sfp) ...@@ -1689,19 +1709,19 @@ static int sfp_sm_probe_for_phy(struct sfp *sfp)
{ {
int err = 0; int err = 0;
switch (sfp->id.base.extended_cc) { switch (sfp->mdio_protocol) {
case SFF8024_ECC_10GBASE_T_SFI: case MDIO_I2C_NONE:
case SFF8024_ECC_10GBASE_T_SR:
case SFF8024_ECC_5GBASE_T:
case SFF8024_ECC_2_5GBASE_T:
err = sfp_sm_probe_phy(sfp, true);
break; break;
default: case MDIO_I2C_MARVELL_C22:
if (sfp->id.base.e1000_base_t) err = sfp_sm_probe_phy(sfp, false);
err = sfp_sm_probe_phy(sfp, false); break;
case MDIO_I2C_C45:
err = sfp_sm_probe_phy(sfp, true);
break; break;
} }
return err; return err;
} }
...@@ -2028,6 +2048,16 @@ static int sfp_sm_mod_probe(struct sfp *sfp, bool report) ...@@ -2028,6 +2048,16 @@ static int sfp_sm_mod_probe(struct sfp *sfp, bool report)
sfp->tx_fault_ignore = false; sfp->tx_fault_ignore = false;
if (sfp->id.base.extended_cc == SFF8024_ECC_10GBASE_T_SFI ||
sfp->id.base.extended_cc == SFF8024_ECC_10GBASE_T_SR ||
sfp->id.base.extended_cc == SFF8024_ECC_5GBASE_T ||
sfp->id.base.extended_cc == SFF8024_ECC_2_5GBASE_T)
sfp->mdio_protocol = MDIO_I2C_C45;
else if (sfp->id.base.e1000_base_t)
sfp->mdio_protocol = MDIO_I2C_MARVELL_C22;
else
sfp->mdio_protocol = MDIO_I2C_NONE;
sfp->quirk = sfp_lookup_quirk(&id); sfp->quirk = sfp_lookup_quirk(&id);
if (sfp->quirk && sfp->quirk->fixup) if (sfp->quirk && sfp->quirk->fixup)
sfp->quirk->fixup(sfp); sfp->quirk->fixup(sfp);
...@@ -2204,6 +2234,8 @@ static void sfp_sm_main(struct sfp *sfp, unsigned int event) ...@@ -2204,6 +2234,8 @@ static void sfp_sm_main(struct sfp *sfp, unsigned int event)
sfp_module_stop(sfp->sfp_bus); sfp_module_stop(sfp->sfp_bus);
if (sfp->mod_phy) if (sfp->mod_phy)
sfp_sm_phy_detach(sfp); sfp_sm_phy_detach(sfp);
if (sfp->i2c_mii)
sfp_i2c_mdiobus_destroy(sfp);
sfp_module_tx_disable(sfp); sfp_module_tx_disable(sfp);
sfp_soft_stop_poll(sfp); sfp_soft_stop_poll(sfp);
sfp_sm_next(sfp, SFP_S_DOWN, 0); sfp_sm_next(sfp, SFP_S_DOWN, 0);
...@@ -2266,6 +2298,12 @@ static void sfp_sm_main(struct sfp *sfp, unsigned int event) ...@@ -2266,6 +2298,12 @@ static void sfp_sm_main(struct sfp *sfp, unsigned int event)
sfp->sm_fault_retries == N_FAULT_INIT); sfp->sm_fault_retries == N_FAULT_INIT);
} else if (event == SFP_E_TIMEOUT || event == SFP_E_TX_CLEAR) { } else if (event == SFP_E_TIMEOUT || event == SFP_E_TX_CLEAR) {
init_done: init_done:
/* Create mdiobus and start trying for PHY */
ret = sfp_sm_add_mdio_bus(sfp);
if (ret < 0) {
sfp_sm_next(sfp, SFP_S_FAIL, 0);
break;
}
sfp->sm_phy_retries = R_PHY_RETRY; sfp->sm_phy_retries = R_PHY_RETRY;
goto phy_probe; goto phy_probe;
} }
......
...@@ -11,6 +11,12 @@ struct device; ...@@ -11,6 +11,12 @@ struct device;
struct i2c_adapter; struct i2c_adapter;
struct mii_bus; struct mii_bus;
enum mdio_i2c_proto {
MDIO_I2C_NONE,
MDIO_I2C_MARVELL_C22,
MDIO_I2C_C45,
};
struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c); struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c);
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment