E1000_SWSM      = 0x05B50, /* SW Semaphore */
        E1000_FWSM      = 0x05B54, /* FW Semaphore */
        E1000_SWSM2     = 0x05B58, /* Driver-only SW semaphore */
+       E1000_CRC_OFFSET = 0x05F50, /* CRC Offset register */
        E1000_HICR      = 0x08F00, /* Host Interface Control */
 };
 
 #define E1000_KMRNCTRLSTA_REN          0x00200000
 #define E1000_KMRNCTRLSTA_DIAG_OFFSET  0x3    /* Kumeran Diagnostic */
 #define E1000_KMRNCTRLSTA_DIAG_NELPBK  0x1000 /* Nearend Loopback mode */
+#define E1000_KMRNCTRLSTA_K1_CONFIG    0x7
+#define E1000_KMRNCTRLSTA_K1_ENABLE    0x140E
+#define E1000_KMRNCTRLSTA_K1_DISABLE   0x1400
 
 #define IFE_PHY_EXTENDED_STATUS_CONTROL        0x10
 #define IFE_PHY_SPECIAL_CONTROL                0x11 /* 100BaseTx PHY Special Control */
 
        return 0;
 }
 
+/**
+ *  e1000_check_for_copper_link_ich8lan - Check for link (Copper)
+ *  @hw: pointer to the HW structure
+ *
+ *  Checks to see of the link status of the hardware has changed.  If a
+ *  change in link status has been detected, then we read the PHY registers
+ *  to get the current speed/duplex if link exists.
+ **/
+static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
+{
+       struct e1000_mac_info *mac = &hw->mac;
+       s32 ret_val;
+       bool link;
+
+       /*
+        * We only want to go out to the PHY registers to see if Auto-Neg
+        * has completed and/or if our link status has changed.  The
+        * get_link_status flag is set upon receiving a Link Status
+        * Change or Rx Sequence Error interrupt.
+        */
+       if (!mac->get_link_status) {
+               ret_val = 0;
+               goto out;
+       }
+
+       if (hw->mac.type == e1000_pchlan) {
+               ret_val = e1000e_write_kmrn_reg(hw,
+                                                  E1000_KMRNCTRLSTA_K1_CONFIG,
+                                                  E1000_KMRNCTRLSTA_K1_ENABLE);
+               if (ret_val)
+                       goto out;
+       }
+
+       /*
+        * First we want to see if the MII Status Register reports
+        * link.  If so, then we want to get the current speed/duplex
+        * of the PHY.
+        */
+       ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link);
+       if (ret_val)
+               goto out;
+
+       if (!link)
+               goto out; /* No link detected */
+
+       mac->get_link_status = false;
+
+       if (hw->phy.type == e1000_phy_82578) {
+               ret_val = e1000_link_stall_workaround_hv(hw);
+               if (ret_val)
+                       goto out;
+       }
+
+       /*
+        * Check if there was DownShift, must be checked
+        * immediately after link-up
+        */
+       e1000e_check_downshift(hw);
+
+       /*
+        * If we are forcing speed/duplex, then we simply return since
+        * we have already determined whether we have link or not.
+        */
+       if (!mac->autoneg) {
+               ret_val = -E1000_ERR_CONFIG;
+               goto out;
+       }
+
+       /*
+        * Auto-Neg is enabled.  Auto Speed Detection takes care
+        * of MAC speed/duplex configuration.  So we only need to
+        * configure Collision Distance in the MAC.
+        */
+       e1000e_config_collision_dist(hw);
+
+       /*
+        * Configure Flow Control now that Auto-Neg has completed.
+        * First, we need to restore the desired flow control
+        * settings because we may have had to re-autoneg with a
+        * different link partner.
+        */
+       ret_val = e1000e_config_fc_after_link_up(hw);
+       if (ret_val)
+               hw_dbg(hw, "Error configuring flow control\n");
+
+out:
+       return ret_val;
+}
+
 static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter)
 {
        struct e1000_hw *hw = &adapter->hw;
                }
        }
 
+       /*
+        * For PCH, this write will make sure that any noise
+        * will be detected as a CRC error and be dropped rather than show up
+        * as a bad packet to the DMA engine.
+        */
+       if (hw->mac.type == e1000_pchlan)
+               ew32(CRC_OFFSET, 0x65656565);
+
        ew32(IMC, 0xffffffff);
        icr = er32(ICR);
 
        if (ret_val)
                return ret_val;
 
+       if ((hw->mac.type == e1000_pchlan) && (*speed == SPEED_1000)) {
+               ret_val = e1000e_write_kmrn_reg(hw,
+                                                 E1000_KMRNCTRLSTA_K1_CONFIG,
+                                                 E1000_KMRNCTRLSTA_K1_DISABLE);
+               if (ret_val)
+                       return ret_val;
+       }
+
        if ((hw->mac.type == e1000_ich8lan) &&
            (hw->phy.type == e1000_phy_igp_3) &&
            (*speed == SPEED_1000)) {
 static struct e1000_mac_operations ich8_mac_ops = {
        .id_led_init            = e1000e_id_led_init,
        .check_mng_mode         = e1000_check_mng_mode_ich8lan,
-       .check_for_link         = e1000e_check_for_copper_link,
+       .check_for_link         = e1000_check_for_copper_link_ich8lan,
        /* cleanup_led dependent on mac type */
        .clear_hw_cntrs         = e1000_clear_hw_cntrs_ich8lan,
        .get_bus_info           = e1000_get_bus_info_ich8lan,