]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - drivers/net/e1000e/netdev.c
e1000e: initialize manageability (IPMI) pass-through in 82574/82583
[mirror_ubuntu-bionic-kernel.git] / drivers / net / e1000e / netdev.c
index c5f65a29865aefe9c69daa716155d91c677f2041..36473e6d07d6cc769b37107215c36620271886a9 100644 (file)
@@ -2526,10 +2526,10 @@ static void e1000_restore_vlan(struct e1000_adapter *adapter)
        }
 }
 
-static void e1000_init_manageability(struct e1000_adapter *adapter)
+static void e1000_init_manageability_pt(struct e1000_adapter *adapter)
 {
        struct e1000_hw *hw = &adapter->hw;
-       u32 manc, manc2h;
+       u32 manc, manc2h, mdef, i, j;
 
        if (!(adapter->flags & FLAG_MNG_PT_ENABLED))
                return;
@@ -2543,10 +2543,49 @@ static void e1000_init_manageability(struct e1000_adapter *adapter)
         */
        manc |= E1000_MANC_EN_MNG2HOST;
        manc2h = er32(MANC2H);
-#define E1000_MNG2HOST_PORT_623 (1 << 5)
-#define E1000_MNG2HOST_PORT_664 (1 << 6)
-       manc2h |= E1000_MNG2HOST_PORT_623;
-       manc2h |= E1000_MNG2HOST_PORT_664;
+
+       switch (hw->mac.type) {
+       default:
+               manc2h |= (E1000_MANC2H_PORT_623 | E1000_MANC2H_PORT_664);
+               break;
+       case e1000_82574:
+       case e1000_82583:
+               /*
+                * Check if IPMI pass-through decision filter already exists;
+                * if so, enable it.
+                */
+               for (i = 0, j = 0; i < 8; i++) {
+                       mdef = er32(MDEF(i));
+
+                       /* Ignore filters with anything other than IPMI ports */
+                       if (mdef & !(E1000_MDEF_PORT_623 | E1000_MDEF_PORT_664))
+                               continue;
+
+                       /* Enable this decision filter in MANC2H */
+                       if (mdef)
+                               manc2h |= (1 << i);
+
+                       j |= mdef;
+               }
+
+               if (j == (E1000_MDEF_PORT_623 | E1000_MDEF_PORT_664))
+                       break;
+
+               /* Create new decision filter in an empty filter */
+               for (i = 0, j = 0; i < 8; i++)
+                       if (er32(MDEF(i)) == 0) {
+                               ew32(MDEF(i), (E1000_MDEF_PORT_623 |
+                                              E1000_MDEF_PORT_664));
+                               manc2h |= (1 << 1);
+                               j++;
+                               break;
+                       }
+
+               if (!j)
+                       e_warn("Unable to create IPMI pass-through filter\n");
+               break;
+       }
+
        ew32(MANC2H, manc2h);
        ew32(MANC, manc);
 }
@@ -2961,7 +3000,7 @@ static void e1000_configure(struct e1000_adapter *adapter)
        e1000_set_multi(adapter->netdev);
 
        e1000_restore_vlan(adapter);
-       e1000_init_manageability(adapter);
+       e1000_init_manageability_pt(adapter);
 
        e1000_configure_tx(adapter);
        e1000_setup_rctl(adapter);
@@ -3444,6 +3483,15 @@ static int e1000_open(struct net_device *netdev)
        if (err)
                goto err_setup_rx;
 
+       /*
+        * If AMT is enabled, let the firmware know that the network
+        * interface is now open and reset the part to a known state.
+        */
+       if (adapter->flags & FLAG_HAS_AMT) {
+               e1000_get_hw_control(adapter);
+               e1000e_reset(adapter);
+       }
+
        e1000e_power_up_phy(adapter);
 
        adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
@@ -3451,13 +3499,6 @@ static int e1000_open(struct net_device *netdev)
             E1000_MNG_DHCP_COOKIE_STATUS_VLAN))
                e1000_update_mng_vlan(adapter);
 
-       /*
-        * If AMT is enabled, let the firmware know that the network
-        * interface is now open
-        */
-       if (adapter->flags & FLAG_HAS_AMT)
-               e1000_get_hw_control(adapter);
-
        /*
         * before we allocate an interrupt, we must be ready to handle it.
         * Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt
@@ -5102,7 +5143,7 @@ static int __e1000_resume(struct pci_dev *pdev)
 
        e1000e_reset(adapter);
 
-       e1000_init_manageability(adapter);
+       e1000_init_manageability_pt(adapter);
 
        if (netif_running(netdev))
                e1000e_up(adapter);
@@ -5303,7 +5344,7 @@ static void e1000_io_resume(struct pci_dev *pdev)
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct e1000_adapter *adapter = netdev_priv(netdev);
 
-       e1000_init_manageability(adapter);
+       e1000_init_manageability_pt(adapter);
 
        if (netif_running(netdev)) {
                if (e1000e_up(adapter)) {