On Thu, Dec 13, 2012 at 20:49 +0100, Mike Belopuhov wrote:
first this allows you to connect the sfp+ cable after boot
and correctly identify and use it, secondly it allows you
(supposedly as i've only tested two different types of
direct attach cables, i.e. different phys) to switch between
copper and fiber w/o rebooting.
SDP1 interrupt processing is not enabled because i can't
test it.
code from the intel driver (except for handling the bad hp
cable correctly -- and that's b not a for those who have
any idea what i'm talking about).
OK?
a bit better arrangement of code + use change autoneg to use
hw-phy.autoneg_advertised like FreeBSD does. in this case
it should be set properly.
forgot to mention that diff only affects 82599 and only when
interface is up (since interrupts must be enabled).
diff --git sys/dev/pci/if_ix.c sys/dev/pci/if_ix.c
index 8c3f817..337f789 100644
--- sys/dev/pci/if_ix.c
+++ sys/dev/pci/if_ix.c
@@ -145,6 +145,8 @@ voidixgbe_setup_vlan_hw_support(struct ix_softc *);
/* Support for pluggable optic modules */
intixgbe_sfp_probe(struct ix_softc *);
void ixgbe_setup_optics(struct ix_softc *);
+void ixgbe_handle_mod(struct ix_softc *);
+void ixgbe_handle_msf(struct ix_softc *);
/* Legacy (single vector interrupt handler */
intixgbe_legacy_irq(void *);
@@ -928,12 +930,6 @@ ixgbe_legacy_irq(void *arg)
return (0);
}
- if (ifp-if_flags IFF_RUNNING) {
- ixgbe_rxeof(que);
- ixgbe_txeof(txr);
- refill = 1;
- }
-
/* Check for fan failure */
if ((hw-phy.media_type == ixgbe_media_type_copper)
(reg_eicr IXGBE_EICR_GPI_SDP1)) {
@@ -958,6 +954,28 @@ ixgbe_legacy_irq(void *arg)
timeout_add_sec(sc-timer, 1);
}
+ if (hw-mac.type != ixgbe_mac_82598EB) {
+ if (reg_eicr IXGBE_EICR_GPI_SDP2) {
+ /* Clear the interrupt */
+ IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP2);
+ ixgbe_handle_mod(sc);
+ }
+#if 0
+ else if ((hw-phy.media_type != ixgbe_media_type_copper)
+ (reg_eicr IXGBE_EICR_GPI_SDP1)) {
+ /* Clear the interrupt */
+ IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1);
+ ixgbe_handle_msf(sc);
+ }
+#endif
+ }
+
+ if (ifp-if_flags IFF_RUNNING) {
+ ixgbe_rxeof(que);
+ ixgbe_txeof(txr);
+ refill = 1;
+ }
+
if (refill) {
if (ixgbe_rxfill(que-rxr)) {
/* Advance the Rx Queue Tail Pointer */
@@ -3408,6 +3426,50 @@ out:
return (result);
}
+/*
+ * SFP module interrupts handler
+ */
+void
+ixgbe_handle_mod(struct ix_softc *sc)
+{
+ struct ixgbe_hw *hw = sc-hw;
+ uint32_t err;
+
+ err = hw-phy.ops.identify_sfp(hw);
+ if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
+ printf(%s: Unsupported SFP+ module type was detected!\n,
+ sc-dev.dv_xname);
+ return;
+ }
+ err = hw-mac.ops.setup_sfp(hw);
+ if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
+ printf(%s: Setup failure - unsupported SFP+ module type!\n,
+ sc-dev.dv_xname);
+ return;
+ }
+ /* Set the optics type so system reports correctly */
+ ixgbe_setup_optics(sc);
+ return (ixgbe_handle_msf(sc));
+}
+
+
+/*
+ * MSF (multispeed fiber) interrupts handler
+ */
+void
+ixgbe_handle_msf(struct ix_softc *sc)
+{
+ struct ixgbe_hw *hw = sc-hw;
+ uint32_t autoneg;
+ int negotiate;
+
+ autoneg = hw-phy.autoneg_advertised;
+ if ((!autoneg) (hw-mac.ops.get_link_capabilities))
+ hw-mac.ops.get_link_capabilities(hw, autoneg, negotiate);
+ if (hw-mac.ops.setup_link)
+ hw-mac.ops.setup_link(hw, autoneg, negotiate, TRUE);
+}
+
/**
*
* Update the board statistics counters.
diff --git sys/dev/pci/ixgbe_82599.c sys/dev/pci/ixgbe_82599.c
index 350ddc7..e91579d 100644
--- sys/dev/pci/ixgbe_82599.c
+++ sys/dev/pci/ixgbe_82599.c
@@ -1350,6 +1350,11 @@ sfp_check:
physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR;
else if (comp_codes_10g IXGBE_SFF_10GBASELR_CAPABLE)
physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR;
+ else if (comp_codes_10g
+ (IXGBE_SFF_DA_PASSIVE_CABLE | IXGBE_SFF_DA_BAD_HP_CABLE))
+ physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU;
+ else if (comp_codes_10g IXGBE_SFF_DA_ACTIVE_CABLE)
+ physical_layer = IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA;
else if (comp_codes_1g IXGBE_SFF_1GBASET_CAPABLE)