Loading drivers/net/ethernet/aquantia/atlantic-fwd/atl_common.h +1 −1 Original line number Diff line number Diff line Loading @@ -18,7 +18,7 @@ #include <linux/netdevice.h> #include <linux/moduleparam.h> #define ATL_VERSION "1.0.22" #define ATL_VERSION "1.0.23" struct atl_nic; Loading drivers/net/ethernet/aquantia/atlantic-fwd/atl_ethtool.c +18 −0 Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ */ #include <linux/ethtool.h> #include <linux/pm_runtime.h> #include "atl_common.h" #include "atl_ring.h" Loading Loading @@ -2066,6 +2067,8 @@ static int atl_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) ret = device_set_wakeup_enable(&nic->hw.pdev->dev, !!(nic->flags & ATL_FL_WOL)); if (ret == -EEXIST) ret = 0; if (ret) { atl_nic_err("device_set_wakeup_enable failed: %d\n", -ret); nic->flags &= ~ATL_FL_WOL; Loading @@ -2075,6 +2078,19 @@ static int atl_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) return ret; } static int atl_ethtool_begin(struct net_device *ndev) { struct atl_nic *nic = netdev_priv(ndev); pm_runtime_get_sync(&nic->hw.pdev->dev); return 0; } static void atl_ethtool_complete(struct net_device *ndev) { struct atl_nic *nic = netdev_priv(ndev); pm_runtime_put(&nic->hw.pdev->dev); } const struct ethtool_ops atl_ethtool_ops = { .get_link = atl_ethtool_get_link, #ifndef ATL_HAVE_ETHTOOL_KSETTINGS Loading Loading @@ -2110,4 +2126,6 @@ const struct ethtool_ops atl_ethtool_ops = { .set_coalesce = atl_set_coalesce, .get_wol = atl_get_wol, .set_wol = atl_set_wol, .begin = atl_ethtool_begin, .complete = atl_ethtool_complete, }; drivers/net/ethernet/aquantia/atlantic-fwd/atl_fw.c +71 −22 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ struct atl_link_type atl_link_types[] = { LINK_TYPE("10GBaseT-FD", 10000, ETHTOOL_LINK_MODE_10000baseT_Full_BIT, 1, 1 << 11) }; #define ATL_FW2_LINK_MSK (BIT(5) | BIT(8) | BIT(10) | BIT(11)) const int atl_num_rates = ARRAY_SIZE(atl_link_types); Loading Loading @@ -188,7 +189,8 @@ static int __atl_fw2_get_link_caps(struct atl_hw *hw) uint32_t fw_stat_addr = mcp->fw_stat_addr; struct atl_link_type *rate; unsigned int supported = 0; uint32_t caps[2], mask = atl_fw2_pause_mask | atl_fw2_link_drop; uint32_t caps[2], caps_ex; uint32_t mask = atl_fw2_pause_mask | atl_fw2_link_drop; int i, ret; atl_dev_dbg("Host data struct addr: %#x\n", fw_stat_addr); Loading @@ -196,10 +198,14 @@ static int __atl_fw2_get_link_caps(struct atl_hw *hw) caps, 8); if (ret) return ret; ret = atl_read_fwstat_word(hw, atl_fw2_stat_caps_ex, &caps_ex); if (ret) return ret; mcp->caps_low = caps[0]; mcp->caps_high = caps[1]; atl_dev_dbg("Got link caps: %#x %#x\n", caps[0], caps[1]); mcp->caps_ex = caps_ex; atl_dev_dbg("Got link caps: %#x %#x %#x\n", caps[0], caps[1], caps_ex); atl_for_each_rate(i, rate) { uint32_t bit = rate->fw_bits[1]; Loading @@ -224,9 +230,6 @@ static inline unsigned int atl_link_adv(struct atl_link_state *lstate) { struct atl_hw *hw = container_of(lstate, struct atl_hw, link_state); if (lstate->force_off) return 0; if (lstate->thermal_throttled && hw->thermal.flags & atl_thermal_throttle) /* FW doesn't provide raw LP's advertized rates, only Loading Loading @@ -319,16 +322,14 @@ static void __atl_fw2_set_link(struct atl_hw *hw) hi_bits ^= atl_fw2_asym_pause; bits = atl_set_fw_bits(hw, 1); /* If no modes are advertized, put PHY into low-power */ if (!bits) hi_bits |= atl_fw2_link_drop; else hi_bits |= bits >> 32; if (lstate->force_off) hi_bits |= atl_fw2_link_drop; hw->mcp.req_high = hi_bits; atl_write(hw, ATL_MCP_SCRATCH(FW2_LINK_REQ_LOW), bits); atl_write_mask_bits(hw, ATL_MCP_SCRATCH(FW2_LINK_REQ_LOW), ATL_FW2_LINK_MSK, bits); atl_write(hw, ATL_MCP_SCRATCH(FW2_LINK_REQ_HIGH), hi_bits); } Loading Loading @@ -374,25 +375,47 @@ static void atl_fw2_set_default_link(struct atl_hw *hw) lstate->eee_enabled = 1; } static int atl_fw2_enable_wol(struct atl_hw *hw) static int atl_fw1_enable_wol(struct atl_hw *hw, unsigned int wol_mode) { int ret; return -EOPNOTSUPP; } static int atl_fw2_enable_wol(struct atl_hw *hw, unsigned int wol_mode) { int ret = 0; struct offloadInfo *info; struct drvIface *msg = NULL; uint32_t val, wol_bits = 0; uint32_t val, wol_bits = 0, req_high = hw->mcp.req_high; uint32_t low_req; atl_lock_fw(hw); if (hw->wol_mode & WAKE_PHY) if (hw->mcp.caps_ex & atl_fw2_ex_caps_wol_ex) { ret = atl_write_fwsettings_word(hw, atl_fw2_setings_wol_ex, atl_fw2_wol_ex_wake_on_link_keep_rate | atl_fw2_wol_ex_wake_on_magic_keep_rate); if (ret) return ret; } low_req = atl_read(hw, ATL_MCP_SCRATCH(FW2_LINK_REQ_LOW)); if (wol_mode & atl_fw_wake_on_link) { wol_bits |= atl_fw2_wake_on_link; low_req &= ~atl_fw2_wake_on_link_force; } if (hw->wol_mode & WAKE_MAGIC) { if (wol_mode & atl_fw_wake_on_link_rtpm) { wol_bits |= atl_fw2_wake_on_link; low_req |= atl_fw2_wake_on_link_force; } if (wol_mode & atl_fw_wake_on_magic) { wol_bits |= atl_fw2_nic_proxy | atl_fw2_wol; ret = -ENOMEM; msg = kzalloc(sizeof(*msg), GFP_KERNEL); if (!msg) goto unlock_free; goto unlock; info = &msg->fw2xOffloads; info->version = 0; Loading @@ -408,8 +431,10 @@ static int atl_fw2_enable_wol(struct atl_hw *hw) } } atl_write(hw, ATL_MCP_SCRATCH(FW2_LINK_REQ_LOW), 0); atl_write(hw, ATL_MCP_SCRATCH(FW2_LINK_REQ_HIGH), wol_bits); req_high |= wol_bits; req_high &= ~atl_fw2_link_drop; atl_write(hw, ATL_MCP_SCRATCH(FW2_LINK_REQ_LOW), low_req); atl_write(hw, ATL_MCP_SCRATCH(FW2_LINK_REQ_HIGH), req_high); busy_wait(100, mdelay(1), val, atl_read(hw, ATL_MCP_SCRATCH(FW2_LINK_RES_HIGH)), (val & wol_bits) != wol_bits); Loading @@ -419,8 +444,9 @@ static int atl_fw2_enable_wol(struct atl_hw *hw) atl_dev_err("Timeout waiting for WoL enable\n"); unlock_free: atl_unlock_fw(hw); kfree(msg); unlock: atl_unlock_fw(hw); return ret; } Loading Loading @@ -537,6 +563,24 @@ static void __atl_fw2_thermal_check(struct atl_hw *hw, uint32_t sts) } } static int atl_fw2_dump_cfg(struct atl_hw *hw) { /* save link configuration */ hw->fw_cfg_dump[0] = atl_read(hw, ATL_MCP_SCRATCH(FW2_LINK_REQ_LOW)); hw->fw_cfg_dump[1] = atl_read(hw, ATL_MCP_SCRATCH(FW2_LINK_REQ_HIGH)) & 0xF18; return 0; } static int atl_fw2_restore_cfg(struct atl_hw *hw) { /* restore link configuration */ atl_write(hw, ATL_MCP_SCRATCH(FW2_LINK_REQ_LOW), hw->fw_cfg_dump[0]); atl_write(hw, ATL_MCP_SCRATCH(FW2_LINK_REQ_HIGH), hw->fw_cfg_dump[1]); return 0; } static struct atl_fw_ops atl_fw_ops[2] = { [0] = { .__wait_fw_init = __atl_fw1_wait_fw_init, Loading @@ -545,8 +589,10 @@ static struct atl_fw_ops atl_fw_ops[2] = { .__get_link_caps = __atl_fw1_get_link_caps, .restart_aneg = atl_fw1_unsupported, .set_default_link = atl_fw1_set_default_link, .enable_wol = atl_fw1_unsupported, .enable_wol = atl_fw1_enable_wol, .get_phy_temperature = (void *)atl_fw1_unsupported, .dump_cfg = atl_fw1_unsupported, .restore_cfg = atl_fw1_unsupported, .efuse_shadow_addr_reg = ATL_MCP_SCRATCH(FW1_EFUSE_SHADOW), }, [1] = { Loading @@ -558,6 +604,8 @@ static struct atl_fw_ops atl_fw_ops[2] = { .set_default_link = atl_fw2_set_default_link, .enable_wol = atl_fw2_enable_wol, .get_phy_temperature = atl_fw2_get_phy_temperature, .dump_cfg = atl_fw2_dump_cfg, .restore_cfg = atl_fw2_restore_cfg, .efuse_shadow_addr_reg = ATL_MCP_SCRATCH(FW2_EFUSE_SHADOW), }, }; Loading Loading @@ -811,7 +859,8 @@ int atl_fw_init(struct atl_hw *hw) mcp->next_wdog = jiffies + 2 * HZ; if (major > 1) { mcp->req_high = 0; mcp->req_high = atl_read(hw, ATL_MCP_SCRATCH(FW2_LINK_REQ_HIGH)); ret = atl_read_fwstat_word(hw, atl_fw2_stat_settings_addr, &mcp->fw_settings_addr); Loading drivers/net/ethernet/aquantia/atlantic-fwd/atl_fw.h +24 −3 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ struct atl_mcp { uint32_t req_high_mask; /* Clears link rate-dependend bits */ uint32_t caps_low; uint32_t caps_high; uint32_t caps_ex; struct mutex lock; unsigned long next_wdog; bool wdog_disabled; Loading Loading @@ -59,6 +60,7 @@ enum atl_fw2_opts { atl_define_bit(atl_fw2_asym_pause, 4) atl_fw2_pause_mask = atl_fw2_pause | atl_fw2_asym_pause, atl_define_bit(atl_fw2_wake_on_link, 16) atl_define_bit(atl_fw2_wake_on_link_force, 17) atl_define_bit(atl_fw2_phy_temp, 18) atl_define_bit(atl_fw2_set_thermal, 21) atl_define_bit(atl_fw2_link_drop, 22) Loading @@ -67,17 +69,28 @@ enum atl_fw2_opts { atl_define_bit(atl_fw2_thermal_alarm, 29) }; enum atl_fw2_ex_caps { atl_define_bit(atl_fw2_ex_caps_wol_ex, 23) }; enum atl_fw2_wol_ex { atl_define_bit(atl_fw2_wol_ex_wake_on_link_keep_rate, 0) atl_define_bit(atl_fw2_wol_ex_wake_on_magic_keep_rate, 1) }; enum atl_fw2_stat_offt { atl_fw2_stat_phy_hbeat = 0x4c, atl_fw2_stat_temp = 0x50, atl_fw2_stat_lcaps = 0x84, atl_fw2_stat_settings_addr = 0x110, atl_fw2_stat_settings_len = 0x114, atl_fw2_stat_settings_addr = 0x10c, atl_fw2_stat_settings_len = 0x110, atl_fw2_stat_caps_ex = 0x114, }; enum atl_fw2_settings_offt { atl_fw2_setings_msm_opts = 0x90, atl_fw2_setings_media_detect = 0x98, atl_fw2_setings_wol_ex = 0x9c, }; enum atl_fw2_msm_opts { Loading @@ -103,6 +116,12 @@ struct atl_fc_state { enum atl_fc_mode cur; }; enum atl_wake_flags { atl_fw_wake_on_link = WAKE_PHY, atl_fw_wake_on_magic = WAKE_MAGIC, atl_fw_wake_on_link_rtpm = BIT(10), }; #define ATL_EEE_BIT_OFFT 16 #define ATL_EEE_MASK ~(BIT(ATL_EEE_BIT_OFFT) - 1) Loading Loading @@ -133,8 +152,10 @@ struct atl_fw_ops { int (*__get_link_caps)(struct atl_hw *hw); int (*restart_aneg)(struct atl_hw *hw); void (*set_default_link)(struct atl_hw *hw); int (*enable_wol)(struct atl_hw *hw); int (*enable_wol)(struct atl_hw *hw, unsigned int wol_mode); int (*get_phy_temperature)(struct atl_hw *hw, int *temp); int (*dump_cfg)(struct atl_hw *hw); int (*restore_cfg)(struct atl_hw *hw); unsigned efuse_shadow_addr_reg; }; Loading drivers/net/ethernet/aquantia/atlantic-fwd/atl_hw.c +19 −5 Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ */ #include <linux/interrupt.h> #include <linux/pm_runtime.h> #include "atl_common.h" #include "atl_hw.h" Loading Loading @@ -138,12 +139,18 @@ static int atl_hw_reset_nonrbl(struct atl_hw *hw) } atl_dev_dbg("FLB kickstart took %d ms\n", tries); atl_write(hw, 0x404, 0x80e0); atl_write(hw, 0x404, 0x40e1); mdelay(50); atl_write(hw, 0x3a0, 1); atl_glb_soft_reset_full(hw); if (hw->mcp.ops) hw->mcp.ops->restore_cfg(hw); /* unstall FW*/ atl_write(hw, 0x404, 0x40e0); ret = atl_fw_init(hw); unlock: Loading Loading @@ -197,6 +204,9 @@ int atl_hw_reset(struct atl_hw *hw) atl_glb_soft_reset_full(hw); if (hw->mcp.ops) hw->mcp.ops->restore_cfg(hw); atl_write(hw, ATL_GLOBAL_CTRL2, 0x40e0); for (tries = 0; tries < 10000; mdelay(1)) { Loading Loading @@ -320,13 +330,17 @@ void atl_refresh_link(struct atl_nic *nic) link = hw->mcp.ops->check_link(hw); if (link) { if (link != prev_link) if (link != prev_link) { atl_nic_info("Link up: %s\n", link->name); netif_carrier_on(nic->ndev); pm_runtime_get_sync(&nic->hw.pdev->dev); } } else { if (link != prev_link) if (link != prev_link) { atl_nic_info("Link down\n"); netif_carrier_off(nic->ndev); pm_runtime_put_sync(&nic->hw.pdev->dev); } } atl_rx_xoff_set(hw, !!(hw->link_state.fc.cur & atl_fc_rx)); Loading Loading
drivers/net/ethernet/aquantia/atlantic-fwd/atl_common.h +1 −1 Original line number Diff line number Diff line Loading @@ -18,7 +18,7 @@ #include <linux/netdevice.h> #include <linux/moduleparam.h> #define ATL_VERSION "1.0.22" #define ATL_VERSION "1.0.23" struct atl_nic; Loading
drivers/net/ethernet/aquantia/atlantic-fwd/atl_ethtool.c +18 −0 Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ */ #include <linux/ethtool.h> #include <linux/pm_runtime.h> #include "atl_common.h" #include "atl_ring.h" Loading Loading @@ -2066,6 +2067,8 @@ static int atl_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) ret = device_set_wakeup_enable(&nic->hw.pdev->dev, !!(nic->flags & ATL_FL_WOL)); if (ret == -EEXIST) ret = 0; if (ret) { atl_nic_err("device_set_wakeup_enable failed: %d\n", -ret); nic->flags &= ~ATL_FL_WOL; Loading @@ -2075,6 +2078,19 @@ static int atl_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) return ret; } static int atl_ethtool_begin(struct net_device *ndev) { struct atl_nic *nic = netdev_priv(ndev); pm_runtime_get_sync(&nic->hw.pdev->dev); return 0; } static void atl_ethtool_complete(struct net_device *ndev) { struct atl_nic *nic = netdev_priv(ndev); pm_runtime_put(&nic->hw.pdev->dev); } const struct ethtool_ops atl_ethtool_ops = { .get_link = atl_ethtool_get_link, #ifndef ATL_HAVE_ETHTOOL_KSETTINGS Loading Loading @@ -2110,4 +2126,6 @@ const struct ethtool_ops atl_ethtool_ops = { .set_coalesce = atl_set_coalesce, .get_wol = atl_get_wol, .set_wol = atl_set_wol, .begin = atl_ethtool_begin, .complete = atl_ethtool_complete, };
drivers/net/ethernet/aquantia/atlantic-fwd/atl_fw.c +71 −22 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ struct atl_link_type atl_link_types[] = { LINK_TYPE("10GBaseT-FD", 10000, ETHTOOL_LINK_MODE_10000baseT_Full_BIT, 1, 1 << 11) }; #define ATL_FW2_LINK_MSK (BIT(5) | BIT(8) | BIT(10) | BIT(11)) const int atl_num_rates = ARRAY_SIZE(atl_link_types); Loading Loading @@ -188,7 +189,8 @@ static int __atl_fw2_get_link_caps(struct atl_hw *hw) uint32_t fw_stat_addr = mcp->fw_stat_addr; struct atl_link_type *rate; unsigned int supported = 0; uint32_t caps[2], mask = atl_fw2_pause_mask | atl_fw2_link_drop; uint32_t caps[2], caps_ex; uint32_t mask = atl_fw2_pause_mask | atl_fw2_link_drop; int i, ret; atl_dev_dbg("Host data struct addr: %#x\n", fw_stat_addr); Loading @@ -196,10 +198,14 @@ static int __atl_fw2_get_link_caps(struct atl_hw *hw) caps, 8); if (ret) return ret; ret = atl_read_fwstat_word(hw, atl_fw2_stat_caps_ex, &caps_ex); if (ret) return ret; mcp->caps_low = caps[0]; mcp->caps_high = caps[1]; atl_dev_dbg("Got link caps: %#x %#x\n", caps[0], caps[1]); mcp->caps_ex = caps_ex; atl_dev_dbg("Got link caps: %#x %#x %#x\n", caps[0], caps[1], caps_ex); atl_for_each_rate(i, rate) { uint32_t bit = rate->fw_bits[1]; Loading @@ -224,9 +230,6 @@ static inline unsigned int atl_link_adv(struct atl_link_state *lstate) { struct atl_hw *hw = container_of(lstate, struct atl_hw, link_state); if (lstate->force_off) return 0; if (lstate->thermal_throttled && hw->thermal.flags & atl_thermal_throttle) /* FW doesn't provide raw LP's advertized rates, only Loading Loading @@ -319,16 +322,14 @@ static void __atl_fw2_set_link(struct atl_hw *hw) hi_bits ^= atl_fw2_asym_pause; bits = atl_set_fw_bits(hw, 1); /* If no modes are advertized, put PHY into low-power */ if (!bits) hi_bits |= atl_fw2_link_drop; else hi_bits |= bits >> 32; if (lstate->force_off) hi_bits |= atl_fw2_link_drop; hw->mcp.req_high = hi_bits; atl_write(hw, ATL_MCP_SCRATCH(FW2_LINK_REQ_LOW), bits); atl_write_mask_bits(hw, ATL_MCP_SCRATCH(FW2_LINK_REQ_LOW), ATL_FW2_LINK_MSK, bits); atl_write(hw, ATL_MCP_SCRATCH(FW2_LINK_REQ_HIGH), hi_bits); } Loading Loading @@ -374,25 +375,47 @@ static void atl_fw2_set_default_link(struct atl_hw *hw) lstate->eee_enabled = 1; } static int atl_fw2_enable_wol(struct atl_hw *hw) static int atl_fw1_enable_wol(struct atl_hw *hw, unsigned int wol_mode) { int ret; return -EOPNOTSUPP; } static int atl_fw2_enable_wol(struct atl_hw *hw, unsigned int wol_mode) { int ret = 0; struct offloadInfo *info; struct drvIface *msg = NULL; uint32_t val, wol_bits = 0; uint32_t val, wol_bits = 0, req_high = hw->mcp.req_high; uint32_t low_req; atl_lock_fw(hw); if (hw->wol_mode & WAKE_PHY) if (hw->mcp.caps_ex & atl_fw2_ex_caps_wol_ex) { ret = atl_write_fwsettings_word(hw, atl_fw2_setings_wol_ex, atl_fw2_wol_ex_wake_on_link_keep_rate | atl_fw2_wol_ex_wake_on_magic_keep_rate); if (ret) return ret; } low_req = atl_read(hw, ATL_MCP_SCRATCH(FW2_LINK_REQ_LOW)); if (wol_mode & atl_fw_wake_on_link) { wol_bits |= atl_fw2_wake_on_link; low_req &= ~atl_fw2_wake_on_link_force; } if (hw->wol_mode & WAKE_MAGIC) { if (wol_mode & atl_fw_wake_on_link_rtpm) { wol_bits |= atl_fw2_wake_on_link; low_req |= atl_fw2_wake_on_link_force; } if (wol_mode & atl_fw_wake_on_magic) { wol_bits |= atl_fw2_nic_proxy | atl_fw2_wol; ret = -ENOMEM; msg = kzalloc(sizeof(*msg), GFP_KERNEL); if (!msg) goto unlock_free; goto unlock; info = &msg->fw2xOffloads; info->version = 0; Loading @@ -408,8 +431,10 @@ static int atl_fw2_enable_wol(struct atl_hw *hw) } } atl_write(hw, ATL_MCP_SCRATCH(FW2_LINK_REQ_LOW), 0); atl_write(hw, ATL_MCP_SCRATCH(FW2_LINK_REQ_HIGH), wol_bits); req_high |= wol_bits; req_high &= ~atl_fw2_link_drop; atl_write(hw, ATL_MCP_SCRATCH(FW2_LINK_REQ_LOW), low_req); atl_write(hw, ATL_MCP_SCRATCH(FW2_LINK_REQ_HIGH), req_high); busy_wait(100, mdelay(1), val, atl_read(hw, ATL_MCP_SCRATCH(FW2_LINK_RES_HIGH)), (val & wol_bits) != wol_bits); Loading @@ -419,8 +444,9 @@ static int atl_fw2_enable_wol(struct atl_hw *hw) atl_dev_err("Timeout waiting for WoL enable\n"); unlock_free: atl_unlock_fw(hw); kfree(msg); unlock: atl_unlock_fw(hw); return ret; } Loading Loading @@ -537,6 +563,24 @@ static void __atl_fw2_thermal_check(struct atl_hw *hw, uint32_t sts) } } static int atl_fw2_dump_cfg(struct atl_hw *hw) { /* save link configuration */ hw->fw_cfg_dump[0] = atl_read(hw, ATL_MCP_SCRATCH(FW2_LINK_REQ_LOW)); hw->fw_cfg_dump[1] = atl_read(hw, ATL_MCP_SCRATCH(FW2_LINK_REQ_HIGH)) & 0xF18; return 0; } static int atl_fw2_restore_cfg(struct atl_hw *hw) { /* restore link configuration */ atl_write(hw, ATL_MCP_SCRATCH(FW2_LINK_REQ_LOW), hw->fw_cfg_dump[0]); atl_write(hw, ATL_MCP_SCRATCH(FW2_LINK_REQ_HIGH), hw->fw_cfg_dump[1]); return 0; } static struct atl_fw_ops atl_fw_ops[2] = { [0] = { .__wait_fw_init = __atl_fw1_wait_fw_init, Loading @@ -545,8 +589,10 @@ static struct atl_fw_ops atl_fw_ops[2] = { .__get_link_caps = __atl_fw1_get_link_caps, .restart_aneg = atl_fw1_unsupported, .set_default_link = atl_fw1_set_default_link, .enable_wol = atl_fw1_unsupported, .enable_wol = atl_fw1_enable_wol, .get_phy_temperature = (void *)atl_fw1_unsupported, .dump_cfg = atl_fw1_unsupported, .restore_cfg = atl_fw1_unsupported, .efuse_shadow_addr_reg = ATL_MCP_SCRATCH(FW1_EFUSE_SHADOW), }, [1] = { Loading @@ -558,6 +604,8 @@ static struct atl_fw_ops atl_fw_ops[2] = { .set_default_link = atl_fw2_set_default_link, .enable_wol = atl_fw2_enable_wol, .get_phy_temperature = atl_fw2_get_phy_temperature, .dump_cfg = atl_fw2_dump_cfg, .restore_cfg = atl_fw2_restore_cfg, .efuse_shadow_addr_reg = ATL_MCP_SCRATCH(FW2_EFUSE_SHADOW), }, }; Loading Loading @@ -811,7 +859,8 @@ int atl_fw_init(struct atl_hw *hw) mcp->next_wdog = jiffies + 2 * HZ; if (major > 1) { mcp->req_high = 0; mcp->req_high = atl_read(hw, ATL_MCP_SCRATCH(FW2_LINK_REQ_HIGH)); ret = atl_read_fwstat_word(hw, atl_fw2_stat_settings_addr, &mcp->fw_settings_addr); Loading
drivers/net/ethernet/aquantia/atlantic-fwd/atl_fw.h +24 −3 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ struct atl_mcp { uint32_t req_high_mask; /* Clears link rate-dependend bits */ uint32_t caps_low; uint32_t caps_high; uint32_t caps_ex; struct mutex lock; unsigned long next_wdog; bool wdog_disabled; Loading Loading @@ -59,6 +60,7 @@ enum atl_fw2_opts { atl_define_bit(atl_fw2_asym_pause, 4) atl_fw2_pause_mask = atl_fw2_pause | atl_fw2_asym_pause, atl_define_bit(atl_fw2_wake_on_link, 16) atl_define_bit(atl_fw2_wake_on_link_force, 17) atl_define_bit(atl_fw2_phy_temp, 18) atl_define_bit(atl_fw2_set_thermal, 21) atl_define_bit(atl_fw2_link_drop, 22) Loading @@ -67,17 +69,28 @@ enum atl_fw2_opts { atl_define_bit(atl_fw2_thermal_alarm, 29) }; enum atl_fw2_ex_caps { atl_define_bit(atl_fw2_ex_caps_wol_ex, 23) }; enum atl_fw2_wol_ex { atl_define_bit(atl_fw2_wol_ex_wake_on_link_keep_rate, 0) atl_define_bit(atl_fw2_wol_ex_wake_on_magic_keep_rate, 1) }; enum atl_fw2_stat_offt { atl_fw2_stat_phy_hbeat = 0x4c, atl_fw2_stat_temp = 0x50, atl_fw2_stat_lcaps = 0x84, atl_fw2_stat_settings_addr = 0x110, atl_fw2_stat_settings_len = 0x114, atl_fw2_stat_settings_addr = 0x10c, atl_fw2_stat_settings_len = 0x110, atl_fw2_stat_caps_ex = 0x114, }; enum atl_fw2_settings_offt { atl_fw2_setings_msm_opts = 0x90, atl_fw2_setings_media_detect = 0x98, atl_fw2_setings_wol_ex = 0x9c, }; enum atl_fw2_msm_opts { Loading @@ -103,6 +116,12 @@ struct atl_fc_state { enum atl_fc_mode cur; }; enum atl_wake_flags { atl_fw_wake_on_link = WAKE_PHY, atl_fw_wake_on_magic = WAKE_MAGIC, atl_fw_wake_on_link_rtpm = BIT(10), }; #define ATL_EEE_BIT_OFFT 16 #define ATL_EEE_MASK ~(BIT(ATL_EEE_BIT_OFFT) - 1) Loading Loading @@ -133,8 +152,10 @@ struct atl_fw_ops { int (*__get_link_caps)(struct atl_hw *hw); int (*restart_aneg)(struct atl_hw *hw); void (*set_default_link)(struct atl_hw *hw); int (*enable_wol)(struct atl_hw *hw); int (*enable_wol)(struct atl_hw *hw, unsigned int wol_mode); int (*get_phy_temperature)(struct atl_hw *hw, int *temp); int (*dump_cfg)(struct atl_hw *hw); int (*restore_cfg)(struct atl_hw *hw); unsigned efuse_shadow_addr_reg; }; Loading
drivers/net/ethernet/aquantia/atlantic-fwd/atl_hw.c +19 −5 Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ */ #include <linux/interrupt.h> #include <linux/pm_runtime.h> #include "atl_common.h" #include "atl_hw.h" Loading Loading @@ -138,12 +139,18 @@ static int atl_hw_reset_nonrbl(struct atl_hw *hw) } atl_dev_dbg("FLB kickstart took %d ms\n", tries); atl_write(hw, 0x404, 0x80e0); atl_write(hw, 0x404, 0x40e1); mdelay(50); atl_write(hw, 0x3a0, 1); atl_glb_soft_reset_full(hw); if (hw->mcp.ops) hw->mcp.ops->restore_cfg(hw); /* unstall FW*/ atl_write(hw, 0x404, 0x40e0); ret = atl_fw_init(hw); unlock: Loading Loading @@ -197,6 +204,9 @@ int atl_hw_reset(struct atl_hw *hw) atl_glb_soft_reset_full(hw); if (hw->mcp.ops) hw->mcp.ops->restore_cfg(hw); atl_write(hw, ATL_GLOBAL_CTRL2, 0x40e0); for (tries = 0; tries < 10000; mdelay(1)) { Loading Loading @@ -320,13 +330,17 @@ void atl_refresh_link(struct atl_nic *nic) link = hw->mcp.ops->check_link(hw); if (link) { if (link != prev_link) if (link != prev_link) { atl_nic_info("Link up: %s\n", link->name); netif_carrier_on(nic->ndev); pm_runtime_get_sync(&nic->hw.pdev->dev); } } else { if (link != prev_link) if (link != prev_link) { atl_nic_info("Link down\n"); netif_carrier_off(nic->ndev); pm_runtime_put_sync(&nic->hw.pdev->dev); } } atl_rx_xoff_set(hw, !!(hw->link_state.fc.cur & atl_fc_rx)); Loading