Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 171957
b: refs/heads/master
c: 55edc6e
h: refs/heads/master
i:
  171955: 8858e55
v: v3
  • Loading branch information
Ben Hutchings authored and David S. Miller committed Nov 26, 2009
1 parent 42b4975 commit 34cf004
Show file tree
Hide file tree
Showing 10 changed files with 140 additions and 89 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 1dfc5ceacd00365a9089e98643f4b26253d5a6aa
refs/heads/master: 55edc6e6ff728681ebc10d418222740705376664
48 changes: 13 additions & 35 deletions trunk/drivers/net/sfc/efx.c
Original file line number Diff line number Diff line change
Expand Up @@ -637,6 +637,7 @@ void __efx_reconfigure_port(struct efx_nic *efx)
netif_addr_unlock_bh(efx->net_dev);
}

falcon_stop_nic_stats(efx);
falcon_deconfigure_mac_wrapper(efx);

/* Reconfigure the PHY, disabling transmit in mac level loopback. */
Expand All @@ -651,6 +652,8 @@ void __efx_reconfigure_port(struct efx_nic *efx)

efx->mac_op->reconfigure(efx);

falcon_start_nic_stats(efx);

/* Inform kernel of loss/gain of carrier */
efx_link_status_changed(efx);
return;
Expand Down Expand Up @@ -749,7 +752,6 @@ static int efx_init_port(struct efx_nic *efx)
efx->mac_op->reconfigure(efx);

efx->port_initialized = true;
efx_stats_enable(efx);

mutex_unlock(&efx->mac_lock);
return 0;
Expand Down Expand Up @@ -802,7 +804,6 @@ static void efx_fini_port(struct efx_nic *efx)
if (!efx->port_initialized)
return;

efx_stats_disable(efx);
efx->phy_op->fini(efx);
efx->port_initialized = false;

Expand Down Expand Up @@ -1158,6 +1159,8 @@ static void efx_start_all(struct efx_nic *efx)
if (efx->state == STATE_RUNNING)
queue_delayed_work(efx->workqueue, &efx->monitor_work,
efx_monitor_interval);

falcon_start_nic_stats(efx);
}

/* Flush all delayed work. Should only be called when no more delayed work
Expand Down Expand Up @@ -1195,6 +1198,8 @@ static void efx_stop_all(struct efx_nic *efx)
if (!efx->port_enabled)
return;

falcon_stop_nic_stats(efx);

/* Disable interrupts and wait for ISR to complete */
falcon_disable_interrupts(efx);
if (efx->legacy_irq)
Expand Down Expand Up @@ -1438,38 +1443,16 @@ static int efx_net_stop(struct net_device *net_dev)
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. */
static struct net_device_stats *efx_net_stats(struct net_device *net_dev)
{
struct efx_nic *efx = netdev_priv(net_dev);
struct efx_mac_stats *mac_stats = &efx->mac_stats;
struct net_device_stats *stats = &net_dev->stats;

/* Update stats if possible, but do not wait if another thread
* is updating them or if MAC stats fetches are temporarily
* disabled; slightly stale stats are acceptable.
*/
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);
spin_lock_bh(&efx->stats_lock);
falcon_update_nic_stats(efx);
spin_unlock_bh(&efx->stats_lock);

stats->rx_packets = mac_stats->rx_packets;
stats->tx_packets = mac_stats->tx_packets;
Expand Down Expand Up @@ -1726,7 +1709,6 @@ void efx_reset_down(struct efx_nic *efx, enum reset_type method,
{
EFX_ASSERT_RESET_SERIALISED(efx);

efx_stats_disable(efx);
efx_stop_all(efx);
mutex_lock(&efx->mac_lock);
mutex_lock(&efx->spi_lock);
Expand Down Expand Up @@ -1776,10 +1758,8 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method,
mutex_unlock(&efx->spi_lock);
mutex_unlock(&efx->mac_lock);

if (ok) {
if (ok)
efx_start_all(efx);
efx_stats_enable(efx);
}
return rc;
}

Expand Down Expand Up @@ -1977,7 +1957,6 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
efx->rx_checksum_enabled = true;
spin_lock_init(&efx->netif_stop_lock);
spin_lock_init(&efx->stats_lock);
efx->stats_disable_count = 1;
mutex_init(&efx->mac_lock);
efx->mac_op = &efx_dummy_mac_operations;
efx->phy_op = &efx_dummy_phy_operations;
Expand Down Expand Up @@ -2219,9 +2198,8 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
goto fail4;
}

/* Switch to the running state before we expose the device to
* the OS. This is to ensure that the initial gathering of
* MAC stats succeeds. */
/* Switch to the running state before we expose the device to the OS,
* so that dev_open()|efx_start_all() will actually start the device */
efx->state = STATE_RUNNING;

rc = efx_register_netdev(efx);
Expand Down
2 changes: 0 additions & 2 deletions trunk/drivers/net/sfc/efx.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,6 @@ extern void efx_process_channel_now(struct efx_channel *channel);
#define EFX_EVQ_MASK (EFX_EVQ_SIZE - 1)

/* 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);

Expand Down
131 changes: 101 additions & 30 deletions trunk/drivers/net/sfc/falcon.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@
**************************************************************************
*/

static int disable_dma_stats;

/* This is set to 16 for a good reason. In summary, if larger than
* 16, the descriptor cache holds more than a default socket
* buffer's worth of packets (for UDP we can only have at most one
Expand Down Expand Up @@ -1890,7 +1888,7 @@ static int falcon_reset_macs(struct efx_nic *efx)

/* MAC stats will fail whilst the TX fifo is draining. Serialise
* 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_SET_OWORD_FIELD(reg, FRF_BB_TXFIFO_DRAIN_EN, 1);
Expand Down Expand Up @@ -1920,13 +1918,13 @@ static int falcon_reset_macs(struct efx_nic *efx)
udelay(10);
}

efx_stats_enable(efx);

/* 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 */
if (efx->link_state.up && EFX_IS10G(efx) && EFX_WORKAROUND_5147(efx))
falcon_reset_xaui(efx);

falcon_start_nic_stats(efx);

return 0;
}

Expand Down Expand Up @@ -2010,25 +2008,19 @@ void falcon_reconfigure_mac_wrapper(struct efx_nic *efx)
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;
u32 *dma_done;
int i;

if (disable_dma_stats)
return 0;
WARN_ON(nic_data->stats_pending);
WARN_ON(nic_data->stats_disable_count);

/* Statistics fetch will fail if the MAC is in TX drain */
if (falcon_rev(efx) >= FALCON_REV_B0) {
efx_oword_t temp;
efx_reado(efx, &temp, FR_AB_MAC_CTRL);
if (EFX_OWORD_FIELD(temp, FRF_BB_TXFIFO_DRAIN_EN))
return 0;
}
if (nic_data->stats_dma_done == NULL)
return; /* no mac selected */

dma_done = (efx->stats_buffer.addr + done_offset);
*dma_done = FALCON_STATS_NOT_DONE;
*nic_data->stats_dma_done = FALCON_STATS_NOT_DONE;
nic_data->stats_pending = true;
wmb(); /* ensure done flag is clear */

/* Initiate DMA transfer of stats */
Expand All @@ -2038,17 +2030,37 @@ int falcon_dma_stats(struct efx_nic *efx, unsigned int done_offset)
efx->stats_buffer.dma_addr);
efx_writeo(efx, &reg, FR_AB_MAC_STAT_DMA);

/* Wait for transfer to complete */
for (i = 0; i < 400; i++) {
if (*(volatile u32 *)dma_done == FALCON_STATS_DONE) {
rmb(); /* Ensure the stats are valid. */
return 0;
}
udelay(10);
mod_timer(&nic_data->stats_timer, round_jiffies_up(jiffies + HZ / 2));
}

static void falcon_stats_complete(struct efx_nic *efx)
{
struct falcon_nic_data *nic_data = efx->nic_data;

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");
return -ETIMEDOUT;
static void falcon_stats_timer_func(unsigned long context)
{
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);
}

/**************************************************************************
Expand Down Expand Up @@ -2206,10 +2218,12 @@ static void falcon_clock_mac(struct efx_nic *efx)
int falcon_switch_mac(struct efx_nic *efx)
{
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;

/* 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 */
if (efx->loopback_mode == LOOPBACK_GMAC) {
Expand All @@ -2224,6 +2238,12 @@ int falcon_switch_mac(struct efx_nic *efx)
efx->mac_op = (EFX_IS10G(efx) ?
&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)
goto out;

Expand All @@ -2235,7 +2255,7 @@ int falcon_switch_mac(struct efx_nic *efx)

rc = falcon_reset_macs(efx);
out:
efx_stats_enable(efx);
falcon_start_nic_stats(efx);
return rc;
}

Expand Down Expand Up @@ -2900,6 +2920,10 @@ int falcon_probe_nic(struct efx_nic *efx)
goto fail6;
}

nic_data->stats_disable_count = 1;
setup_timer(&nic_data->stats_timer, &falcon_stats_timer_func,
(unsigned long)efx);

return 0;

fail6:
Expand Down Expand Up @@ -3125,11 +3149,58 @@ void falcon_remove_nic(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;

if (nic_data->stats_disable_count)
return;

efx_reado(efx, &cnt, FR_AZ_RX_NODESC_DROP);
efx->n_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);
}

/**************************************************************************
Expand Down
Loading

0 comments on commit 34cf004

Please sign in to comment.