/* t_start_up (SFF-8431) or t_init (SFF-8472) is the time required for a * non-cooled module to initialise its laser safety circuitry. We wait * an initial T_WAIT period before we check the tx fault to give any PHY * on board (for a copper SFP) time to initialise.
*/ #define T_WAIT msecs_to_jiffies(50) #define T_START_UP msecs_to_jiffies(300) #define T_START_UP_BAD_GPON msecs_to_jiffies(60000)
/* t_reset is the time required to assert the TX_DISABLE signal to reset * an indicated TX_FAULT.
*/ #define T_RESET_US 10 #define T_FAULT_RECOVER msecs_to_jiffies(1000)
/* N_FAULT_INIT is the number of recovery attempts at module initialisation * time. If the TX_FAULT signal is not deasserted after this number of * attempts at clearing it, we decide that the module is faulty. * N_FAULT is the same but after the module has initialised.
*/ #define N_FAULT_INIT 5 #define N_FAULT 5
/* T_PHY_RETRY is the time interval between attempts to probe the PHY. * R_PHY_RETRY is the number of attempts.
*/ #define T_PHY_RETRY msecs_to_jiffies(50) #define R_PHY_RETRY 25
/* SFP module presence detection is poor: the three MOD DEF signals are * the same length on the PCB, which means it's possible for MOD DEF 0 to * connect before the I2C bus on MOD DEF 1/2. * * The SFF-8472 specifies t_serial ("Time from power on until module is * ready for data transmission over the two wire serial bus.") as 300ms.
*/ #define T_SERIAL msecs_to_jiffies(300) #define T_HPOWER_LEVEL msecs_to_jiffies(300) #define T_PROBE_RETRY_INIT msecs_to_jiffies(100) #define R_PROBE_RETRY_INIT 10 #define T_PROBE_RETRY_SLOW msecs_to_jiffies(5000) #define R_PROBE_RETRY_SLOW 12
/* SFP modules appear to always have their PHY configured for bus address * 0x56 (which with mdio-i2c, translates to a PHY address of 22). * RollBall SFPs access phy via SFP Enhanced Digital Diagnostic Interface * via address 0x51 (mdio-i2c will use RollBall protocol on this address).
*/ #define SFP_PHY_ADDR 22 #define SFP_PHY_ADDR_ROLLBALL 17
/* SFP_EEPROM_BLOCK_SIZE is the size of data chunk to read the EEPROM * at a time. Some SFP modules and also some Linux I2C drivers do not like * reads longer than 16 bytes.
*/ #define SFP_EEPROM_BLOCK_SIZE 16
/* SFP GPON module Ubiquiti U-Fiber Instant has in its EEPROM stored * phys id SFF instead of SFP. Therefore mark this module explicitly * as supported based on vendor name and pn match.
*/ if (id->base.phys_id == SFF8024_ID_SFF_8472 &&
id->base.phys_ext_id == SFP_PHYS_EXT_ID_SFP &&
!memcmp(id->base.vendor_name, "UBNT ", 16) &&
!memcmp(id->base.vendor_pn, "UF-INSTANT ", 16)) returntrue;
staticvoid sfp_fixup_ignore_los(struct sfp *sfp)
{ /* This forces LOS to zero, so we ignore transitions */
sfp->state_ignore_mask |= SFP_F_LOS; /* Make sure that LOS options are clear */
sfp->id.ext.options &= ~cpu_to_be16(SFP_OPTIONS_LOS_INVERTED |
SFP_OPTIONS_LOS_NORMAL);
}
/* RollBall modules may disallow access to PHY registers for up to 25 * seconds, and the reads return 0xffff before that. Increase the time * between PHY probe retries from 50ms to 1s so that we will wait for * the PHY for a sufficient amount of time.
*/
sfp->phy_t_retry = msecs_to_jiffies(1000);
}
/* The RollBall fixup is not enough for FS modules, the PHY chip inside * them does not return 0xffff for PHY ID registers in all MMDs for the * while initializing. They need a 4 second wait before accessing PHY.
*/
sfp->module_t_wait = msecs_to_jiffies(4000);
}
staticvoid sfp_fixup_halny_gsfp(struct sfp *sfp)
{ /* Ignore the TX_FAULT and LOS signals on this module. * these are possibly used for other purposes on this * module, e.g. a serial port.
*/
sfp_fixup_ignore_hw(sfp, SFP_F_TX_FAULT | SFP_F_LOS);
}
staticvoid sfp_fixup_potron(struct sfp *sfp)
{ /* * The TX_FAULT and LOS pins on this device are used for serial * communication, so ignore them. Additionally, provide extra * time for this device to fully start up.
*/
/* Some RollBall SFPs may have wrong (zero) extended compliance code * burned in EEPROM. For PHY probing we need the correct one.
*/
sfp->id.base.extended_cc = SFF8024_ECC_10GBASE_T_SFI;
}
staticvoid sfp_quirk_ubnt_uf_instant(conststruct sfp_eeprom_id *id, unsignedlong *modes, unsignedlong *interfaces)
{ /* 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);
}
staticconststruct sfp_quirk sfp_quirks[] = { // Alcatel Lucent G-010S-P can operate at 2500base-X, but incorrectly // report 2500MBd NRZ in their EEPROM
SFP_QUIRK("ALCATELLUCENT", "G010SP", sfp_quirk_2500basex,
sfp_fixup_ignore_tx_fault),
// Alcatel Lucent G-010S-A can operate at 2500base-X, but report 3.2GBd // NRZ in their EEPROM
SFP_QUIRK("ALCATELLUCENT", "3FE46541AA", sfp_quirk_2500basex,
sfp_fixup_nokia),
// FLYPRO SFP-10GT-CS-30M uses Rollball protocol to talk to the PHY.
SFP_QUIRK_F("FLYPRO", "SFP-10GT-CS-30M", sfp_fixup_rollball),
// Fiberstore SFP-10G-T doesn't identify as copper, uses the Rollball // protocol to talk to the PHY and needs 4 sec wait before probing the // PHY.
SFP_QUIRK_F("FS", "SFP-10G-T", sfp_fixup_fs_10gt),
// Fiberstore SFP-2.5G-T and SFP-10GM-T uses Rollball protocol to talk // to the PHY and needs 4 sec wait before probing the PHY.
SFP_QUIRK_F("FS", "SFP-2.5G-T", sfp_fixup_rollball_wait4s),
SFP_QUIRK_F("FS", "SFP-10GM-T", sfp_fixup_rollball_wait4s),
// Fiberstore GPON-ONU-34-20BI can operate at 2500base-X, but report 1.2GBd // NRZ in their EEPROM
SFP_QUIRK("FS", "GPON-ONU-34-20BI", sfp_quirk_2500basex,
sfp_fixup_ignore_tx_fault),
// 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),
// Huawei MA5671A can operate at 2500base-X, but report 1.2GBd NRZ in // their EEPROM
SFP_QUIRK("HUAWEI", "MA5671A", sfp_quirk_2500basex,
sfp_fixup_ignore_tx_fault),
// 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),
// Walsun HXSX-ATR[CI]-1 don't identify as copper, and use the // Rollball protocol to talk to the PHY.
SFP_QUIRK_F("Walsun", "HXSX-ATRC-1", sfp_fixup_fs_10gt),
SFP_QUIRK_F("Walsun", "HXSX-ATRI-1", sfp_fixup_fs_10gt),
/* Trailing characters should be filled with space chars, but * some manufacturers can't read SFF-8472 and use NUL.
*/ for (i = 0, size = 0; i < maxlen; i++) if (str[i] != ' ' && str[i] != '\0')
size = i + 1;
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); else
gpiod_direction_input(sfp->gpio[GPIO_TX_DISABLE]);
}
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]);
}
}
ret = sfp_read(sfp, a2, addr, &old, sizeof(old)); if (ret != sizeof(old)) return ret;
v = (old & ~mask) | (val & mask); if (v == old) returnsizeof(v);
return sfp_write(sfp, a2, addr, &v, sizeof(v));
}
staticunsignedint sfp_soft_get_state(struct sfp *sfp)
{ unsignedint state = 0;
u8 status; int ret;
ret = sfp_read(sfp, true, SFP_STATUS, &status, sizeof(status)); if (ret == sizeof(status)) { if (status & SFP_STATUS_RX_LOS)
state |= SFP_F_LOS; if (status & SFP_STATUS_TX_FAULT)
state |= SFP_F_TX_FAULT;
} else {
dev_err_ratelimited(sfp->dev, "failed to read SFP soft status: %pe\n",
ERR_PTR(ret)); /* Preserve the current state */
state = sfp->state;
}
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 & ~sfp->state_ignore_mask &
mask;
/* sfp_get_state() - must be called with st_mutex held, or in the * initialisation path.
*/ staticunsignedint sfp_get_state(struct sfp *sfp)
{ unsignedint soft = sfp->state_soft_mask & (SFP_F_LOS | SFP_F_TX_FAULT); unsignedint state;
state = sfp->get_state(sfp) & sfp->state_hw_mask; if (state & SFP_F_PRESENT && soft)
state |= sfp_soft_get_state(sfp);
return state;
}
/* sfp_set_state() - must be called with st_mutex held, or in the * initialisation path.
*/ staticvoid sfp_set_state(struct sfp *sfp, unsignedint state)
{ unsignedint soft;
switch (type) { case hwmon_temp: switch (attr) { case hwmon_temp_min_alarm: case hwmon_temp_max_alarm: case hwmon_temp_lcrit_alarm: case hwmon_temp_crit_alarm: case hwmon_temp_min: case hwmon_temp_max: case hwmon_temp_lcrit: case hwmon_temp_crit: if (!(sfp->id.ext.enhopts & SFP_ENHOPTS_ALARMWARN)) return 0;
fallthrough; case hwmon_temp_input: case hwmon_temp_label: return 0444; default: return 0;
} case hwmon_in: switch (attr) { case hwmon_in_min_alarm: case hwmon_in_max_alarm: case hwmon_in_lcrit_alarm: case hwmon_in_crit_alarm: case hwmon_in_min: case hwmon_in_max: case hwmon_in_lcrit: case hwmon_in_crit: if (!(sfp->id.ext.enhopts & SFP_ENHOPTS_ALARMWARN)) return 0;
fallthrough; case hwmon_in_input: case hwmon_in_label: return 0444; default: return 0;
} case hwmon_curr: switch (attr) { case hwmon_curr_min_alarm: case hwmon_curr_max_alarm: case hwmon_curr_lcrit_alarm: case hwmon_curr_crit_alarm: case hwmon_curr_min: case hwmon_curr_max: case hwmon_curr_lcrit: case hwmon_curr_crit: if (!(sfp->id.ext.enhopts & SFP_ENHOPTS_ALARMWARN)) return 0;
fallthrough; case hwmon_curr_input: case hwmon_curr_label: return 0444; default: return 0;
} case hwmon_power: /* External calibration of receive power requires * floating point arithmetic. Doing that in the kernel * is not easy, so just skip it. If the module does * not require external calibration, we can however * show receiver power, since FP is then not needed.
*/ if (sfp->id.ext.diagmon & SFP_DIAGMON_EXT_CAL &&
channel == 1) return 0; switch (attr) { case hwmon_power_min_alarm: case hwmon_power_max_alarm: case hwmon_power_lcrit_alarm: case hwmon_power_crit_alarm: case hwmon_power_min: case hwmon_power_max: case hwmon_power_lcrit: case hwmon_power_crit: if (!(sfp->id.ext.enhopts & SFP_ENHOPTS_ALARMWARN)) return 0;
fallthrough; case hwmon_power_input: case hwmon_power_label: return 0444; default: return 0;
} default: return 0;
}
}
staticint sfp_hwmon_read_sensor(struct sfp *sfp, int reg, long *value)
{
__be16 val; int err;
/* hwmon interface needs to access 16bit registers in atomic way to * guarantee coherency of the diagnostic monitoring data. If it is not * possible to guarantee coherency because EEPROM is broken in such way * that does not support atomic 16bit read operation then we have to * skip registration of hwmon device.
*/ if (sfp->i2c_block_size < 2) {
dev_info(sfp->dev, "skipping hwmon device registration\n");
dev_info(sfp->dev, "diagnostic EEPROM area cannot be read atomically to guarantee data coherency\n"); return;
}
sfp->hwmon_name = hwmon_sanitize_name(dev_name(sfp->dev)); if (IS_ERR(sfp->hwmon_name)) {
dev_err(sfp->dev, "out of memory for hwmon name\n"); return;
}
sfp->hwmon_dev = hwmon_device_register_with_info(sfp->dev,
sfp->hwmon_name, sfp,
&sfp_hwmon_chip_info,
NULL); if (IS_ERR(sfp->hwmon_dev))
dev_err(sfp->dev, "failed to register hwmon device: %ld\n",
PTR_ERR(sfp->hwmon_dev));
}
/* If neither SFP_OPTIONS_LOS_INVERTED nor SFP_OPTIONS_LOS_NORMAL * are set, we assume that no LOS signal is available. If both are * set, we assume LOS is not implemented (and is meaningless.)
*/ if (los_options == los_inverted)
los = !(sfp->state & SFP_F_LOS); elseif (los_options == los_normal)
los = !!(sfp->state & SFP_F_LOS);
if (los)
sfp_sm_next(sfp, SFP_S_WAIT_LOS, 0); else
sfp_sm_link_up(sfp);
}
/* 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 * or clause 45 PHY. * * Clause 22 copper SFP modules normally operate in Cisco SGMII mode with * negotiation enabled, but some may be in 1000base-X - which is for the * PHY driver to determine. * * Clause 45 copper SFP+ modules (10G) appear to switch their interface * mode according to the negotiated line speed.
*/ staticint sfp_sm_probe_for_phy(struct sfp *sfp)
{ int err = 0;
switch (sfp->mdio_protocol) { case MDIO_I2C_NONE: break;
case MDIO_I2C_MARVELL_C22:
err = sfp_sm_probe_phy(sfp, SFP_PHY_ADDR, false); break;
case MDIO_I2C_C45:
err = sfp_sm_probe_phy(sfp, SFP_PHY_ADDR, true); break;
case MDIO_I2C_ROLLBALL:
err = sfp_sm_probe_phy(sfp, SFP_PHY_ADDR_ROLLBALL, true); break;
}
if (sfp->id.ext.sff8472_compliance >= SFP_SFF8472_COMPLIANCE_REV10_2 &&
sfp->id.ext.options & cpu_to_be16(SFP_OPTIONS_POWER_DECL))
power_mW = 1500; /* Added in Rev 11.9, but there is no compliance code for this */ if (sfp->id.ext.sff8472_compliance >= SFP_SFF8472_COMPLIANCE_REV11_4 &&
sfp->id.ext.options & cpu_to_be16(SFP_OPTIONS_HIGH_POWER_LEVEL))
power_mW = 2000;
/* Power level 1 modules (max. 1W) are always supported. */ if (power_mW <= 1000) {
sfp->module_power_mW = power_mW; return 0;
}
if (power_mW > sfp->max_power_mW) { /* Module power specification exceeds the allowed maximum. */ if (!supports_a2) { /* The module appears not to implement bus address * 0xa2, so assume that the module powers up in the * indicated mode.
*/
dev_err(sfp->dev, "Host does not support %u.%uW modules\n",
power_mW / 1000, (power_mW / 100) % 10); return -EINVAL;
} else {
dev_warn(sfp->dev, "Host does not support %u.%uW modules, module left in power mode 1\n",
power_mW / 1000, (power_mW / 100) % 10); return 0;
}
}
if (!supports_a2) { /* The module power level is below the host maximum and the * module appears not to implement bus address 0xa2, so assume * that the module powers up in the indicated mode.
*/ return 0;
}
/* If the module requires a higher power mode, but also requires * an address change sequence, warn the user that the module may * not be functional.
*/ if (sfp->id.ext.diagmon & SFP_DIAGMON_ADDRMODE) {
dev_warn(sfp->dev, "Address Change Sequence not supported but module requires %u.%uW, module may not be functional\n",
power_mW / 1000, (power_mW / 100) % 10); return 0;
}
sfp->module_power_mW = power_mW;
return 0;
}
staticint sfp_sm_mod_hpower(struct sfp *sfp, bool enable)
{ int err;
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;
/* 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 * operation returns just one byte of EEPROM followed by zeros. There is * no way to identify which modules are using Realtek RTL8672 and RTL9601C * chips. Moreover every OEM of V-SOL V2801F module puts its own vendor * name and vendor id into EEPROM, so there is even no way to detect if * module is V-SOL V2801F. Therefore check for those zeros in the read * data and then based on check switch to reading EEPROM to one byte * at a time.
*/ staticbool sfp_id_needs_byte_io(struct sfp *sfp, void *buf, size_t len)
{
size_t i, block_size = sfp->i2c_block_size;
/* Already using byte IO */ if (block_size == 1) returnfalse;
for (i = 1; i < len; i += block_size) { if (memchr_inv(buf + i, '\0', min(block_size - 1, len - i))) returnfalse;
} returntrue;
}
/* Cotsworks modules have been found to require a delay between write operations. */
mdelay(50);
/* Update base structure checksum */
check = sfp_check(&id->base, sizeof(id->base) - 1);
err = sfp_write(sfp, false, SFP_CC_BASE, &check, 1); if (err != 1) {
dev_err(sfp->dev, "Failed to update base structure checksum in fiber module EEPROM: %pe\n",
ERR_PTR(err)); return err;
}
} return 0;
}
staticint sfp_module_parse_sff8472(struct sfp *sfp)
{ /* If the module requires address swap mode, warn about it */ if (sfp->id.ext.diagmon & SFP_DIAGMON_ADDRMODE)
dev_warn(sfp->dev, "module address swap to access page 0xA2 is not supported.\n"); else
sfp->have_a2 = true;
ret = sfp_read(sfp, false, 0, &id.base, sizeof(id.base)); if (ret < 0) { if (report)
dev_err(sfp->dev, "failed to read EEPROM: %pe\n",
ERR_PTR(ret)); return -EAGAIN;
}
if (ret != sizeof(id.base)) {
dev_err(sfp->dev, "EEPROM short read: %pe\n", ERR_PTR(ret)); return -EAGAIN;
}
/* Some SFP modules (e.g. Nokia 3FE46541AA) lock up if read from * address 0x51 is just one byte at a time. Also SFF-8472 requires * that EEPROM supports atomic 16bit read operation for diagnostic * fields, so do not switch to one byte reading at a time unless it * is really required and we have no other option.
*/ if (sfp_id_needs_byte_io(sfp, &id.base, sizeof(id.base))) {
dev_info(sfp->dev, "Detected broken RTL8672/RTL9601C emulated EEPROM\n");
dev_info(sfp->dev, "Switching to reading EEPROM to one byte at a time\n");
sfp->i2c_block_size = 1;
ret = sfp_read(sfp, false, 0, &id.base, sizeof(id.base)); if (ret < 0) { if (report)
dev_err(sfp->dev, "failed to read EEPROM: %pe\n",
ERR_PTR(ret)); return -EAGAIN;
}
if (ret != sizeof(id.base)) {
dev_err(sfp->dev, "EEPROM short read: %pe\n",
ERR_PTR(ret)); return -EAGAIN;
}
}
/* Cotsworks do not seem to update the checksums when they * do the final programming with the final module part number, * serial number and date code.
*/
cotsworks = !memcmp(id.base.vendor_name, "COTSWORKS ", 16);
cotsworks_sfbg = !memcmp(id.base.vendor_pn, "SFBG", 4);
/* Cotsworks SFF module EEPROM do not always have valid phys_id, * phys_ext_id, and connector bytes. Rewrite SFF EEPROM bytes if * Cotsworks PN matches and bytes are not correct.
*/ if (cotsworks && cotsworks_sfbg) {
ret = sfp_cotsworks_fixup_check(sfp, &id); if (ret < 0) return ret;
}
/* Validate the checksum over the base structure */
check = sfp_check(&id.base, sizeof(id.base) - 1); if (check != id.base.cc_base) { if (cotsworks) {
dev_warn(sfp->dev, "EEPROM base structure checksum failure (0x%02x != 0x%02x)\n",
check, id.base.cc_base);
} else {
dev_err(sfp->dev, "EEPROM base structure checksum failure: 0x%02x != 0x%02x\n",
check, id.base.cc_base);
print_hex_dump(KERN_ERR, "sfp EE: ", DUMP_PREFIX_OFFSET,
16, 1, &id, sizeof(id), true); return -EINVAL;
}
}
ret = sfp_read(sfp, false, SFP_CC_BASE + 1, &id.ext, sizeof(id.ext)); if (ret < 0) { if (report)
dev_err(sfp->dev, "failed to read EEPROM: %pe\n",
ERR_PTR(ret)); return -EAGAIN;
}
if (ret != sizeof(id.ext)) {
dev_err(sfp->dev, "EEPROM short read: %pe\n", ERR_PTR(ret)); return -EAGAIN;
}
dev_info(sfp->dev, "module %.*s %.*s rev %.*s sn %.*s dc %.*s\n",
(int)sizeof(id.base.vendor_name), id.base.vendor_name,
(int)sizeof(id.base.vendor_pn), id.base.vendor_pn,
(int)sizeof(id.base.vendor_rev), id.base.vendor_rev,
(int)sizeof(id.ext.vendor_sn), id.ext.vendor_sn,
(int)sizeof(id.ext.datecode), id.ext.datecode);
/* Check whether we support this module */ if (!sfp->type->module_supported(&id)) {
dev_err(sfp->dev, "module is not supported - phys id 0x%02x 0x%02x\n",
sfp->id.base.phys_id, sfp->id.base.phys_ext_id); return -EINVAL;
}
if (sfp->id.ext.sff8472_compliance != SFP_SFF8472_COMPLIANCE_NONE) {
ret = sfp_module_parse_sff8472(sfp); if (ret < 0) return ret;
}
/* Parse the module power requirement */
ret = sfp_module_parse_power(sfp); if (ret < 0) return ret;
sfp_module_parse_rate_select(sfp);
mask = SFP_F_PRESENT; if (sfp->gpio[GPIO_TX_DISABLE])
mask |= SFP_F_TX_DISABLE; if (sfp->gpio[GPIO_TX_FAULT])
mask |= SFP_F_TX_FAULT; if (sfp->gpio[GPIO_LOS])
mask |= SFP_F_LOS; if (sfp->gpio[GPIO_RS0])
mask |= SFP_F_RS0; if (sfp->gpio[GPIO_RS1])
mask |= SFP_F_RS1;
/* This state machine tracks the upstream's state */ staticvoid sfp_sm_device(struct sfp *sfp, unsignedint event)
{ switch (sfp->sm_dev_state) { default: if (event == SFP_E_DEV_ATTACH)
sfp->sm_dev_state = SFP_DEV_DOWN; break;
case SFP_DEV_DOWN: if (event == SFP_E_DEV_DETACH)
sfp->sm_dev_state = SFP_DEV_DETACHED; elseif (event == SFP_E_DEV_UP)
sfp->sm_dev_state = SFP_DEV_UP; break;
case SFP_DEV_UP: if (event == SFP_E_DEV_DETACH)
sfp->sm_dev_state = SFP_DEV_DETACHED; elseif (event == SFP_E_DEV_DOWN)
sfp->sm_dev_state = SFP_DEV_DOWN; break;
}
}
/* This state machine tracks the insert/remove state of the module, probes * the on-board EEPROM, and sets up the power level.
*/ staticvoid sfp_sm_module(struct sfp *sfp, unsignedint event)
{ int err;
/* Handle remove event globally, it resets this state machine */ if (event == SFP_E_REMOVE) {
sfp_sm_mod_remove(sfp);
sfp_sm_mod_next(sfp, SFP_MOD_EMPTY, 0); return;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.