You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
352 lines
10 KiB
352 lines
10 KiB
From 3be54b42035cc3b59bf4dc5dbbc0b844308083d3 Mon Sep 17 00:00:00 2001
|
|
From: Igor Russkikh <irusskik@redhat.com>
|
|
Date: Fri, 6 Nov 2020 18:37:01 -0500
|
|
Subject: [PATCH 044/139] [netdrv] net: atlantic: add fw configuration memory
|
|
area
|
|
|
|
Message-id: <1604687916-15087-45-git-send-email-irusskik@redhat.com>
|
|
Patchwork-id: 338471
|
|
Patchwork-instance: patchwork
|
|
O-Subject: [RHEL8.4 BZ 1857861 044/139] net: atlantic: add fw configuration memory area
|
|
Bugzilla: 1857861
|
|
RH-Acked-by: David Arcari <darcari@redhat.com>
|
|
RH-Acked-by: John Linville <linville@redhat.com>
|
|
RH-Acked-by: Tony Camuso <tcamuso@redhat.com>
|
|
|
|
Bugzilla: http://bugzilla.redhat.com/1857861
|
|
|
|
commit dc12f75afcc677f225e5465b0654c54a14945168
|
|
Author: Nikita Danilov <ndanilov@marvell.com>
|
|
Date: Thu Nov 7 22:41:57 2019 +0000
|
|
|
|
net: atlantic: add fw configuration memory area
|
|
|
|
Device FW has a separate memory area where various
|
|
config fields are stored and could be used by the
|
|
driver.
|
|
|
|
Here we modify download/upload infrastructure to
|
|
allow accessing this area.
|
|
|
|
Lateron this will be used to configure various behaviours
|
|
|
|
Signed-off-by: Nikita Danilov <ndanilov@marvell.com>
|
|
Signed-off-by: Igor Russkikh <irusskikh@marvell.com>
|
|
Signed-off-by: David S. Miller <davem@davemloft.net>
|
|
|
|
Signed-off-by: Igor Russkikh <irusskik@redhat.com>
|
|
|
|
Cc: David Arcari <darcari@redhat.com>
|
|
Cc: Igor Russkikh <irusskik@redhat.com>
|
|
Signed-off-by: Jan Stancek <jstancek@redhat.com>
|
|
---
|
|
drivers/net/ethernet/aquantia/atlantic/aq_hw.h | 1 +
|
|
.../aquantia/atlantic/hw_atl/hw_atl_utils.c | 129 +++++++++++++++------
|
|
.../aquantia/atlantic/hw_atl/hw_atl_utils.h | 47 +++++++-
|
|
.../aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c | 19 ++-
|
|
4 files changed, 159 insertions(+), 37 deletions(-)
|
|
|
|
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h
|
|
index ce4b8db03882..b2203f43e00a 100644
|
|
--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h
|
|
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h
|
|
@@ -140,6 +140,7 @@ struct aq_hw_s {
|
|
atomic_t dpc;
|
|
u32 mbox_addr;
|
|
u32 rpc_addr;
|
|
+ u32 settings_addr;
|
|
u32 rpc_tid;
|
|
struct hw_atl_utils_fw_rpc rpc;
|
|
s64 ptp_clk_offset;
|
|
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c
|
|
index fc82ede18b20..db8c09c5a768 100644
|
|
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c
|
|
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c
|
|
@@ -47,6 +47,11 @@
|
|
|
|
#define FORCE_FLASHLESS 0
|
|
|
|
+enum mcp_area {
|
|
+ MCP_AREA_CONFIG = 0x80000000,
|
|
+ MCP_AREA_SETTINGS = 0x20000000,
|
|
+};
|
|
+
|
|
static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual);
|
|
|
|
static int hw_atl_utils_mpi_set_state(struct aq_hw_s *self,
|
|
@@ -327,10 +332,75 @@ int hw_atl_utils_fw_downld_dwords(struct aq_hw_s *self, u32 a,
|
|
return err;
|
|
}
|
|
|
|
-int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 a, u32 *p, u32 cnt)
|
|
+static int hw_atl_utils_write_b1_mbox(struct aq_hw_s *self, u32 addr,
|
|
+ u32 *p, u32 cnt, enum mcp_area area)
|
|
+{
|
|
+ u32 data_offset = 0;
|
|
+ u32 offset = addr;
|
|
+ int err = 0;
|
|
+ u32 val;
|
|
+
|
|
+ switch (area) {
|
|
+ case MCP_AREA_CONFIG:
|
|
+ offset -= self->rpc_addr;
|
|
+ break;
|
|
+
|
|
+ case MCP_AREA_SETTINGS:
|
|
+ offset -= self->settings_addr;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ offset = offset / sizeof(u32);
|
|
+
|
|
+ for (; data_offset < cnt; ++data_offset, ++offset) {
|
|
+ aq_hw_write_reg(self, 0x328, p[data_offset]);
|
|
+ aq_hw_write_reg(self, 0x32C,
|
|
+ (area | (0xFFFF & (offset * 4))));
|
|
+ hw_atl_mcp_up_force_intr_set(self, 1);
|
|
+ /* 1000 times by 10us = 10ms */
|
|
+ err = readx_poll_timeout_atomic(hw_atl_scrpad12_get,
|
|
+ self, val,
|
|
+ (val & 0xF0000000) !=
|
|
+ area,
|
|
+ 10U, 10000U);
|
|
+
|
|
+ if (err < 0)
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ return err;
|
|
+}
|
|
+
|
|
+static int hw_atl_utils_write_b0_mbox(struct aq_hw_s *self, u32 addr,
|
|
+ u32 *p, u32 cnt)
|
|
{
|
|
+ u32 offset = 0;
|
|
+ int err = 0;
|
|
u32 val;
|
|
+
|
|
+ aq_hw_write_reg(self, 0x208, addr);
|
|
+
|
|
+ for (; offset < cnt; ++offset) {
|
|
+ aq_hw_write_reg(self, 0x20C, p[offset]);
|
|
+ aq_hw_write_reg(self, 0x200, 0xC000);
|
|
+
|
|
+ err = readx_poll_timeout_atomic(hw_atl_utils_mif_cmd_get,
|
|
+ self, val,
|
|
+ (val & 0x100) == 0U,
|
|
+ 10U, 10000U);
|
|
+
|
|
+ if (err < 0)
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ return err;
|
|
+}
|
|
+
|
|
+static int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 addr, u32 *p,
|
|
+ u32 cnt, enum mcp_area area)
|
|
+{
|
|
int err = 0;
|
|
+ u32 val;
|
|
|
|
err = readx_poll_timeout_atomic(hw_atl_sem_ram_get, self,
|
|
val, val == 1U,
|
|
@@ -338,43 +408,35 @@ int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 a, u32 *p, u32 cnt)
|
|
if (err < 0)
|
|
goto err_exit;
|
|
|
|
- if (IS_CHIP_FEATURE(REVISION_B1)) {
|
|
- u32 offset = 0;
|
|
-
|
|
- for (; offset < cnt; ++offset) {
|
|
- aq_hw_write_reg(self, 0x328, p[offset]);
|
|
- aq_hw_write_reg(self, 0x32C,
|
|
- (0x80000000 | (0xFFFF & (offset * 4))));
|
|
- hw_atl_mcp_up_force_intr_set(self, 1);
|
|
- /* 1000 times by 10us = 10ms */
|
|
- err = readx_poll_timeout_atomic(hw_atl_scrpad12_get,
|
|
- self, val,
|
|
- (val & 0xF0000000) !=
|
|
- 0x80000000,
|
|
- 10U, 10000U);
|
|
- }
|
|
- } else {
|
|
- u32 offset = 0;
|
|
-
|
|
- aq_hw_write_reg(self, 0x208, a);
|
|
+ if (IS_CHIP_FEATURE(REVISION_B1))
|
|
+ err = hw_atl_utils_write_b1_mbox(self, addr, p, cnt, area);
|
|
+ else
|
|
+ err = hw_atl_utils_write_b0_mbox(self, addr, p, cnt);
|
|
|
|
- for (; offset < cnt; ++offset) {
|
|
- aq_hw_write_reg(self, 0x20C, p[offset]);
|
|
- aq_hw_write_reg(self, 0x200, 0xC000);
|
|
+ hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM);
|
|
|
|
- err = readx_poll_timeout_atomic(hw_atl_utils_mif_cmd_get,
|
|
- self, val,
|
|
- (val & 0x100) == 0,
|
|
- 1000U, 10000U);
|
|
- }
|
|
- }
|
|
+ if (err < 0)
|
|
+ goto err_exit;
|
|
|
|
- hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM);
|
|
+ err = aq_hw_err_from_flags(self);
|
|
|
|
err_exit:
|
|
return err;
|
|
}
|
|
|
|
+int hw_atl_write_fwcfg_dwords(struct aq_hw_s *self, u32 *p, u32 cnt)
|
|
+{
|
|
+ return hw_atl_utils_fw_upload_dwords(self, self->rpc_addr, p,
|
|
+ cnt, MCP_AREA_CONFIG);
|
|
+}
|
|
+
|
|
+int hw_atl_write_fwsettings_dwords(struct aq_hw_s *self, u32 offset, u32 *p,
|
|
+ u32 cnt)
|
|
+{
|
|
+ return hw_atl_utils_fw_upload_dwords(self, self->settings_addr + offset,
|
|
+ p, cnt, MCP_AREA_SETTINGS);
|
|
+}
|
|
+
|
|
static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual)
|
|
{
|
|
int err = 0;
|
|
@@ -437,10 +499,9 @@ int hw_atl_utils_fw_rpc_call(struct aq_hw_s *self, unsigned int rpc_size)
|
|
err = -1;
|
|
goto err_exit;
|
|
}
|
|
- err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr,
|
|
- (u32 *)(void *)&self->rpc,
|
|
- (rpc_size + sizeof(u32) -
|
|
- sizeof(u8)) / sizeof(u32));
|
|
+ err = hw_atl_write_fwcfg_dwords(self, (u32 *)(void *)&self->rpc,
|
|
+ (rpc_size + sizeof(u32) -
|
|
+ sizeof(u8)) / sizeof(u32));
|
|
if (err < 0)
|
|
goto err_exit;
|
|
|
|
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h
|
|
index c6708f0d5d3e..68fe17ec171d 100644
|
|
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h
|
|
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h
|
|
@@ -277,6 +277,48 @@ struct __packed hw_fw_request_iface {
|
|
};
|
|
};
|
|
|
|
+struct __packed hw_atl_utils_settings {
|
|
+ u32 mtu;
|
|
+ u32 downshift_retry_count;
|
|
+ u32 link_pause_frame_quanta_100m;
|
|
+ u32 link_pause_frame_threshold_100m;
|
|
+ u32 link_pause_frame_quanta_1g;
|
|
+ u32 link_pause_frame_threshold_1g;
|
|
+ u32 link_pause_frame_quanta_2p5g;
|
|
+ u32 link_pause_frame_threshold_2p5g;
|
|
+ u32 link_pause_frame_quanta_5g;
|
|
+ u32 link_pause_frame_threshold_5g;
|
|
+ u32 link_pause_frame_quanta_10g;
|
|
+ u32 link_pause_frame_threshold_10g;
|
|
+ u32 pfc_quanta_class_0;
|
|
+ u32 pfc_threshold_class_0;
|
|
+ u32 pfc_quanta_class_1;
|
|
+ u32 pfc_threshold_class_1;
|
|
+ u32 pfc_quanta_class_2;
|
|
+ u32 pfc_threshold_class_2;
|
|
+ u32 pfc_quanta_class_3;
|
|
+ u32 pfc_threshold_class_3;
|
|
+ u32 pfc_quanta_class_4;
|
|
+ u32 pfc_threshold_class_4;
|
|
+ u32 pfc_quanta_class_5;
|
|
+ u32 pfc_threshold_class_5;
|
|
+ u32 pfc_quanta_class_6;
|
|
+ u32 pfc_threshold_class_6;
|
|
+ u32 pfc_quanta_class_7;
|
|
+ u32 pfc_threshold_class_7;
|
|
+ u32 eee_link_down_timeout;
|
|
+ u32 eee_link_up_timeout;
|
|
+ u32 eee_max_link_drops;
|
|
+ u32 eee_rates_mask;
|
|
+ u32 wake_timer;
|
|
+ u32 thermal_shutdown_off_temp;
|
|
+ u32 thermal_shutdown_warning_temp;
|
|
+ u32 thermal_shutdown_cold_temp;
|
|
+ u32 msm_options;
|
|
+ u32 dac_cable_serdes_modes;
|
|
+ u32 media_detect;
|
|
+};
|
|
+
|
|
enum hw_atl_rx_action_with_traffic {
|
|
HW_ATL_RX_DISCARD,
|
|
HW_ATL_RX_HOST,
|
|
@@ -554,7 +596,10 @@ struct aq_stats_s *hw_atl_utils_get_hw_stats(struct aq_hw_s *self);
|
|
int hw_atl_utils_fw_downld_dwords(struct aq_hw_s *self, u32 a,
|
|
u32 *p, u32 cnt);
|
|
|
|
-int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 a, u32 *p, u32 cnt);
|
|
+int hw_atl_write_fwcfg_dwords(struct aq_hw_s *self, u32 *p, u32 cnt);
|
|
+
|
|
+int hw_atl_write_fwsettings_dwords(struct aq_hw_s *self, u32 offset, u32 *p,
|
|
+ u32 cnt);
|
|
|
|
int hw_atl_utils_fw_set_wol(struct aq_hw_s *self, bool wol_enabled, u8 *mac);
|
|
|
|
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c
|
|
index 4eab51b5b400..3dbce03c5a94 100644
|
|
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c
|
|
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c
|
|
@@ -78,6 +78,7 @@ static int aq_fw2x_set_state(struct aq_hw_s *self,
|
|
|
|
static u32 aq_fw2x_mbox_get(struct aq_hw_s *self);
|
|
static u32 aq_fw2x_rpc_get(struct aq_hw_s *self);
|
|
+static int aq_fw2x_settings_get(struct aq_hw_s *self, u32 *addr);
|
|
static u32 aq_fw2x_state2_get(struct aq_hw_s *self);
|
|
|
|
static int aq_fw2x_init(struct aq_hw_s *self)
|
|
@@ -95,6 +96,8 @@ static int aq_fw2x_init(struct aq_hw_s *self)
|
|
self->rpc_addr != 0U,
|
|
1000U, 100000U);
|
|
|
|
+ err = aq_fw2x_settings_get(self, &self->settings_addr);
|
|
+
|
|
return err;
|
|
}
|
|
|
|
@@ -418,8 +421,7 @@ static int aq_fw2x_send_fw_request(struct aq_hw_s *self,
|
|
dword_cnt = size / sizeof(u32);
|
|
if (size % sizeof(u32))
|
|
dword_cnt++;
|
|
- err = hw_atl_utils_fw_upload_dwords(self, aq_fw2x_rpc_get(self),
|
|
- (void *)fw_req, dword_cnt);
|
|
+ err = hw_atl_write_fwcfg_dwords(self, (void *)fw_req, dword_cnt);
|
|
if (err < 0)
|
|
goto err_exit;
|
|
|
|
@@ -547,6 +549,19 @@ static u32 aq_fw2x_rpc_get(struct aq_hw_s *self)
|
|
return aq_hw_read_reg(self, HW_ATL_FW2X_MPI_RPC_ADDR);
|
|
}
|
|
|
|
+static int aq_fw2x_settings_get(struct aq_hw_s *self, u32 *addr)
|
|
+{
|
|
+ int err = 0;
|
|
+ u32 offset;
|
|
+
|
|
+ offset = self->mbox_addr + offsetof(struct hw_atl_utils_mbox,
|
|
+ info.setting_address);
|
|
+
|
|
+ err = hw_atl_utils_fw_downld_dwords(self, offset, addr, 1);
|
|
+
|
|
+ return err;
|
|
+}
|
|
+
|
|
static u32 aq_fw2x_state2_get(struct aq_hw_s *self)
|
|
{
|
|
return aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR);
|
|
--
|
|
2.13.6
|
|
|