Author: np
Date: Wed Nov 12 23:29:22 2014
New Revision: 274456
URL: https://svnweb.freebsd.org/changeset/base/274456

Log:
  Fix some bad interaction between cxgbe(4) and lacp lagg(4) that could
  leave a port permanently disabled when a copper cable is unplugged and
  then plugged right back in.
  
  lacp_linkstate goes looking for the current ifmedia on a link state
  change and it could get stale information from cxgbe(4) on a module
  unplug followed by replug.  The fix is to process module events before
  link-state events within the driver, and to always rebuild the ifmedia
  list on a module change event (instead of rebuilding it lazily).
  
  Thanks to asomers@ for the problem report and detailed analysis to go
  with it.
  
  MFC after:    1 week

Modified:
  head/sys/dev/cxgbe/common/t4_hw.c
  head/sys/dev/cxgbe/t4_main.c

Modified: head/sys/dev/cxgbe/common/t4_hw.c
==============================================================================
--- head/sys/dev/cxgbe/common/t4_hw.c   Wed Nov 12 22:58:52 2014        
(r274455)
+++ head/sys/dev/cxgbe/common/t4_hw.c   Wed Nov 12 23:29:22 2014        
(r274456)
@@ -5420,6 +5420,10 @@ int t4_handle_fw_rpl(struct adapter *ada
                }
                lc = &pi->link_cfg;
 
+               if (mod != pi->mod_type) {
+                       pi->mod_type = mod;
+                       t4_os_portmod_changed(adap, i);
+               }
                if (link_ok != lc->link_ok || speed != lc->speed ||
                    fc != lc->fc) {                    /* something changed */
                        int reason;
@@ -5435,10 +5439,6 @@ int t4_handle_fw_rpl(struct adapter *ada
                        lc->supported = ntohs(p->u.info.pcap);
                        t4_os_link_changed(adap, i, link_ok, reason);
                }
-               if (mod != pi->mod_type) {
-                       pi->mod_type = mod;
-                       t4_os_portmod_changed(adap, i);
-               }
        } else {
                CH_WARN_RATELIMIT(adap,
                    "Unknown firmware reply 0x%x (0x%x)\n", opcode, action);

Modified: head/sys/dev/cxgbe/t4_main.c
==============================================================================
--- head/sys/dev/cxgbe/t4_main.c        Wed Nov 12 22:58:52 2014        
(r274455)
+++ head/sys/dev/cxgbe/t4_main.c        Wed Nov 12 23:29:22 2014        
(r274456)
@@ -1590,7 +1590,9 @@ cxgbe_media_status(struct ifnet *ifp, st
        struct ifmedia *media = NULL;
        struct ifmedia_entry *cur;
        int speed = pi->link_cfg.speed;
+#ifdef INVARIANTS
        int data = (pi->port_type << 8) | pi->mod_type;
+#endif
 
        if (ifp == pi->ifp)
                media = &pi->media;
@@ -1601,10 +1603,7 @@ cxgbe_media_status(struct ifnet *ifp, st
        MPASS(media != NULL);
 
        cur = media->ifm_cur;
-       if (cur->ifm_data != data) {
-               build_medialist(pi, media);
-               cur = media->ifm_cur;
-       }
+       MPASS(cur->ifm_data == data);
 
        ifmr->ifm_status = IFM_AVALID;
        if (!pi->link_cfg.link_ok)
@@ -8005,6 +8004,11 @@ t4_os_portmod_changed(const struct adapt
                NULL, "LR", "SR", "ER", "TWINAX", "active TWINAX", "LRM"
        };
 
+       build_medialist(pi, &pi->media);
+#ifdef DEV_NETMAP
+       build_medialist(pi, &pi->nm_media);
+#endif
+
        if (pi->mod_type == FW_PORT_MOD_TYPE_NONE)
                if_printf(pi->ifp, "transceiver unplugged.\n");
        else if (pi->mod_type == FW_PORT_MOD_TYPE_UNKNOWN)
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to