From bbec969b7f57a6ab5683145b99da869f99080e2a Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 11 Sep 2012 18:25:13 +0100 Subject: sfc: Fix check for failure of MC_CMD_FLUSH_RX_QUEUES efx_mcdi_rpc_start() returns a negative value on error or zero on success. However one caller that can't properly handle failure then does WARN_ON(rc > 0). Change it to WARN_ON(rc < 0). Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/mcdi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/ethernet/sfc/mcdi.c') diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c index aea43cbd0520..e1967fbad161 100644 --- a/drivers/net/ethernet/sfc/mcdi.c +++ b/drivers/net/ethernet/sfc/mcdi.c @@ -1216,7 +1216,7 @@ int efx_mcdi_flush_rxqs(struct efx_nic *efx) rc = efx_mcdi_rpc(efx, MC_CMD_FLUSH_RX_QUEUES, (u8 *)qid, count * sizeof(*qid), NULL, 0, NULL); - WARN_ON(rc > 0); + WARN_ON(rc < 0); kfree(qid); -- cgit v1.2.3 From 876be083b669c43203c0ee8709d749896e1d8d60 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 1 Oct 2012 20:58:35 +0100 Subject: sfc: Reset driver's MAC stats after MC reboot seen If the MC reboots then the stats it reports to us will have been reset. We need to reset ours to get efx_update_diff_stat() working properly. (Ideally we would maintain stats across the reboot, but as this should only happen immediately after a firmware upgrade it's not really worth the trouble.) Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/mcdi.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/net/ethernet/sfc/mcdi.c') diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c index e1967fbad161..3ef71a0f99a8 100644 --- a/drivers/net/ethernet/sfc/mcdi.c +++ b/drivers/net/ethernet/sfc/mcdi.c @@ -207,7 +207,9 @@ out: return 0; } -/* Test and clear MC-rebooted flag for this port/function */ +/* Test and clear MC-rebooted flag for this port/function; reset + * software state as necessary. + */ int efx_mcdi_poll_reboot(struct efx_nic *efx) { unsigned int addr = FR_CZ_MC_TREG_SMEM + MCDI_STATUS(efx); @@ -223,6 +225,11 @@ int efx_mcdi_poll_reboot(struct efx_nic *efx) if (value == 0) return 0; + /* MAC statistics have been cleared on the NIC; clear our copy + * so that efx_update_diff_stat() can continue to work. + */ + memset(&efx->mac_stats, 0, sizeof(efx->mac_stats)); + EFX_ZERO_DWORD(reg); efx_writed(efx, ®, addr); -- cgit v1.2.3 From ebf98e797b4e26ad52ace1511a0b503ee60a6cd4 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sat, 1 Dec 2012 02:21:17 +0000 Subject: sfc: Fix timekeeping in efx_mcdi_poll() efx_mcdi_poll() uses get_seconds() to read the current time and to implement a polling timeout. The use of this function was chosen partly because it could easily be replaced in a co-sim environment with a macro that read the simulated time. Unfortunately the real get_seconds() returns the system time (real time) which is subject to adjustment by e.g. ntpd. If the system time is adjusted forward during a polled MCDI operation, the effective timeout can be shorter than the intended 10 seconds, resulting in a spurious failure. It is also possible for a backward adjustment to delay detection of a areal failure. Use jiffies instead, and change MCDI_RPC_TIMEOUT to be denominated in jiffies. Also correct rounding of the timeout: check time > finish (or rather time_after(time, finish)) and not time >= finish. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/mcdi.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/net/ethernet/sfc/mcdi.c') diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c index 3ef71a0f99a8..0095ce95150b 100644 --- a/drivers/net/ethernet/sfc/mcdi.c +++ b/drivers/net/ethernet/sfc/mcdi.c @@ -22,7 +22,7 @@ ************************************************************************** */ -#define MCDI_RPC_TIMEOUT 10 /*seconds */ +#define MCDI_RPC_TIMEOUT (10 * HZ) #define MCDI_PDU(efx) \ (efx_port_num(efx) ? MC_SMEM_P1_PDU_OFST : MC_SMEM_P0_PDU_OFST) @@ -120,7 +120,7 @@ static void efx_mcdi_copyout(struct efx_nic *efx, u8 *outbuf, size_t outlen) static int efx_mcdi_poll(struct efx_nic *efx) { struct efx_mcdi_iface *mcdi = efx_mcdi(efx); - unsigned int time, finish; + unsigned long time, finish; unsigned int respseq, respcmd, error; unsigned int pdu = FR_CZ_MC_TREG_SMEM + MCDI_PDU(efx); unsigned int rc, spins; @@ -136,7 +136,7 @@ static int efx_mcdi_poll(struct efx_nic *efx) * and poll once a jiffy (approximately) */ spins = TICK_USEC; - finish = get_seconds() + MCDI_RPC_TIMEOUT; + finish = jiffies + MCDI_RPC_TIMEOUT; while (1) { if (spins != 0) { @@ -146,7 +146,7 @@ static int efx_mcdi_poll(struct efx_nic *efx) schedule_timeout_uninterruptible(1); } - time = get_seconds(); + time = jiffies; rmb(); efx_readd(efx, ®, pdu); @@ -158,7 +158,7 @@ static int efx_mcdi_poll(struct efx_nic *efx) EFX_DWORD_FIELD(reg, MCDI_HEADER_RESPONSE)) break; - if (time >= finish) + if (time_after(time, finish)) return -ETIMEDOUT; } @@ -257,7 +257,7 @@ static int efx_mcdi_await_completion(struct efx_nic *efx) if (wait_event_timeout( mcdi->wq, atomic_read(&mcdi->state) == MCDI_STATE_COMPLETED, - msecs_to_jiffies(MCDI_RPC_TIMEOUT * 1000)) == 0) + MCDI_RPC_TIMEOUT) == 0) return -ETIMEDOUT; /* Check if efx_mcdi_set_mode() switched us back to polled completions. -- cgit v1.2.3