Commit 55edc6e6 authored by Ben Hutchings's avatar Ben Hutchings Committed by David S. Miller

sfc: Split MAC stats DMA initiation and completion

From: Steve Hodgson <shodgson@solarflare.com>

Currently we initiate MAC stats DMA and busy-wait for completion when
stats are requested.  We can improve on this with a periodic timer to
initiate and poll for stats, and opportunistically poll when stats are
requested.

Since efx_nic::stats_disable_count and efx_stats_{disable,enable}()
are Falcon-specific, rename them and move them accordingly.
Signed-off-by: default avatarBen Hutchings <bhutchings@solarflare.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 1dfc5cea
...@@ -637,6 +637,7 @@ void __efx_reconfigure_port(struct efx_nic *efx) ...@@ -637,6 +637,7 @@ void __efx_reconfigure_port(struct efx_nic *efx)
netif_addr_unlock_bh(efx->net_dev); netif_addr_unlock_bh(efx->net_dev);
} }
falcon_stop_nic_stats(efx);
falcon_deconfigure_mac_wrapper(efx); falcon_deconfigure_mac_wrapper(efx);
/* Reconfigure the PHY, disabling transmit in mac level loopback. */ /* Reconfigure the PHY, disabling transmit in mac level loopback. */
...@@ -651,6 +652,8 @@ void __efx_reconfigure_port(struct efx_nic *efx) ...@@ -651,6 +652,8 @@ void __efx_reconfigure_port(struct efx_nic *efx)
efx->mac_op->reconfigure(efx); efx->mac_op->reconfigure(efx);
falcon_start_nic_stats(efx);
/* Inform kernel of loss/gain of carrier */ /* Inform kernel of loss/gain of carrier */
efx_link_status_changed(efx); efx_link_status_changed(efx);
return; return;
...@@ -749,7 +752,6 @@ static int efx_init_port(struct efx_nic *efx) ...@@ -749,7 +752,6 @@ static int efx_init_port(struct efx_nic *efx)
efx->mac_op->reconfigure(efx); efx->mac_op->reconfigure(efx);
efx->port_initialized = true; efx->port_initialized = true;
efx_stats_enable(efx);
mutex_unlock(&efx->mac_lock); mutex_unlock(&efx->mac_lock);
return 0; return 0;
...@@ -802,7 +804,6 @@ static void efx_fini_port(struct efx_nic *efx) ...@@ -802,7 +804,6 @@ static void efx_fini_port(struct efx_nic *efx)
if (!efx->port_initialized) if (!efx->port_initialized)
return; return;
efx_stats_disable(efx);
efx->phy_op->fini(efx); efx->phy_op->fini(efx);
efx->port_initialized = false; efx->port_initialized = false;
...@@ -1158,6 +1159,8 @@ static void efx_start_all(struct efx_nic *efx) ...@@ -1158,6 +1159,8 @@ static void efx_start_all(struct efx_nic *efx)
if (efx->state == STATE_RUNNING) if (efx->state == STATE_RUNNING)
queue_delayed_work(efx->workqueue, &efx->monitor_work, queue_delayed_work(efx->workqueue, &efx->monitor_work,
efx_monitor_interval); efx_monitor_interval);
falcon_start_nic_stats(efx);
} }
/* Flush all delayed work. Should only be called when no more delayed work /* Flush all delayed work. Should only be called when no more delayed work
...@@ -1195,6 +1198,8 @@ static void efx_stop_all(struct efx_nic *efx) ...@@ -1195,6 +1198,8 @@ static void efx_stop_all(struct efx_nic *efx)
if (!efx->port_enabled) if (!efx->port_enabled)
return; return;
falcon_stop_nic_stats(efx);
/* Disable interrupts and wait for ISR to complete */ /* Disable interrupts and wait for ISR to complete */
falcon_disable_interrupts(efx); falcon_disable_interrupts(efx);
if (efx->legacy_irq) if (efx->legacy_irq)
...@@ -1438,20 +1443,6 @@ static int efx_net_stop(struct net_device *net_dev) ...@@ -1438,20 +1443,6 @@ static int efx_net_stop(struct net_device *net_dev)
return 0; return 0;
} }
void efx_stats_disable(struct efx_nic *efx)
{
spin_lock(&efx->stats_lock);
++efx->stats_disable_count;
spin_unlock(&efx->stats_lock);
}
void efx_stats_enable(struct efx_nic *efx)
{
spin_lock(&efx->stats_lock);
--efx->stats_disable_count;
spin_unlock(&efx->stats_lock);
}
/* Context: process, dev_base_lock or RTNL held, non-blocking. */ /* Context: process, dev_base_lock or RTNL held, non-blocking. */
static struct net_device_stats *efx_net_stats(struct net_device *net_dev) static struct net_device_stats *efx_net_stats(struct net_device *net_dev)
{ {
...@@ -1459,17 +1450,9 @@ static struct net_device_stats *efx_net_stats(struct net_device *net_dev) ...@@ -1459,17 +1450,9 @@ static struct net_device_stats *efx_net_stats(struct net_device *net_dev)
struct efx_mac_stats *mac_stats = &efx->mac_stats; struct efx_mac_stats *mac_stats = &efx->mac_stats;
struct net_device_stats *stats = &net_dev->stats; struct net_device_stats *stats = &net_dev->stats;
/* Update stats if possible, but do not wait if another thread spin_lock_bh(&efx->stats_lock);
* is updating them or if MAC stats fetches are temporarily falcon_update_nic_stats(efx);
* disabled; slightly stale stats are acceptable. spin_unlock_bh(&efx->stats_lock);
*/
if (!spin_trylock(&efx->stats_lock))
return stats;
if (!efx->stats_disable_count) {
efx->mac_op->update_stats(efx);
falcon_update_nic_stats(efx);
}
spin_unlock(&efx->stats_lock);
stats->rx_packets = mac_stats->rx_packets; stats->rx_packets = mac_stats->rx_packets;
stats->tx_packets = mac_stats->tx_packets; stats->tx_packets = mac_stats->tx_packets;
...@@ -1726,7 +1709,6 @@ void efx_reset_down(struct efx_nic *efx, enum reset_type method, ...@@ -1726,7 +1709,6 @@ void efx_reset_down(struct efx_nic *efx, enum reset_type method,
{ {
EFX_ASSERT_RESET_SERIALISED(efx); EFX_ASSERT_RESET_SERIALISED(efx);
efx_stats_disable(efx);
efx_stop_all(efx); efx_stop_all(efx);
mutex_lock(&efx->mac_lock); mutex_lock(&efx->mac_lock);
mutex_lock(&efx->spi_lock); mutex_lock(&efx->spi_lock);
...@@ -1776,10 +1758,8 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method, ...@@ -1776,10 +1758,8 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method,
mutex_unlock(&efx->spi_lock); mutex_unlock(&efx->spi_lock);
mutex_unlock(&efx->mac_lock); mutex_unlock(&efx->mac_lock);
if (ok) { if (ok)
efx_start_all(efx); efx_start_all(efx);
efx_stats_enable(efx);
}
return rc; return rc;
} }
...@@ -1977,7 +1957,6 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type, ...@@ -1977,7 +1957,6 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
efx->rx_checksum_enabled = true; efx->rx_checksum_enabled = true;
spin_lock_init(&efx->netif_stop_lock); spin_lock_init(&efx->netif_stop_lock);
spin_lock_init(&efx->stats_lock); spin_lock_init(&efx->stats_lock);
efx->stats_disable_count = 1;
mutex_init(&efx->mac_lock); mutex_init(&efx->mac_lock);
efx->mac_op = &efx_dummy_mac_operations; efx->mac_op = &efx_dummy_mac_operations;
efx->phy_op = &efx_dummy_phy_operations; efx->phy_op = &efx_dummy_phy_operations;
...@@ -2219,9 +2198,8 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev, ...@@ -2219,9 +2198,8 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
goto fail4; goto fail4;
} }
/* Switch to the running state before we expose the device to /* Switch to the running state before we expose the device to the OS,
* the OS. This is to ensure that the initial gathering of * so that dev_open()|efx_start_all() will actually start the device */
* MAC stats succeeds. */
efx->state = STATE_RUNNING; efx->state = STATE_RUNNING;
rc = efx_register_netdev(efx); rc = efx_register_netdev(efx);
......
...@@ -60,8 +60,6 @@ extern void efx_process_channel_now(struct efx_channel *channel); ...@@ -60,8 +60,6 @@ extern void efx_process_channel_now(struct efx_channel *channel);
#define EFX_EVQ_MASK (EFX_EVQ_SIZE - 1) #define EFX_EVQ_MASK (EFX_EVQ_SIZE - 1)
/* Ports */ /* Ports */
extern void efx_stats_disable(struct efx_nic *efx);
extern void efx_stats_enable(struct efx_nic *efx);
extern void efx_reconfigure_port(struct efx_nic *efx); extern void efx_reconfigure_port(struct efx_nic *efx);
extern void __efx_reconfigure_port(struct efx_nic *efx); extern void __efx_reconfigure_port(struct efx_nic *efx);
......
...@@ -36,8 +36,6 @@ ...@@ -36,8 +36,6 @@
************************************************************************** **************************************************************************
*/ */
static int disable_dma_stats;
/* This is set to 16 for a good reason. In summary, if larger than /* This is set to 16 for a good reason. In summary, if larger than
* 16, the descriptor cache holds more than a default socket * 16, the descriptor cache holds more than a default socket
* buffer's worth of packets (for UDP we can only have at most one * buffer's worth of packets (for UDP we can only have at most one
...@@ -1890,7 +1888,7 @@ static int falcon_reset_macs(struct efx_nic *efx) ...@@ -1890,7 +1888,7 @@ static int falcon_reset_macs(struct efx_nic *efx)
/* MAC stats will fail whilst the TX fifo is draining. Serialise /* MAC stats will fail whilst the TX fifo is draining. Serialise
* the drain sequence with the statistics fetch */ * the drain sequence with the statistics fetch */
efx_stats_disable(efx); falcon_stop_nic_stats(efx);
efx_reado(efx, &reg, FR_AB_MAC_CTRL); efx_reado(efx, &reg, FR_AB_MAC_CTRL);
EFX_SET_OWORD_FIELD(reg, FRF_BB_TXFIFO_DRAIN_EN, 1); EFX_SET_OWORD_FIELD(reg, FRF_BB_TXFIFO_DRAIN_EN, 1);
...@@ -1920,13 +1918,13 @@ static int falcon_reset_macs(struct efx_nic *efx) ...@@ -1920,13 +1918,13 @@ static int falcon_reset_macs(struct efx_nic *efx)
udelay(10); udelay(10);
} }
efx_stats_enable(efx);
/* If we've reset the EM block and the link is up, then /* If we've reset the EM block and the link is up, then
* we'll have to kick the XAUI link so the PHY can recover */ * we'll have to kick the XAUI link so the PHY can recover */
if (efx->link_state.up && EFX_IS10G(efx) && EFX_WORKAROUND_5147(efx)) if (efx->link_state.up && EFX_IS10G(efx) && EFX_WORKAROUND_5147(efx))
falcon_reset_xaui(efx); falcon_reset_xaui(efx);
falcon_start_nic_stats(efx);
return 0; return 0;
} }
...@@ -2010,25 +2008,19 @@ void falcon_reconfigure_mac_wrapper(struct efx_nic *efx) ...@@ -2010,25 +2008,19 @@ void falcon_reconfigure_mac_wrapper(struct efx_nic *efx)
efx_writeo(efx, &reg, FR_AZ_RX_CFG); efx_writeo(efx, &reg, FR_AZ_RX_CFG);
} }
int falcon_dma_stats(struct efx_nic *efx, unsigned int done_offset) static void falcon_stats_request(struct efx_nic *efx)
{ {
struct falcon_nic_data *nic_data = efx->nic_data;
efx_oword_t reg; efx_oword_t reg;
u32 *dma_done;
int i;
if (disable_dma_stats) WARN_ON(nic_data->stats_pending);
return 0; WARN_ON(nic_data->stats_disable_count);
/* Statistics fetch will fail if the MAC is in TX drain */ if (nic_data->stats_dma_done == NULL)
if (falcon_rev(efx) >= FALCON_REV_B0) { return; /* no mac selected */
efx_oword_t temp;
efx_reado(efx, &temp, FR_AB_MAC_CTRL);
if (EFX_OWORD_FIELD(temp, FRF_BB_TXFIFO_DRAIN_EN))
return 0;
}
dma_done = (efx->stats_buffer.addr + done_offset); *nic_data->stats_dma_done = FALCON_STATS_NOT_DONE;
*dma_done = FALCON_STATS_NOT_DONE; nic_data->stats_pending = true;
wmb(); /* ensure done flag is clear */ wmb(); /* ensure done flag is clear */
/* Initiate DMA transfer of stats */ /* Initiate DMA transfer of stats */
...@@ -2038,17 +2030,37 @@ int falcon_dma_stats(struct efx_nic *efx, unsigned int done_offset) ...@@ -2038,17 +2030,37 @@ int falcon_dma_stats(struct efx_nic *efx, unsigned int done_offset)
efx->stats_buffer.dma_addr); efx->stats_buffer.dma_addr);
efx_writeo(efx, &reg, FR_AB_MAC_STAT_DMA); efx_writeo(efx, &reg, FR_AB_MAC_STAT_DMA);
/* Wait for transfer to complete */ mod_timer(&nic_data->stats_timer, round_jiffies_up(jiffies + HZ / 2));
for (i = 0; i < 400; i++) { }
if (*(volatile u32 *)dma_done == FALCON_STATS_DONE) {
rmb(); /* Ensure the stats are valid. */ static void falcon_stats_complete(struct efx_nic *efx)
return 0; {
} struct falcon_nic_data *nic_data = efx->nic_data;
udelay(10);
if (!nic_data->stats_pending)
return;
nic_data->stats_pending = 0;
if (*nic_data->stats_dma_done == FALCON_STATS_DONE) {
rmb(); /* read the done flag before the stats */
efx->mac_op->update_stats(efx);
} else {
EFX_ERR(efx, "timed out waiting for statistics\n");
} }
}
EFX_ERR(efx, "timed out waiting for statistics\n"); static void falcon_stats_timer_func(unsigned long context)
return -ETIMEDOUT; {
struct efx_nic *efx = (struct efx_nic *)context;
struct falcon_nic_data *nic_data = efx->nic_data;
spin_lock(&efx->stats_lock);
falcon_stats_complete(efx);
if (nic_data->stats_disable_count == 0)
falcon_stats_request(efx);
spin_unlock(&efx->stats_lock);
} }
/************************************************************************** /**************************************************************************
...@@ -2206,10 +2218,12 @@ static void falcon_clock_mac(struct efx_nic *efx) ...@@ -2206,10 +2218,12 @@ static void falcon_clock_mac(struct efx_nic *efx)
int falcon_switch_mac(struct efx_nic *efx) int falcon_switch_mac(struct efx_nic *efx)
{ {
struct efx_mac_operations *old_mac_op = efx->mac_op; struct efx_mac_operations *old_mac_op = efx->mac_op;
struct falcon_nic_data *nic_data = efx->nic_data;
unsigned int stats_done_offset;
int rc = 0; int rc = 0;
/* Don't try to fetch MAC stats while we're switching MACs */ /* Don't try to fetch MAC stats while we're switching MACs */
efx_stats_disable(efx); falcon_stop_nic_stats(efx);
/* Internal loopbacks override the phy speed setting */ /* Internal loopbacks override the phy speed setting */
if (efx->loopback_mode == LOOPBACK_GMAC) { if (efx->loopback_mode == LOOPBACK_GMAC) {
...@@ -2224,6 +2238,12 @@ int falcon_switch_mac(struct efx_nic *efx) ...@@ -2224,6 +2238,12 @@ int falcon_switch_mac(struct efx_nic *efx)
efx->mac_op = (EFX_IS10G(efx) ? efx->mac_op = (EFX_IS10G(efx) ?
&falcon_xmac_operations : &falcon_gmac_operations); &falcon_xmac_operations : &falcon_gmac_operations);
if (EFX_IS10G(efx))
stats_done_offset = XgDmaDone_offset;
else
stats_done_offset = GDmaDone_offset;
nic_data->stats_dma_done = efx->stats_buffer.addr + stats_done_offset;
if (old_mac_op == efx->mac_op) if (old_mac_op == efx->mac_op)
goto out; goto out;
...@@ -2235,7 +2255,7 @@ int falcon_switch_mac(struct efx_nic *efx) ...@@ -2235,7 +2255,7 @@ int falcon_switch_mac(struct efx_nic *efx)
rc = falcon_reset_macs(efx); rc = falcon_reset_macs(efx);
out: out:
efx_stats_enable(efx); falcon_start_nic_stats(efx);
return rc; return rc;
} }
...@@ -2900,6 +2920,10 @@ int falcon_probe_nic(struct efx_nic *efx) ...@@ -2900,6 +2920,10 @@ int falcon_probe_nic(struct efx_nic *efx)
goto fail6; goto fail6;
} }
nic_data->stats_disable_count = 1;
setup_timer(&nic_data->stats_timer, &falcon_stats_timer_func,
(unsigned long)efx);
return 0; return 0;
fail6: fail6:
...@@ -3125,11 +3149,58 @@ void falcon_remove_nic(struct efx_nic *efx) ...@@ -3125,11 +3149,58 @@ void falcon_remove_nic(struct efx_nic *efx)
void falcon_update_nic_stats(struct efx_nic *efx) void falcon_update_nic_stats(struct efx_nic *efx)
{ {
struct falcon_nic_data *nic_data = efx->nic_data;
efx_oword_t cnt; efx_oword_t cnt;
if (nic_data->stats_disable_count)
return;
efx_reado(efx, &cnt, FR_AZ_RX_NODESC_DROP); efx_reado(efx, &cnt, FR_AZ_RX_NODESC_DROP);
efx->n_rx_nodesc_drop_cnt += efx->n_rx_nodesc_drop_cnt +=
EFX_OWORD_FIELD(cnt, FRF_AB_RX_NODESC_DROP_CNT); EFX_OWORD_FIELD(cnt, FRF_AB_RX_NODESC_DROP_CNT);
if (nic_data->stats_pending &&
*nic_data->stats_dma_done == FALCON_STATS_DONE) {
nic_data->stats_pending = false;
rmb(); /* read the done flag before the stats */
efx->mac_op->update_stats(efx);
}
}
void falcon_start_nic_stats(struct efx_nic *efx)
{
struct falcon_nic_data *nic_data = efx->nic_data;
spin_lock_bh(&efx->stats_lock);
if (--nic_data->stats_disable_count == 0)
falcon_stats_request(efx);
spin_unlock_bh(&efx->stats_lock);
}
void falcon_stop_nic_stats(struct efx_nic *efx)
{
struct falcon_nic_data *nic_data = efx->nic_data;
int i;
might_sleep();
spin_lock_bh(&efx->stats_lock);
++nic_data->stats_disable_count;
spin_unlock_bh(&efx->stats_lock);
del_timer_sync(&nic_data->stats_timer);
/* Wait enough time for the most recent transfer to
* complete. */
for (i = 0; i < 4 && nic_data->stats_pending; i++) {
if (*nic_data->stats_dma_done == FALCON_STATS_DONE)
break;
msleep(1);
}
spin_lock_bh(&efx->stats_lock);
falcon_stats_complete(efx);
spin_unlock_bh(&efx->stats_lock);
} }
/************************************************************************** /**************************************************************************
......
...@@ -75,10 +75,18 @@ struct falcon_board { ...@@ -75,10 +75,18 @@ struct falcon_board {
* struct falcon_nic_data - Falcon NIC state * struct falcon_nic_data - Falcon NIC state
* @pci_dev2: Secondary function of Falcon A * @pci_dev2: Secondary function of Falcon A
* @board: Board state and functions * @board: Board state and functions
* @stats_disable_count: Nest count for disabling statistics fetches
* @stats_pending: Is there a pending DMA of MAC statistics.
* @stats_timer: A timer for regularly fetching MAC statistics.
* @stats_dma_done: Pointer to the flag which indicates DMA completion.
*/ */
struct falcon_nic_data { struct falcon_nic_data {
struct pci_dev *pci_dev2; struct pci_dev *pci_dev2;
struct falcon_board board; struct falcon_board board;
unsigned int stats_disable_count;
bool stats_pending;
struct timer_list stats_timer;
u32 *stats_dma_done;
}; };
static inline struct falcon_board *falcon_board(struct efx_nic *efx) static inline struct falcon_board *falcon_board(struct efx_nic *efx)
...@@ -128,8 +136,6 @@ extern void falcon_remove_port(struct efx_nic *efx); ...@@ -128,8 +136,6 @@ extern void falcon_remove_port(struct efx_nic *efx);
/* MAC/PHY */ /* MAC/PHY */
extern int falcon_switch_mac(struct efx_nic *efx); extern int falcon_switch_mac(struct efx_nic *efx);
extern bool falcon_xaui_link_ok(struct efx_nic *efx); extern bool falcon_xaui_link_ok(struct efx_nic *efx);
extern int falcon_dma_stats(struct efx_nic *efx,
unsigned int done_offset);
extern void falcon_drain_tx_fifo(struct efx_nic *efx); extern void falcon_drain_tx_fifo(struct efx_nic *efx);
extern void falcon_deconfigure_mac_wrapper(struct efx_nic *efx); extern void falcon_deconfigure_mac_wrapper(struct efx_nic *efx);
extern void falcon_reconfigure_mac_wrapper(struct efx_nic *efx); extern void falcon_reconfigure_mac_wrapper(struct efx_nic *efx);
...@@ -154,6 +160,8 @@ extern int falcon_flush_queues(struct efx_nic *efx); ...@@ -154,6 +160,8 @@ extern int falcon_flush_queues(struct efx_nic *efx);
extern int falcon_reset_hw(struct efx_nic *efx, enum reset_type method); extern int falcon_reset_hw(struct efx_nic *efx, enum reset_type method);
extern void falcon_remove_nic(struct efx_nic *efx); extern void falcon_remove_nic(struct efx_nic *efx);
extern void falcon_update_nic_stats(struct efx_nic *efx); extern void falcon_update_nic_stats(struct efx_nic *efx);
extern void falcon_start_nic_stats(struct efx_nic *efx);
extern void falcon_stop_nic_stats(struct efx_nic *efx);
extern void falcon_set_multicast_hash(struct efx_nic *efx); extern void falcon_set_multicast_hash(struct efx_nic *efx);
extern int falcon_reset_xaui(struct efx_nic *efx); extern int falcon_reset_xaui(struct efx_nic *efx);
......
...@@ -347,14 +347,14 @@ static ssize_t set_phy_flash_cfg(struct device *dev, ...@@ -347,14 +347,14 @@ static ssize_t set_phy_flash_cfg(struct device *dev,
* MAC stats accordingly. */ * MAC stats accordingly. */
efx->phy_mode = new_mode; efx->phy_mode = new_mode;
if (new_mode & PHY_MODE_SPECIAL) if (new_mode & PHY_MODE_SPECIAL)
efx_stats_disable(efx); falcon_stop_nic_stats(efx);
if (falcon_board(efx)->type->id == FALCON_BOARD_SFE4001) if (falcon_board(efx)->type->id == FALCON_BOARD_SFE4001)
err = sfe4001_poweron(efx); err = sfe4001_poweron(efx);
else else
err = sfn4111t_reset(efx); err = sfn4111t_reset(efx);
efx_reconfigure_port(efx); efx_reconfigure_port(efx);
if (!(new_mode & PHY_MODE_SPECIAL)) if (!(new_mode & PHY_MODE_SPECIAL))
efx_stats_enable(efx); falcon_start_nic_stats(efx);
} }
rtnl_unlock(); rtnl_unlock();
...@@ -441,7 +441,7 @@ static int sfe4001_init(struct efx_nic *efx) ...@@ -441,7 +441,7 @@ static int sfe4001_init(struct efx_nic *efx)
if (efx->phy_mode & PHY_MODE_SPECIAL) { if (efx->phy_mode & PHY_MODE_SPECIAL) {
/* PHY won't generate a 156.25 MHz clock and MAC stats fetch /* PHY won't generate a 156.25 MHz clock and MAC stats fetch
* will fail. */ * will fail. */
efx_stats_disable(efx); falcon_stop_nic_stats(efx);
} }
rc = sfe4001_poweron(efx); rc = sfe4001_poweron(efx);
if (rc) if (rc)
...@@ -504,7 +504,7 @@ static void sfn4111t_init_phy(struct efx_nic *efx) ...@@ -504,7 +504,7 @@ static void sfn4111t_init_phy(struct efx_nic *efx)
return; return;
efx->phy_mode = PHY_MODE_SPECIAL; efx->phy_mode = PHY_MODE_SPECIAL;
efx_stats_disable(efx); falcon_stop_nic_stats(efx);
} }
sfn4111t_reset(efx); sfn4111t_reset(efx);
...@@ -531,7 +531,7 @@ static int sfn4111t_init(struct efx_nic *efx) ...@@ -531,7 +531,7 @@ static int sfn4111t_init(struct efx_nic *efx)
if (efx->phy_mode & PHY_MODE_SPECIAL) if (efx->phy_mode & PHY_MODE_SPECIAL)
/* PHY may not generate a 156.25 MHz clock and MAC /* PHY may not generate a 156.25 MHz clock and MAC
* stats fetch will fail. */ * stats fetch will fail. */
efx_stats_disable(efx); falcon_stop_nic_stats(efx);
return 0; return 0;
......
...@@ -130,11 +130,6 @@ static void falcon_update_stats_gmac(struct efx_nic *efx) ...@@ -130,11 +130,6 @@ static void falcon_update_stats_gmac(struct efx_nic *efx)
struct efx_mac_stats *mac_stats = &efx->mac_stats; struct efx_mac_stats *mac_stats = &efx->mac_stats;
unsigned long old_rx_pause, old_tx_pause; unsigned long old_rx_pause, old_tx_pause;
unsigned long new_rx_pause, new_tx_pause; unsigned long new_rx_pause, new_tx_pause;
int rc;
rc = falcon_dma_stats(efx, GDmaDone_offset);
if (rc)
return;
/* Pause frames are erroneously counted as errors (SFC bug 3269) */ /* Pause frames are erroneously counted as errors (SFC bug 3269) */
old_rx_pause = mac_stats->rx_pause; old_rx_pause = mac_stats->rx_pause;
......
...@@ -60,9 +60,13 @@ static void falcon_setup_xaui(struct efx_nic *efx) ...@@ -60,9 +60,13 @@ static void falcon_setup_xaui(struct efx_nic *efx)
int falcon_reset_xaui(struct efx_nic *efx) int falcon_reset_xaui(struct efx_nic *efx)
{ {
struct falcon_nic_data *nic_data = efx->nic_data;
efx_oword_t reg; efx_oword_t reg;
int count; int count;
/* Don't fetch MAC statistics over an XMAC reset */
WARN_ON(nic_data->stats_disable_count == 0);
/* Start reset sequence */ /* Start reset sequence */
EFX_POPULATE_OWORD_1(reg, FRF_AB_XX_RST_XX_EN, 1); EFX_POPULATE_OWORD_1(reg, FRF_AB_XX_RST_XX_EN, 1);
efx_writeo(efx, &reg, FR_AB_XX_PWR_RST); efx_writeo(efx, &reg, FR_AB_XX_PWR_RST);
...@@ -250,6 +254,8 @@ static void falcon_check_xaui_link_up(struct efx_nic *efx, int tries) ...@@ -250,6 +254,8 @@ static void falcon_check_xaui_link_up(struct efx_nic *efx, int tries)
/* XAUI link is expected to be down */ /* XAUI link is expected to be down */
return; return;
falcon_stop_nic_stats(efx);
while (!efx->mac_up && tries) { while (!efx->mac_up && tries) {
EFX_LOG(efx, "bashing xaui\n"); EFX_LOG(efx, "bashing xaui\n");
falcon_reset_xaui(efx); falcon_reset_xaui(efx);
...@@ -258,6 +264,8 @@ static void falcon_check_xaui_link_up(struct efx_nic *efx, int tries) ...@@ -258,6 +264,8 @@ static void falcon_check_xaui_link_up(struct efx_nic *efx, int tries)
efx->mac_up = falcon_xaui_link_ok(efx); efx->mac_up = falcon_xaui_link_ok(efx);
--tries; --tries;
} }
falcon_start_nic_stats(efx);
} }
static void falcon_reconfigure_xmac(struct efx_nic *efx) static void falcon_reconfigure_xmac(struct efx_nic *efx)
...@@ -276,11 +284,6 @@ static void falcon_reconfigure_xmac(struct efx_nic *efx) ...@@ -276,11 +284,6 @@ static void falcon_reconfigure_xmac(struct efx_nic *efx)
static void falcon_update_stats_xmac(struct efx_nic *efx) static void falcon_update_stats_xmac(struct efx_nic *efx)
{ {
struct efx_mac_stats *mac_stats = &efx->mac_stats; struct efx_mac_stats *mac_stats = &efx->mac_stats;
int rc;
rc = falcon_dma_stats(efx, XgDmaDone_offset);
if (rc)
return;
/* Update MAC stats from DMAed values */ /* Update MAC stats from DMAed values */
FALCON_STAT(efx, XgRxOctets, rx_bytes); FALCON_STAT(efx, XgRxOctets, rx_bytes);
......
...@@ -717,7 +717,6 @@ union efx_multicast_hash { ...@@ -717,7 +717,6 @@ union efx_multicast_hash {
* &struct net_device_stats. * &struct net_device_stats.
* @stats_buffer: DMA buffer for statistics * @stats_buffer: DMA buffer for statistics
* @stats_lock: Statistics update lock. Serialises statistics fetches * @stats_lock: Statistics update lock. Serialises statistics fetches
* @stats_disable_count: Nest count for disabling statistics fetches
* @mac_op: MAC interface * @mac_op: MAC interface
* @mac_address: Permanent MAC address * @mac_address: Permanent MAC address
* @phy_type: PHY type * @phy_type: PHY type
...@@ -799,7 +798,6 @@ struct efx_nic { ...@@ -799,7 +798,6 @@ struct efx_nic {
struct efx_mac_stats mac_stats; struct efx_mac_stats mac_stats;
struct efx_buffer stats_buffer; struct efx_buffer stats_buffer;
spinlock_t stats_lock; spinlock_t stats_lock;
unsigned int stats_disable_count;
struct efx_mac_operations *mac_op; struct efx_mac_operations *mac_op;
unsigned char mac_address[ETH_ALEN]; unsigned char mac_address[ETH_ALEN];
......
...@@ -374,7 +374,7 @@ static int tenxpress_special_reset(struct efx_nic *efx) ...@@ -374,7 +374,7 @@ static int tenxpress_special_reset(struct efx_nic *efx)
/* The XGMAC clock is driven from the SFC7101/SFT9001 312MHz clock, so /* The XGMAC clock is driven from the SFC7101/SFT9001 312MHz clock, so
* a special software reset can glitch the XGMAC sufficiently for stats * a special software reset can glitch the XGMAC sufficiently for stats
* requests to fail. */ * requests to fail. */
efx_stats_disable(efx); falcon_stop_nic_stats(efx);
/* Initiate reset */ /* Initiate reset */
reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG); reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG);
...@@ -396,7 +396,7 @@ static int tenxpress_special_reset(struct efx_nic *efx) ...@@ -396,7 +396,7 @@ static int tenxpress_special_reset(struct efx_nic *efx)
/* Wait for the XGXS state machine to churn */ /* Wait for the XGXS state machine to churn */
mdelay(10); mdelay(10);
out: out:
efx_stats_enable(efx); falcon_start_nic_stats(efx);
return rc; return rc;
} }
......
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