Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5102ebd4 authored by Dmitry Bogdanov's avatar Dmitry Bogdanov Committed by Jinesh K. Jayakumar
Browse files

atlantic-forwarding driver v1.0.23



[ATLDRV-983] - runtime D3 support
[ATLDRV-1056] - Crash in atl_reconfigure, if rx size is changed after traffic exchange
[ATLDRV-1023] - AQ056: Wake on link race condition with host power manament

commit e9b4dee78870ec931a75cacbdd84499a65fab591
Author: Dmitry Bogdanov <dmitry.bogdanov@aquantia.com>
Date:   Mon Aug 26 14:41:35 2019 +0300

    Update release notes, version bump

commit c7c69c925d3bbd5caa5336f699412b79978876df
Author: Dmitry Bogdanov <dmitry.bogdanov@aquantia.com>
Date:   Thu Aug 22 17:41:48 2019 +0300

    rename fw_ops.push_cfg to restore_cfg

commit b180a0060bad074cb04711f422747efaf9168f08
Author: Dmitry Bogdanov <dmitry.bogdanov@aquantia.com>
Date:   Thu Aug 22 17:32:04 2019 +0300

    use macros instead of hardcoded registers

commit 997385f36de78b7dec03f8b9099865ef73651ea8
Author: Dmitry Bogdanov <dmitry.bogdanov@aquantia.com>
Date:   Thu Aug 22 17:07:32 2019 +0300

    add FW provisioning in RBL mode

commit cf9de81f6a4b5b4c7527492ab288714f3b91b899
Author: Dmitry Bogdanov <dmitry.bogdanov@aquantia.com>
Date:   Thu Aug 22 17:06:52 2019 +0300

    revert reset sequence to recommended

    as it turned out FW stall bit is semi sticky: it is cleared in
    the register on reset, but FW is kept stall up to next MCP reset

commit aceb231d8e30cd6a694c55d309e81510e34b132d
Author: Dmitry Bogdanov <dmitry.bogdanov@aquantia.com>
Date:   Thu Aug 22 12:20:54 2019 +0300

    do not reset FW after unstall

commit 27e1c7402ecbd03b93212f409683e8f9418bc0fe
Author: Dmitry Bogdanov <dmitry.bogdanov@aquantia.com>
Date:   Thu Aug 22 11:57:14 2019 +0300

    fix reading CAPS_EX from FW

commit 30314d32125a5266d26368e0d6d426bbb4de398a
Author: Dmitry Bogdanov <dmitry.bogdanov@aquantia.com>
Date:   Tue Aug 20 17:36:57 2019 +0300

    fix clean up of work queue on suspend

commit e5276dbb04446f648c118c7067739bbf647f24bc
Author: Dmitry Bogdanov <dmitry.bogdanov@aquantia.com>
Date:   Tue Aug 20 17:36:20 2019 +0300

    do not clear the link mask on interface down

commit 2ece967b5c43168c1225876d3bb2402789a12f5f
Author: Dmitry Bogdanov <dmitry.bogdanov@aquantia.com>
Date:   Mon Aug 19 17:33:39 2019 +0300

    dump/restore FW configuration during restart

commit 3991f8d7adbecbc469cbbda5a459f49b3b86f3a1
Author: Dmitry Bogdanov <dmitry.bogdanov@aquantia.com>
Date:   Mon Aug 19 14:16:03 2019 +0300

    Turn on wol keep rate option in FW

commit 12a8d43e4da19c63ca4bd9f3ad906c1bcc15a5c5
Author: Dmitry Bogdanov <dmitry.bogdanov@aquantia.com>
Date:   Mon Aug 19 13:03:59 2019 +0300

    Read EX CAPS form FW

commit 44b9bd64d0eb214ac8b6ac6b82f7ba88ea1c51a7
Author: Dmitry Bogdanov <dmitry.bogdanov@aquantia.com>
Date:   Mon Aug 19 12:30:08 2019 +0300

    Do not drop the link on reconfigure

commit f0b52bb28ac5ab93790d61b6da8ca5896de831b3
Author: Dmitry Bogdanov <dmitry.bogdanov@aquantia.com>
Date:   Mon Aug 12 17:27:32 2019 +0300

    Do not drop the link on hw reset

commit c88fc412e9610974ab59d5211602b838e4515f05
Author: Dmitry Bogdanov <dmitry.bogdanov@aquantia.com>
Date:   Mon Aug 5 15:24:46 2019 +0300

    create an enum for wake on link force bit

commit d7dabad0259dc9b1525d05762c66acc68a83ba99
Author: Dmitry Bogdanov <dmitry.bogdanov@aquantia.com>
Date:   Fri Aug 2 18:44:10 2019 +0300

    Turn on wake_on_link for life host for RTPM suspend

commit da74aa3b7e2c9b1023dfdd86acc9bca334f95ea2
Author: Dmitry Bogdanov <dmitry.bogdanov@aquantia.com>
Date:   Fri Aug 2 18:19:29 2019 +0300

    Disable Runtime Power Management if FW do not support it

commit afb57f2941d04f21e534077fe10f42de7c278c58
Author: Dmitry Bogdanov <dmitry.bogdanov@aquantia.com>
Date:   Fri Jul 12 18:35:06 2019 +0300

    Implement Runtime Power Management

    After link down the device goes to low power mode with delay 10 seconds.
    Delay is configured by module parameter sleep_delay in milliseconds.
    Disabled by default.
    Enabled by write 'auto' into
    /sys/bus/pci/devices/.../power/control

commit 136ef09c53a9a502b446b3cbeeb733fdc3712a24
Author: Mark Starovoytov <mstarovo@aquantia.com>
Date:   Thu Aug 8 18:07:00 2019 +0300

    Perform HW reset during reconfigure.

Signed-off-by: default avatarDmitry Bogdanov <dmitry.bogdanov@aquantia.com>
Change-Id: I0eab0c647b1a06d97ecb07b34125b3f5e03c6832
Git-commit: 233592c1f59eccb87b1609f342826de383fde073
Git-repo: https://github.com/aquantia/linux-4.14-atlantic-forwarding


Signed-off-by: default avatarJinesh K. Jayakumar <jineshk@codeaurora.org>
parent 8f930152
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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;

+18 −0
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@
 */

#include <linux/ethtool.h>
#include <linux/pm_runtime.h>

#include "atl_common.h"
#include "atl_ring.h"
@@ -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;
@@ -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
@@ -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,
};
+71 −22
Original line number Diff line number Diff line
@@ -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);

@@ -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);
@@ -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];
@@ -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
@@ -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);
}

@@ -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;
@@ -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);
@@ -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;
}

@@ -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,
@@ -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] = {
@@ -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),
	},
};
@@ -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);
+24 −3
Original line number Diff line number Diff line
@@ -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;
@@ -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)
@@ -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 {
@@ -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)

@@ -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;
};

+19 −5
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@
 */

#include <linux/interrupt.h>
#include <linux/pm_runtime.h>

#include "atl_common.h"
#include "atl_hw.h"
@@ -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:
@@ -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)) {
@@ -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