Commit e7b5f97e authored by Igor Russkikh's avatar Igor Russkikh Committed by David S. Miller

net: atlantic: check rpc result and wait for rpc address

Artificial HW reliability tests revealed a possible hangup in
the driver. Normally, when device disappears from bus, all
register reads returns 0xFFFFFFFF.

At remote procedure invocation towards FW there is a logic
where result is compared with -1 in a loop.
That caused an infinite loop if hardware due to some issues
disappears from bus.

Add extra result checks to prevent this.
Signed-off-by: default avatarDmitry Bogdanov <dbogdanov@marvell.com>
Signed-off-by: default avatarIgor Russkikh <irusskikh@marvell.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 15beab0a
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#define HW_ATL_MIF_ADDR 0x0208U #define HW_ATL_MIF_ADDR 0x0208U
#define HW_ATL_MIF_VAL 0x020CU #define HW_ATL_MIF_VAL 0x020CU
#define HW_ATL_MPI_RPC_ADDR 0x0334U
#define HW_ATL_RPC_CONTROL_ADR 0x0338U #define HW_ATL_RPC_CONTROL_ADR 0x0338U
#define HW_ATL_RPC_STATE_ADR 0x033CU #define HW_ATL_RPC_STATE_ADR 0x033CU
...@@ -53,15 +54,14 @@ enum mcp_area { ...@@ -53,15 +54,14 @@ enum mcp_area {
}; };
static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual); 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, static int hw_atl_utils_mpi_set_state(struct aq_hw_s *self,
enum hal_atl_utils_fw_state_e state); enum hal_atl_utils_fw_state_e state);
static u32 hw_atl_utils_get_mpi_mbox_tid(struct aq_hw_s *self); static u32 hw_atl_utils_get_mpi_mbox_tid(struct aq_hw_s *self);
static u32 hw_atl_utils_mpi_get_state(struct aq_hw_s *self); static u32 hw_atl_utils_mpi_get_state(struct aq_hw_s *self);
static u32 hw_atl_utils_mif_cmd_get(struct aq_hw_s *self); static u32 hw_atl_utils_mif_cmd_get(struct aq_hw_s *self);
static u32 hw_atl_utils_mif_addr_get(struct aq_hw_s *self); static u32 hw_atl_utils_mif_addr_get(struct aq_hw_s *self);
static u32 hw_atl_utils_rpc_state_get(struct aq_hw_s *self); static u32 hw_atl_utils_rpc_state_get(struct aq_hw_s *self);
static u32 aq_fw1x_rpc_get(struct aq_hw_s *self);
int hw_atl_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops) int hw_atl_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops)
{ {
...@@ -476,6 +476,10 @@ static int hw_atl_utils_init_ucp(struct aq_hw_s *self, ...@@ -476,6 +476,10 @@ static int hw_atl_utils_init_ucp(struct aq_hw_s *self,
self, self->mbox_addr, self, self->mbox_addr,
self->mbox_addr != 0U, self->mbox_addr != 0U,
1000U, 10000U); 1000U, 10000U);
err = readx_poll_timeout_atomic(aq_fw1x_rpc_get, self,
self->rpc_addr,
self->rpc_addr != 0U,
1000U, 100000U);
return err; return err;
} }
...@@ -531,6 +535,12 @@ int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self, ...@@ -531,6 +535,12 @@ int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self,
self, fw.val, self, fw.val,
sw.tid == fw.tid, sw.tid == fw.tid,
1000U, 100000U); 1000U, 100000U);
if (err < 0)
goto err_exit;
err = aq_hw_err_from_flags(self);
if (err < 0)
goto err_exit;
if (fw.len == 0xFFFFU) { if (fw.len == 0xFFFFU) {
err = hw_atl_utils_fw_rpc_call(self, sw.len); err = hw_atl_utils_fw_rpc_call(self, sw.len);
...@@ -1025,6 +1035,11 @@ static u32 hw_atl_utils_rpc_state_get(struct aq_hw_s *self) ...@@ -1025,6 +1035,11 @@ static u32 hw_atl_utils_rpc_state_get(struct aq_hw_s *self)
return aq_hw_read_reg(self, HW_ATL_RPC_STATE_ADR); return aq_hw_read_reg(self, HW_ATL_RPC_STATE_ADR);
} }
static u32 aq_fw1x_rpc_get(struct aq_hw_s *self)
{
return aq_hw_read_reg(self, HW_ATL_MPI_RPC_ADDR);
}
const struct aq_fw_ops aq_fw_1x_ops = { const struct aq_fw_ops aq_fw_1x_ops = {
.init = hw_atl_utils_mpi_create, .init = hw_atl_utils_mpi_create,
.deinit = hw_atl_fw1x_deinit, .deinit = hw_atl_fw1x_deinit,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment