diff --git a/packages/base/any/kernels/4.9-lts/configs/x86_64-all/x86_64-all.config b/packages/base/any/kernels/4.9-lts/configs/x86_64-all/x86_64-all.config index 0326395c..b616ae79 100644 --- a/packages/base/any/kernels/4.9-lts/configs/x86_64-all/x86_64-all.config +++ b/packages/base/any/kernels/4.9-lts/configs/x86_64-all/x86_64-all.config @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/x86_64 4.9.30 Kernel Configuration +# Linux/x86 4.9.30 Kernel Configuration # CONFIG_64BIT=y CONFIG_X86_64=y @@ -1477,6 +1477,7 @@ CONFIG_VIRTIO_NET=y # Distributed Switch Architecture drivers # CONFIG_ETHERNET=y +CONFIG_MDIO=y CONFIG_NET_VENDOR_3COM=y # CONFIG_PCMCIA_3C574 is not set # CONFIG_PCMCIA_3C589 is not set @@ -1557,10 +1558,12 @@ CONFIG_E100=y CONFIG_E1000=y CONFIG_E1000E=y CONFIG_E1000E_HWTS=y -# CONFIG_IGB is not set -# CONFIG_IGBVF is not set -# CONFIG_IXGB is not set -# CONFIG_IXGBE is not set +CONFIG_IGB=y +CONFIG_IGB_HWMON=y +CONFIG_IGBVF=y +CONFIG_IXGB=y +CONFIG_IXGBE=y +CONFIG_IXGBE_HWMON=y # CONFIG_IXGBEVF is not set # CONFIG_I40E is not set # CONFIG_I40EVF is not set diff --git a/packages/base/any/kernels/4.9-lts/patches/driver-support-intel-igb-bcm5461-phy.patch b/packages/base/any/kernels/4.9-lts/patches/driver-support-intel-igb-bcm5461-phy.patch new file mode 100644 index 00000000..c780797b --- /dev/null +++ b/packages/base/any/kernels/4.9-lts/patches/driver-support-intel-igb-bcm5461-phy.patch @@ -0,0 +1,263 @@ +From 908a37bb6749d85a7818fb8a0f684d46c858f52e Mon Sep 17 00:00:00 2001 +From: David Ahern +Date: Thu, 11 May 2017 17:53:43 -0700 +Subject: [PATCH] igb: Add support for bcm5461x phy + +Based on driver-support-intel-igb-bcm5461X-phy.patch from +OpenNetworkLinux, 3.16-lts patches + +Signed-off-by: David Ahern +--- + drivers/net/ethernet/intel/igb/e1000_82575.c | 27 ++++++++ + drivers/net/ethernet/intel/igb/e1000_defines.h | 2 + + drivers/net/ethernet/intel/igb/e1000_hw.h | 2 + + drivers/net/ethernet/intel/igb/e1000_phy.c | 87 ++++++++++++++++++++++++-- + drivers/net/ethernet/intel/igb/e1000_phy.h | 2 + + drivers/net/ethernet/intel/igb/igb_main.c | 8 +++ + 6 files changed, 124 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.c b/drivers/net/ethernet/intel/igb/e1000_82575.c +index ee443985581fe..2de38acdc187f 100644 +--- a/drivers/net/ethernet/intel/igb/e1000_82575.c ++++ b/drivers/net/ethernet/intel/igb/e1000_82575.c +@@ -339,6 +339,15 @@ static s32 igb_init_phy_params_82575(struct e1000_hw *hw) + phy->ops.set_d3_lplu_state = igb_set_d3_lplu_state_82580; + phy->ops.force_speed_duplex = igb_phy_force_speed_duplex_m88; + break; ++ case BCM5461S_PHY_ID: ++ phy->type = e1000_phy_bcm5461s; ++ phy->ops.check_polarity = NULL; ++ phy->ops.get_cable_length = NULL; ++ phy->ops.force_speed_duplex = igb_phy_force_speed_duplex_82580; ++ break; ++ case BCM54616_E_PHY_ID: ++ phy->type = e1000_phy_bcm54616; ++ break; + default: + ret_val = -E1000_ERR_PHY; + goto out; +@@ -898,6 +907,16 @@ static s32 igb_get_phy_id_82575(struct e1000_hw *hw) + goto out; + } + ret_val = igb_get_phy_id(hw); ++ if (ret_val && hw->mac.type == e1000_i354) { ++ /* we do a special check for bcm5461s phy by setting ++ * the phy->addr to 5 and doing the phy check again. This ++ * call will succeed and retrieve a valid phy id if we have ++ * the bcm5461s phy ++ */ ++ phy->addr = 5; ++ phy->type = e1000_phy_bcm5461s; ++ ret_val = igb_get_phy_id(hw); ++ } + goto out; + } + +@@ -1285,6 +1304,9 @@ static s32 igb_get_cfg_done_82575(struct e1000_hw *hw) + (hw->phy.type == e1000_phy_igp_3)) + igb_phy_init_script_igp3(hw); + ++ if (hw->phy.type == e1000_phy_bcm5461s) ++ igb_phy_init_script_5461s(hw); ++ + return 0; + } + +@@ -1614,6 +1636,7 @@ static s32 igb_setup_copper_link_82575(struct e1000_hw *hw) + case e1000_i350: + case e1000_i210: + case e1000_i211: ++ case e1000_i354: + phpm_reg = rd32(E1000_82580_PHY_POWER_MGMT); + phpm_reg &= ~E1000_82580_PM_GO_LINKD; + wr32(E1000_82580_PHY_POWER_MGMT, phpm_reg); +@@ -1658,6 +1681,10 @@ static s32 igb_setup_copper_link_82575(struct e1000_hw *hw) + case e1000_phy_82580: + ret_val = igb_copper_link_setup_82580(hw); + break; ++ case e1000_phy_bcm54616: ++ break; ++ case e1000_phy_bcm5461s: ++ break; + default: + ret_val = -E1000_ERR_PHY; + break; +diff --git a/drivers/net/ethernet/intel/igb/e1000_defines.h b/drivers/net/ethernet/intel/igb/e1000_defines.h +index 8aee314332a87..9c1471643c542 100644 +--- a/drivers/net/ethernet/intel/igb/e1000_defines.h ++++ b/drivers/net/ethernet/intel/igb/e1000_defines.h +@@ -868,6 +868,8 @@ + #define I210_I_PHY_ID 0x01410C00 + #define M88E1543_E_PHY_ID 0x01410EA0 + #define M88E1512_E_PHY_ID 0x01410DD0 ++#define BCM54616_E_PHY_ID 0x3625D10 ++#define BCM5461S_PHY_ID 0x002060C0 + + /* M88E1000 Specific Registers */ + #define M88E1000_PHY_SPEC_CTRL 0x10 /* PHY Specific Control Register */ +diff --git a/drivers/net/ethernet/intel/igb/e1000_hw.h b/drivers/net/ethernet/intel/igb/e1000_hw.h +index 2fb2213cd562e..2840ad95396af 100644 +--- a/drivers/net/ethernet/intel/igb/e1000_hw.h ++++ b/drivers/net/ethernet/intel/igb/e1000_hw.h +@@ -128,6 +128,8 @@ enum e1000_phy_type { + e1000_phy_ife, + e1000_phy_82580, + e1000_phy_i210, ++ e1000_phy_bcm54616, ++ e1000_phy_bcm5461s, + }; + + enum e1000_bus_type { +diff --git a/drivers/net/ethernet/intel/igb/e1000_phy.c b/drivers/net/ethernet/intel/igb/e1000_phy.c +index 68812d783f33e..1a4013ca6f85e 100644 +--- a/drivers/net/ethernet/intel/igb/e1000_phy.c ++++ b/drivers/net/ethernet/intel/igb/e1000_phy.c +@@ -146,6 +146,13 @@ s32 igb_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data) + * Control register. The MAC will take care of interfacing with the + * PHY to retrieve the desired data. + */ ++ if (phy->type == e1000_phy_bcm5461s) { ++ mdic = rd32(E1000_MDICNFG); ++ mdic &= ~E1000_MDICNFG_PHY_MASK; ++ mdic |= (phy->addr << E1000_MDICNFG_PHY_SHIFT); ++ wr32(E1000_MDICNFG, mdic); ++ } ++ + mdic = ((offset << E1000_MDIC_REG_SHIFT) | + (phy->addr << E1000_MDIC_PHY_SHIFT) | + (E1000_MDIC_OP_READ)); +@@ -202,6 +209,13 @@ s32 igb_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data) + * Control register. The MAC will take care of interfacing with the + * PHY to retrieve the desired data. + */ ++ if (phy->type == e1000_phy_bcm5461s) { ++ mdic = rd32(E1000_MDICNFG); ++ mdic &= ~E1000_MDICNFG_PHY_MASK; ++ mdic |= (phy->addr << E1000_MDICNFG_PHY_SHIFT); ++ wr32(E1000_MDICNFG, mdic); ++ } ++ + mdic = (((u32)data) | + (offset << E1000_MDIC_REG_SHIFT) | + (phy->addr << E1000_MDIC_PHY_SHIFT) | +@@ -1113,10 +1127,12 @@ s32 igb_setup_copper_link(struct e1000_hw *hw) + * depending on user settings. + */ + hw_dbg("Forcing Speed and Duplex\n"); +- ret_val = hw->phy.ops.force_speed_duplex(hw); +- if (ret_val) { +- hw_dbg("Error Forcing Speed and Duplex\n"); +- goto out; ++ if (hw->phy.ops.force_speed_duplex) { ++ ret_val = hw->phy.ops.force_speed_duplex(hw); ++ if (ret_val) { ++ hw_dbg("Error Forcing Speed and Duplex\n"); ++ goto out; ++ } + } + } + +@@ -2647,3 +2663,66 @@ static s32 igb_set_master_slave_mode(struct e1000_hw *hw) + + return hw->phy.ops.write_reg(hw, PHY_1000T_CTRL, phy_data); + } ++ ++/** ++ * igb_phy_init_script_5461s - Inits the BCM5461S PHY ++ * @hw: pointer to the HW structure ++ * ++ * Initializes a Broadcom Gigabit PHY. ++ **/ ++s32 igb_phy_init_script_5461s(struct e1000_hw *hw) ++{ ++ u16 mii_reg_led = 0; ++ ++ /* 1. Speed LED (Set the Link LED mode), Shadow 00010, 0x1C.bit2=1 */ ++ hw->phy.ops.write_reg(hw, 0x1C, 0x0800); ++ hw->phy.ops.read_reg(hw, 0x1C, &mii_reg_led); ++ mii_reg_led |= 0x0004; ++ hw->phy.ops.write_reg(hw, 0x1C, mii_reg_led | 0x8000); ++ ++ /* 2. Active LED (Set the Link LED mode), Shadow 01001, 0x1C.bit4=1, 0x10.bit5=0 */ ++ hw->phy.ops.write_reg(hw, 0x1C, 0x2400); ++ hw->phy.ops.read_reg(hw, 0x1C, &mii_reg_led); ++ mii_reg_led |= 0x0010; ++ hw->phy.ops.write_reg(hw, 0x1C, mii_reg_led | 0x8000); ++ hw->phy.ops.read_reg(hw, 0x10, &mii_reg_led); ++ mii_reg_led &= 0xffdf; ++ hw->phy.ops.write_reg(hw, 0x10, mii_reg_led); ++ ++ return 0; ++} ++ ++/** ++ * igb_get_phy_info_5461s - Retrieve 5461s PHY information ++ * @hw: pointer to the HW structure ++ * ++ * Read PHY status to determine if link is up. If link is up, then ++ * set/determine 10base-T extended distance and polarity correction. Read ++ * PHY port status to determine MDI/MDIx and speed. Based on the speed, ++ * determine on the cable length, local and remote receiver. ++ **/ ++s32 igb_get_phy_info_5461s(struct e1000_hw *hw) ++{ ++ struct e1000_phy_info *phy = &hw->phy; ++ s32 ret_val; ++ bool link; ++ ++ ret_val = igb_phy_has_link(hw, 1, 0, &link); ++ if (ret_val) ++ goto out; ++ ++ if (!link) { ++ ret_val = -E1000_ERR_CONFIG; ++ goto out; ++ } ++ ++ phy->polarity_correction = true; ++ ++ phy->is_mdix = true; ++ phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; ++ phy->local_rx = e1000_1000t_rx_status_ok; ++ phy->remote_rx = e1000_1000t_rx_status_ok; ++ ++out: ++ return ret_val; ++} +diff --git a/drivers/net/ethernet/intel/igb/e1000_phy.h b/drivers/net/ethernet/intel/igb/e1000_phy.h +index 9b622b33bb5ac..3b28873060946 100644 +--- a/drivers/net/ethernet/intel/igb/e1000_phy.h ++++ b/drivers/net/ethernet/intel/igb/e1000_phy.h +@@ -61,6 +61,8 @@ s32 igb_phy_has_link(struct e1000_hw *hw, u32 iterations, + void igb_power_up_phy_copper(struct e1000_hw *hw); + void igb_power_down_phy_copper(struct e1000_hw *hw); + s32 igb_phy_init_script_igp3(struct e1000_hw *hw); ++s32 igb_phy_init_script_5461s(struct e1000_hw *hw); ++s32 igb_get_phy_info_5461s(struct e1000_hw *hw); + s32 igb_initialize_M88E1512_phy(struct e1000_hw *hw); + s32 igb_initialize_M88E1543_phy(struct e1000_hw *hw); + s32 igb_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data); +diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c +index be456bae81690..4689079f8bbcd 100644 +--- a/drivers/net/ethernet/intel/igb/igb_main.c ++++ b/drivers/net/ethernet/intel/igb/igb_main.c +@@ -7356,11 +7356,19 @@ static int igb_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) + data->phy_id = adapter->hw.phy.addr; + break; + case SIOCGMIIREG: ++ adapter->hw.phy.addr = data->phy_id; + if (igb_read_phy_reg(&adapter->hw, data->reg_num & 0x1F, + &data->val_out)) + return -EIO; + break; + case SIOCSMIIREG: ++ if (!capable(CAP_NET_ADMIN)) ++ return -EPERM; ++ adapter->hw.phy.addr = data->phy_id; ++ if (igb_write_phy_reg(&adapter->hw, data->reg_num & 0x1F, ++ data->val_in)) ++ return -EIO; ++ break; + default: + return -EOPNOTSUPP; + } diff --git a/packages/base/any/kernels/4.9-lts/patches/series b/packages/base/any/kernels/4.9-lts/patches/series index 8b137891..e26a164c 100644 --- a/packages/base/any/kernels/4.9-lts/patches/series +++ b/packages/base/any/kernels/4.9-lts/patches/series @@ -1 +1 @@ - +driver-support-intel-igb-bcm5461-phy.patch