Commit 643510ce authored by Jakub Kicinski's avatar Jakub Kicinski

Merge branch 'net-sfp-add-support-for-control-of-rate-selection'

Russell King says:

====================
net: sfp: add support for control of rate selection

This series introduces control of the rate selection SFP pins (or
their soft state in the I2C diagnostics EEPROM). Several SNIA documents
(referenced in the commits) describe the various different modes for
these, and we implement them all for maximum compatibility, but as
we know, SFP modules tend to do their own thing, so that may not be
sufficient.

In order to implement this, we need to change the locking arrangement
in the SFP layer - we need to make st_mutex (state mutex) able to be
taken from within the rtnl lock and sm_mutex (state machine mutex).
Essentially, st_mutex protects the hard (gpio) and soft state signals.

So, patches 2 through 5 rejig the locking so that st_mutex is only
ever taken when we want to fiddle with the signal state variables,
read or write the GPIOs, or read or write the soft state.

Patch 1 adds a helper that makes the locking rejig a little easier
as it combines the update of sfp->state with setting the updated
control state to the module.

Patch 6 adds code to phylink to give the signalling rate for various
PHY interface modes that are relevant to SFPs - this is the baud rate
of the encoded signal, not the data rate, which is what matters for
SFPs. This rate is passed through the SFP bus layer into the SFP
socket driver, which initially has a stub sfp_set_signal_rate().

Patch 7 adds the code to the SFP socket driver to parse the rate
selection data in the EEPROM, configure which RS signals need to be
driven, and the signalling rate threshold. We fill in
sfp_set_signal_rate() to set the rate select pins as appropriate.
====================

Link: https://lore.kernel.org/r/ZGSuTY8GqjM+sqta@shell.armlinux.org.ukSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 90223c11 fc082b39
......@@ -156,6 +156,23 @@ static const char *phylink_an_mode_str(unsigned int mode)
return mode < ARRAY_SIZE(modestr) ? modestr[mode] : "unknown";
}
static unsigned int phylink_interface_signal_rate(phy_interface_t interface)
{
switch (interface) {
case PHY_INTERFACE_MODE_SGMII:
case PHY_INTERFACE_MODE_1000BASEX: /* 1.25Mbd */
return 1250;
case PHY_INTERFACE_MODE_2500BASEX: /* 3.125Mbd */
return 3125;
case PHY_INTERFACE_MODE_5GBASER: /* 5.15625Mbd */
return 5156;
case PHY_INTERFACE_MODE_10GBASER: /* 10.3125Mbd */
return 10313;
default:
return 0;
}
}
/**
* phylink_interface_max_speed() - get the maximum speed of a phy interface
* @interface: phy interface mode defined by &typedef phy_interface_t
......@@ -1025,6 +1042,7 @@ static void phylink_major_config(struct phylink *pl, bool restart,
{
struct phylink_pcs *pcs = NULL;
bool pcs_changed = false;
unsigned int rate_kbd;
int err;
phylink_dbg(pl, "major config %s\n", phy_modes(state->interface));
......@@ -1084,6 +1102,12 @@ static void phylink_major_config(struct phylink *pl, bool restart,
ERR_PTR(err));
}
if (pl->sfp_bus) {
rate_kbd = phylink_interface_signal_rate(state->interface);
if (rate_kbd)
sfp_upstream_set_signal_rate(pl->sfp_bus, rate_kbd);
}
phylink_pcs_poll_start(pl);
}
......
......@@ -575,6 +575,26 @@ static void sfp_upstream_clear(struct sfp_bus *bus)
bus->upstream = NULL;
}
/**
* sfp_upstream_set_signal_rate() - set data signalling rate
* @bus: a pointer to the &struct sfp_bus structure for the sfp module
* @rate_kbd: signalling rate in units of 1000 baud
*
* Configure the rate select settings on the SFP module for the signalling
* rate (not the same as the data rate).
*
* Locks that may be held:
* Phylink's state_mutex
* rtnl lock
* SFP's sm_mutex
*/
void sfp_upstream_set_signal_rate(struct sfp_bus *bus, unsigned int rate_kbd)
{
if (bus->registered)
bus->socket_ops->set_signal_rate(bus->sfp, rate_kbd);
}
EXPORT_SYMBOL_GPL(sfp_upstream_set_signal_rate);
/**
* sfp_bus_find_fwnode() - parse and locate the SFP bus from fwnode
* @fwnode: firmware node for the parent device (MAC or PHY)
......
......@@ -24,14 +24,18 @@ enum {
GPIO_LOS,
GPIO_TX_FAULT,
GPIO_TX_DISABLE,
GPIO_RATE_SELECT,
GPIO_RS0,
GPIO_RS1,
GPIO_MAX,
SFP_F_PRESENT = BIT(GPIO_MODDEF0),
SFP_F_LOS = BIT(GPIO_LOS),
SFP_F_TX_FAULT = BIT(GPIO_TX_FAULT),
SFP_F_TX_DISABLE = BIT(GPIO_TX_DISABLE),
SFP_F_RATE_SELECT = BIT(GPIO_RATE_SELECT),
SFP_F_RS0 = BIT(GPIO_RS0),
SFP_F_RS1 = BIT(GPIO_RS1),
SFP_F_OUTPUTS = SFP_F_TX_DISABLE | SFP_F_RS0 | SFP_F_RS1,
SFP_E_INSERT = 0,
SFP_E_REMOVE,
......@@ -148,6 +152,7 @@ static const char *gpio_names[] = {
"tx-fault",
"tx-disable",
"rate-select0",
"rate-select1",
};
static const enum gpiod_flags gpio_flags[] = {
......@@ -156,6 +161,7 @@ static const enum gpiod_flags gpio_flags[] = {
GPIOD_IN,
GPIOD_ASIS,
GPIOD_ASIS,
GPIOD_ASIS,
};
/* t_start_up (SFF-8431) or t_init (SFF-8472) is the time required for a
......@@ -242,10 +248,18 @@ struct sfp {
bool need_poll;
/* Access rules:
* state_hw_drive: st_mutex held
* state_hw_mask: st_mutex held
* state_soft_mask: st_mutex held
* state: st_mutex held unless reading input bits
*/
struct mutex st_mutex; /* Protects state */
unsigned int state_hw_drive;
unsigned int state_hw_mask;
unsigned int state_soft_mask;
unsigned int state;
struct delayed_work poll;
struct delayed_work timeout;
struct mutex sm_mutex; /* Protects state machine */
......@@ -262,6 +276,10 @@ struct sfp {
unsigned int module_t_start_up;
unsigned int module_t_wait;
unsigned int rate_kbd;
unsigned int rs_threshold_kbd;
unsigned int rs_state_mask;
bool have_a2;
bool tx_fault_ignore;
......@@ -312,7 +330,7 @@ static bool sfp_module_supported(const struct sfp_eeprom_id *id)
static const struct sff_data sfp_data = {
.gpios = SFP_F_PRESENT | SFP_F_LOS | SFP_F_TX_FAULT |
SFP_F_TX_DISABLE | SFP_F_RATE_SELECT,
SFP_F_TX_DISABLE | SFP_F_RS0 | SFP_F_RS1,
.module_supported = sfp_module_supported,
};
......@@ -500,20 +518,37 @@ static unsigned int sff_gpio_get_state(struct sfp *sfp)
static void sfp_gpio_set_state(struct sfp *sfp, unsigned int state)
{
if (state & SFP_F_PRESENT) {
/* If the module is present, drive the signals */
if (sfp->gpio[GPIO_TX_DISABLE])
unsigned int drive;
if (state & SFP_F_PRESENT)
/* If the module is present, drive the requested signals */
drive = sfp->state_hw_drive;
else
/* Otherwise, let them float to the pull-ups */
drive = 0;
if (sfp->gpio[GPIO_TX_DISABLE]) {
if (drive & SFP_F_TX_DISABLE)
gpiod_direction_output(sfp->gpio[GPIO_TX_DISABLE],
state & SFP_F_TX_DISABLE);
if (state & SFP_F_RATE_SELECT)
gpiod_direction_output(sfp->gpio[GPIO_RATE_SELECT],
state & SFP_F_RATE_SELECT);
} else {
/* Otherwise, let them float to the pull-ups */
if (sfp->gpio[GPIO_TX_DISABLE])
else
gpiod_direction_input(sfp->gpio[GPIO_TX_DISABLE]);
if (state & SFP_F_RATE_SELECT)
gpiod_direction_input(sfp->gpio[GPIO_RATE_SELECT]);
}
if (sfp->gpio[GPIO_RS0]) {
if (drive & SFP_F_RS0)
gpiod_direction_output(sfp->gpio[GPIO_RS0],
state & SFP_F_RS0);
else
gpiod_direction_input(sfp->gpio[GPIO_RS0]);
}
if (sfp->gpio[GPIO_RS1]) {
if (drive & SFP_F_RS1)
gpiod_direction_output(sfp->gpio[GPIO_RS1],
state & SFP_F_RS1);
else
gpiod_direction_input(sfp->gpio[GPIO_RS1]);
}
}
......@@ -675,16 +710,33 @@ static unsigned int sfp_soft_get_state(struct sfp *sfp)
return state & sfp->state_soft_mask;
}
static void sfp_soft_set_state(struct sfp *sfp, unsigned int state)
static void sfp_soft_set_state(struct sfp *sfp, unsigned int state,
unsigned int soft)
{
u8 mask = SFP_STATUS_TX_DISABLE_FORCE;
u8 mask = 0;
u8 val = 0;
if (soft & SFP_F_TX_DISABLE)
mask |= SFP_STATUS_TX_DISABLE_FORCE;
if (state & SFP_F_TX_DISABLE)
val |= SFP_STATUS_TX_DISABLE_FORCE;
if (soft & SFP_F_RS0)
mask |= SFP_STATUS_RS0_SELECT;
if (state & SFP_F_RS0)
val |= SFP_STATUS_RS0_SELECT;
if (mask)
sfp_modify_u8(sfp, true, SFP_STATUS, mask, val);
val = mask = 0;
if (soft & SFP_F_RS1)
mask |= SFP_EXT_STATUS_RS1_SELECT;
if (state & SFP_F_RS1)
val |= SFP_EXT_STATUS_RS1_SELECT;
sfp_modify_u8(sfp, true, SFP_STATUS, mask, val);
if (mask)
sfp_modify_u8(sfp, true, SFP_EXT_STATUS, mask, val);
}
static void sfp_soft_start_poll(struct sfp *sfp)
......@@ -692,27 +744,35 @@ static void sfp_soft_start_poll(struct sfp *sfp)
const struct sfp_eeprom_id *id = &sfp->id;
unsigned int mask = 0;
sfp->state_soft_mask = 0;
if (id->ext.enhopts & SFP_ENHOPTS_SOFT_TX_DISABLE)
mask |= SFP_F_TX_DISABLE;
if (id->ext.enhopts & SFP_ENHOPTS_SOFT_TX_FAULT)
mask |= SFP_F_TX_FAULT;
if (id->ext.enhopts & SFP_ENHOPTS_SOFT_RX_LOS)
mask |= SFP_F_LOS;
if (id->ext.enhopts & SFP_ENHOPTS_SOFT_RATE_SELECT)
mask |= sfp->rs_state_mask;
mutex_lock(&sfp->st_mutex);
// Poll the soft state for hardware pins we want to ignore
sfp->state_soft_mask = ~sfp->state_hw_mask & mask;
if (sfp->state_soft_mask & (SFP_F_LOS | SFP_F_TX_FAULT) &&
!sfp->need_poll)
mod_delayed_work(system_wq, &sfp->poll, poll_jiffies);
mutex_unlock(&sfp->st_mutex);
}
static void sfp_soft_stop_poll(struct sfp *sfp)
{
mutex_lock(&sfp->st_mutex);
sfp->state_soft_mask = 0;
mutex_unlock(&sfp->st_mutex);
}
/* sfp_get_state() - must be called with st_mutex held, or in the
* initialisation path.
*/
static unsigned int sfp_get_state(struct sfp *sfp)
{
unsigned int soft = sfp->state_soft_mask & (SFP_F_LOS | SFP_F_TX_FAULT);
......@@ -725,13 +785,26 @@ static unsigned int sfp_get_state(struct sfp *sfp)
return state;
}
/* sfp_set_state() - must be called with st_mutex held, or in the
* initialisation path.
*/
static void sfp_set_state(struct sfp *sfp, unsigned int state)
{
unsigned int soft;
sfp->set_state(sfp, state);
if (state & SFP_F_PRESENT &&
sfp->state_soft_mask & SFP_F_TX_DISABLE)
sfp_soft_set_state(sfp, state);
soft = sfp->state_soft_mask & SFP_F_OUTPUTS;
if (state & SFP_F_PRESENT && soft)
sfp_soft_set_state(sfp, state, soft);
}
static void sfp_mod_state(struct sfp *sfp, unsigned int mask, unsigned int set)
{
mutex_lock(&sfp->st_mutex);
sfp->state = (sfp->state & ~mask) | set;
sfp_set_state(sfp, sfp->state);
mutex_unlock(&sfp->st_mutex);
}
static unsigned int sfp_check(void *buf, size_t len)
......@@ -1537,16 +1610,14 @@ static void sfp_module_tx_disable(struct sfp *sfp)
{
dev_dbg(sfp->dev, "tx disable %u -> %u\n",
sfp->state & SFP_F_TX_DISABLE ? 1 : 0, 1);
sfp->state |= SFP_F_TX_DISABLE;
sfp_set_state(sfp, sfp->state);
sfp_mod_state(sfp, SFP_F_TX_DISABLE, SFP_F_TX_DISABLE);
}
static void sfp_module_tx_enable(struct sfp *sfp)
{
dev_dbg(sfp->dev, "tx disable %u -> %u\n",
sfp->state & SFP_F_TX_DISABLE ? 1 : 0, 0);
sfp->state &= ~SFP_F_TX_DISABLE;
sfp_set_state(sfp, sfp->state);
sfp_mod_state(sfp, SFP_F_TX_DISABLE, 0);
}
#if IS_ENABLED(CONFIG_DEBUG_FS)
......@@ -1567,10 +1638,15 @@ static int sfp_debug_state_show(struct seq_file *s, void *data)
sfp->sm_fault_retries);
seq_printf(s, "PHY probe remaining retries: %d\n",
sfp->sm_phy_retries);
seq_printf(s, "Signalling rate: %u kBd\n", sfp->rate_kbd);
seq_printf(s, "Rate select threshold: %u kBd\n",
sfp->rs_threshold_kbd);
seq_printf(s, "moddef0: %d\n", !!(sfp->state & SFP_F_PRESENT));
seq_printf(s, "rx_los: %d\n", !!(sfp->state & SFP_F_LOS));
seq_printf(s, "tx_fault: %d\n", !!(sfp->state & SFP_F_TX_FAULT));
seq_printf(s, "tx_disable: %d\n", !!(sfp->state & SFP_F_TX_DISABLE));
seq_printf(s, "rs0: %d\n", !!(sfp->state & SFP_F_RS0));
seq_printf(s, "rs1: %d\n", !!(sfp->state & SFP_F_RS1));
return 0;
}
DEFINE_SHOW_ATTRIBUTE(sfp_debug_state);
......@@ -1599,16 +1675,18 @@ static void sfp_debugfs_exit(struct sfp *sfp)
static void sfp_module_tx_fault_reset(struct sfp *sfp)
{
unsigned int state = sfp->state;
if (state & SFP_F_TX_DISABLE)
return;
unsigned int state;
sfp_set_state(sfp, state | SFP_F_TX_DISABLE);
mutex_lock(&sfp->st_mutex);
state = sfp->state;
if (!(state & SFP_F_TX_DISABLE)) {
sfp_set_state(sfp, state | SFP_F_TX_DISABLE);
udelay(T_RESET_US);
udelay(T_RESET_US);
sfp_set_state(sfp, state);
sfp_set_state(sfp, state);
}
mutex_unlock(&sfp->st_mutex);
}
/* SFP state machine */
......@@ -1874,6 +1952,95 @@ static int sfp_sm_mod_hpower(struct sfp *sfp, bool enable)
return 0;
}
static void sfp_module_parse_rate_select(struct sfp *sfp)
{
u8 rate_id;
sfp->rs_threshold_kbd = 0;
sfp->rs_state_mask = 0;
if (!(sfp->id.ext.options & cpu_to_be16(SFP_OPTIONS_RATE_SELECT)))
/* No support for RateSelect */
return;
/* Default to INF-8074 RateSelect operation. The signalling threshold
* rate is not well specified, so always select "Full Bandwidth", but
* SFF-8079 reveals that it is understood that RS0 will be low for
* 1.0625Gb/s and high for 2.125Gb/s. Choose a value half-way between.
* This method exists prior to SFF-8472.
*/
sfp->rs_state_mask = SFP_F_RS0;
sfp->rs_threshold_kbd = 1594;
/* Parse the rate identifier, which is complicated due to history:
* SFF-8472 rev 9.5 marks this field as reserved.
* SFF-8079 references SFF-8472 rev 9.5 and defines bit 0. SFF-8472
* compliance is not required.
* SFF-8472 rev 10.2 defines this field using values 0..4
* SFF-8472 rev 11.0 redefines this field with bit 0 for SFF-8079
* and even values.
*/
rate_id = sfp->id.base.rate_id;
if (rate_id == 0)
/* Unspecified */
return;
/* SFF-8472 rev 10.0..10.4 did not account for SFF-8079 using bit 0,
* and allocated value 3 to SFF-8431 independent tx/rx rate select.
* Convert this to a SFF-8472 rev 11.0 rate identifier.
*/
if (sfp->id.ext.sff8472_compliance >= SFP_SFF8472_COMPLIANCE_REV10_2 &&
sfp->id.ext.sff8472_compliance < SFP_SFF8472_COMPLIANCE_REV11_0 &&
rate_id == 3)
rate_id = SFF_RID_8431;
if (rate_id & SFF_RID_8079) {
/* SFF-8079 RateSelect / Application Select in conjunction with
* SFF-8472 rev 9.5. SFF-8079 defines rate_id as a bitfield
* with only bit 0 used, which takes precedence over SFF-8472.
*/
if (!(sfp->id.ext.enhopts & SFP_ENHOPTS_APP_SELECT_SFF8079)) {
/* SFF-8079 Part 1 - rate selection between Fibre
* Channel 1.0625/2.125/4.25 Gbd modes. Note that RS0
* is high for 2125, so we have to subtract 1 to
* include it.
*/
sfp->rs_threshold_kbd = 2125 - 1;
sfp->rs_state_mask = SFP_F_RS0;
}
return;
}
/* SFF-8472 rev 9.5 does not define the rate identifier */
if (sfp->id.ext.sff8472_compliance <= SFP_SFF8472_COMPLIANCE_REV9_5)
return;
/* SFF-8472 rev 11.0 defines rate_id as a numerical value which will
* always have bit 0 clear due to SFF-8079's bitfield usage of rate_id.
*/
switch (rate_id) {
case SFF_RID_8431_RX_ONLY:
sfp->rs_threshold_kbd = 4250;
sfp->rs_state_mask = SFP_F_RS0;
break;
case SFF_RID_8431_TX_ONLY:
sfp->rs_threshold_kbd = 4250;
sfp->rs_state_mask = SFP_F_RS1;
break;
case SFF_RID_8431:
sfp->rs_threshold_kbd = 4250;
sfp->rs_state_mask = SFP_F_RS0 | SFP_F_RS1;
break;
case SFF_RID_10G8G:
sfp->rs_threshold_kbd = 9000;
sfp->rs_state_mask = SFP_F_RS0 | SFP_F_RS1;
break;
}
}
/* GPON modules based on Realtek RTL8672 and RTL9601C chips (e.g. V-SOL
* V2801F, CarlitoxxPro CPGOS03-0490, Ubiquiti U-Fiber Instant, ...) do
* not support multibyte reads from the EEPROM. Each multi-byte read
......@@ -1953,6 +2120,7 @@ static int sfp_sm_mod_probe(struct sfp *sfp, bool report)
/* SFP module inserted - read I2C data */
struct sfp_eeprom_id id;
bool cotsworks_sfbg;
unsigned int mask;
bool cotsworks;
u8 check;
int ret;
......@@ -2092,14 +2260,19 @@ static int sfp_sm_mod_probe(struct sfp *sfp, bool report)
if (ret < 0)
return ret;
/* Initialise state bits to use from hardware */
sfp->state_hw_mask = SFP_F_PRESENT;
sfp_module_parse_rate_select(sfp);
mask = SFP_F_PRESENT;
if (sfp->gpio[GPIO_TX_DISABLE])
sfp->state_hw_mask |= SFP_F_TX_DISABLE;
mask |= SFP_F_TX_DISABLE;
if (sfp->gpio[GPIO_TX_FAULT])
sfp->state_hw_mask |= SFP_F_TX_FAULT;
mask |= SFP_F_TX_FAULT;
if (sfp->gpio[GPIO_LOS])
sfp->state_hw_mask |= SFP_F_LOS;
mask |= SFP_F_LOS;
if (sfp->gpio[GPIO_RS0])
mask |= SFP_F_RS0;
if (sfp->gpio[GPIO_RS1])
mask |= SFP_F_RS1;
sfp->module_t_start_up = T_START_UP;
sfp->module_t_wait = T_WAIT;
......@@ -2117,8 +2290,17 @@ static int sfp_sm_mod_probe(struct sfp *sfp, bool report)
sfp->mdio_protocol = MDIO_I2C_NONE;
sfp->quirk = sfp_lookup_quirk(&id);
mutex_lock(&sfp->st_mutex);
/* Initialise state bits to use from hardware */
sfp->state_hw_mask = mask;
/* We want to drive the rate select pins that the module is using */
sfp->state_hw_drive |= sfp->rs_state_mask;
if (sfp->quirk && sfp->quirk->fixup)
sfp->quirk->fixup(sfp);
mutex_unlock(&sfp->st_mutex);
return 0;
}
......@@ -2132,6 +2314,7 @@ static void sfp_sm_mod_remove(struct sfp *sfp)
memset(&sfp->id, 0, sizeof(sfp->id));
sfp->module_power_mW = 0;
sfp->state_hw_drive = SFP_F_TX_DISABLE;
sfp->have_a2 = false;
dev_info(sfp->dev, "module removed\n");
......@@ -2452,10 +2635,8 @@ static void sfp_sm_main(struct sfp *sfp, unsigned int event)
}
}
static void sfp_sm_event(struct sfp *sfp, unsigned int event)
static void __sfp_sm_event(struct sfp *sfp, unsigned int event)
{
mutex_lock(&sfp->sm_mutex);
dev_dbg(sfp->dev, "SM: enter %s:%s:%s event %s\n",
mod_state_to_str(sfp->sm_mod_state),
dev_state_to_str(sfp->sm_dev_state),
......@@ -2470,7 +2651,12 @@ static void sfp_sm_event(struct sfp *sfp, unsigned int event)
mod_state_to_str(sfp->sm_mod_state),
dev_state_to_str(sfp->sm_dev_state),
sm_state_to_str(sfp->sm_state));
}
static void sfp_sm_event(struct sfp *sfp, unsigned int event)
{
mutex_lock(&sfp->sm_mutex);
__sfp_sm_event(sfp, event);
mutex_unlock(&sfp->sm_mutex);
}
......@@ -2494,6 +2680,20 @@ static void sfp_stop(struct sfp *sfp)
sfp_sm_event(sfp, SFP_E_DEV_DOWN);
}
static void sfp_set_signal_rate(struct sfp *sfp, unsigned int rate_kbd)
{
unsigned int set;
sfp->rate_kbd = rate_kbd;
if (rate_kbd > sfp->rs_threshold_kbd)
set = sfp->rs_state_mask;
else
set = 0;
sfp_mod_state(sfp, SFP_F_RS0 | SFP_F_RS1, set);
}
static int sfp_module_info(struct sfp *sfp, struct ethtool_modinfo *modinfo)
{
/* locking... and check module is present */
......@@ -2578,6 +2778,7 @@ static const struct sfp_socket_ops sfp_module_ops = {
.detach = sfp_detach,
.start = sfp_start,
.stop = sfp_stop,
.set_signal_rate = sfp_set_signal_rate,
.module_info = sfp_module_info,
.module_eeprom = sfp_module_eeprom,
.module_eeprom_by_page = sfp_module_eeprom_by_page,
......@@ -2596,6 +2797,7 @@ static void sfp_check_state(struct sfp *sfp)
{
unsigned int state, i, changed;
rtnl_lock();
mutex_lock(&sfp->st_mutex);
state = sfp_get_state(sfp);
changed = state ^ sfp->state;
......@@ -2609,23 +2811,24 @@ static void sfp_check_state(struct sfp *sfp)
dev_dbg(sfp->dev, "%s %u -> %u\n", gpio_names[i],
!!(sfp->state & BIT(i)), !!(state & BIT(i)));
state |= sfp->state & (SFP_F_TX_DISABLE | SFP_F_RATE_SELECT);
state |= sfp->state & SFP_F_OUTPUTS;
sfp->state = state;
mutex_unlock(&sfp->st_mutex);
rtnl_lock();
mutex_lock(&sfp->sm_mutex);
if (changed & SFP_F_PRESENT)
sfp_sm_event(sfp, state & SFP_F_PRESENT ?
SFP_E_INSERT : SFP_E_REMOVE);
__sfp_sm_event(sfp, state & SFP_F_PRESENT ?
SFP_E_INSERT : SFP_E_REMOVE);
if (changed & SFP_F_TX_FAULT)
sfp_sm_event(sfp, state & SFP_F_TX_FAULT ?
SFP_E_TX_FAULT : SFP_E_TX_CLEAR);
__sfp_sm_event(sfp, state & SFP_F_TX_FAULT ?
SFP_E_TX_FAULT : SFP_E_TX_CLEAR);
if (changed & SFP_F_LOS)
sfp_sm_event(sfp, state & SFP_F_LOS ?
SFP_E_LOS_HIGH : SFP_E_LOS_LOW);
__sfp_sm_event(sfp, state & SFP_F_LOS ?
SFP_E_LOS_HIGH : SFP_E_LOS_LOW);
mutex_unlock(&sfp->sm_mutex);
rtnl_unlock();
mutex_unlock(&sfp->st_mutex);
}
static irqreturn_t sfp_irq(int irq, void *data)
......@@ -2643,6 +2846,8 @@ static void sfp_poll(struct work_struct *work)
sfp_check_state(sfp);
// st_mutex doesn't need to be held here for state_soft_mask,
// it's unimportant if we race while reading this.
if (sfp->state_soft_mask & (SFP_F_LOS | SFP_F_TX_FAULT) ||
sfp->need_poll)
mod_delayed_work(system_wq, &sfp->poll, poll_jiffies);
......@@ -2748,6 +2953,7 @@ static int sfp_probe(struct platform_device *pdev)
}
sfp->state_hw_mask = SFP_F_PRESENT;
sfp->state_hw_drive = SFP_F_TX_DISABLE;
sfp->get_state = sfp_gpio_get_state;
sfp->set_state = sfp_gpio_set_state;
......@@ -2773,9 +2979,9 @@ static int sfp_probe(struct platform_device *pdev)
*/
sfp->state = sfp_get_state(sfp) | SFP_F_TX_DISABLE;
if (sfp->gpio[GPIO_RATE_SELECT] &&
gpiod_get_value_cansleep(sfp->gpio[GPIO_RATE_SELECT]))
sfp->state |= SFP_F_RATE_SELECT;
if (sfp->gpio[GPIO_RS0] &&
gpiod_get_value_cansleep(sfp->gpio[GPIO_RS0]))
sfp->state |= SFP_F_RS0;
sfp_set_state(sfp, sfp->state);
sfp_module_tx_disable(sfp);
if (sfp->state & SFP_F_PRESENT) {
......
......@@ -19,6 +19,7 @@ struct sfp_socket_ops {
void (*detach)(struct sfp *sfp);
void (*start)(struct sfp *sfp);
void (*stop)(struct sfp *sfp);
void (*set_signal_rate)(struct sfp *sfp, unsigned int rate_kbd);
int (*module_info)(struct sfp *sfp, struct ethtool_modinfo *modinfo);
int (*module_eeprom)(struct sfp *sfp, struct ethtool_eeprom *ee,
u8 *data);
......
......@@ -342,6 +342,12 @@ enum {
SFP_ENCODING = 11,
SFP_BR_NOMINAL = 12,
SFP_RATE_ID = 13,
SFF_RID_8079 = 0x01,
SFF_RID_8431_RX_ONLY = 0x02,
SFF_RID_8431_TX_ONLY = 0x04,
SFF_RID_8431 = 0x06,
SFF_RID_10G8G = 0x0e,
SFP_LINK_LEN_SM_KM = 14,
SFP_LINK_LEN_SM_100M = 15,
SFP_LINK_LEN_50UM_OM2_10M = 16,
......@@ -465,6 +471,7 @@ enum {
SFP_STATUS = 110,
SFP_STATUS_TX_DISABLE = BIT(7),
SFP_STATUS_TX_DISABLE_FORCE = BIT(6),
SFP_STATUS_RS0_SELECT = BIT(3),
SFP_STATUS_TX_FAULT = BIT(2),
SFP_STATUS_RX_LOS = BIT(1),
SFP_ALARM0 = 112,
......@@ -496,6 +503,7 @@ enum {
SFP_WARN1_RXPWR_LOW = BIT(6),
SFP_EXT_STATUS = 118,
SFP_EXT_STATUS_RS1_SELECT = BIT(3),
SFP_EXT_STATUS_PWRLVL_SELECT = BIT(0),
SFP_VSL = 120,
......@@ -556,6 +564,7 @@ int sfp_get_module_eeprom_by_page(struct sfp_bus *bus,
struct netlink_ext_ack *extack);
void sfp_upstream_start(struct sfp_bus *bus);
void sfp_upstream_stop(struct sfp_bus *bus);
void sfp_upstream_set_signal_rate(struct sfp_bus *bus, unsigned int rate_kbd);
void sfp_bus_put(struct sfp_bus *bus);
struct sfp_bus *sfp_bus_find_fwnode(const struct fwnode_handle *fwnode);
int sfp_bus_add_upstream(struct sfp_bus *bus, void *upstream,
......@@ -615,6 +624,11 @@ static inline void sfp_upstream_stop(struct sfp_bus *bus)
{
}
static inline void sfp_upstream_set_signal_rate(struct sfp_bus *bus,
unsigned int rate_kbd)
{
}
static inline void sfp_bus_put(struct sfp_bus *bus)
{
}
......
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