Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 171964
b: refs/heads/master
c: fdaa9ae
h: refs/heads/master
v: v3
  • Loading branch information
Steve Hodgson authored and David S. Miller committed Nov 29, 2009
1 parent d3147f7 commit 37d945c
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 125 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: 5e7565930524410f097f5b04f8aba663089a6ffc
refs/heads/master: fdaa9aed21c8c8b529f3c94a5ffa138bf3360b75
35 changes: 8 additions & 27 deletions trunk/drivers/net/sfc/efx.c
Original file line number Diff line number Diff line change
Expand Up @@ -583,7 +583,7 @@ void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue, int delay)
* netif_carrier_on/off) of the link status, and also maintains the
* link status's stop on the port's TX queue.
*/
static void efx_link_status_changed(struct efx_nic *efx)
void efx_link_status_changed(struct efx_nic *efx)
{
struct efx_link_state *link_state = &efx->link_state;

Expand Down Expand Up @@ -675,19 +675,6 @@ void efx_reconfigure_port(struct efx_nic *efx)
mutex_unlock(&efx->mac_lock);
}

/* Asynchronous efx_reconfigure_port work item. To speed up efx_flush_all()
* we don't efx_reconfigure_port() if the port is disabled. Care is taken
* in efx_stop_all() and efx_start_port() to prevent PHY events being lost */
static void efx_phy_work(struct work_struct *data)
{
struct efx_nic *efx = container_of(data, struct efx_nic, phy_work);

mutex_lock(&efx->mac_lock);
if (efx->port_enabled)
__efx_reconfigure_port(efx);
mutex_unlock(&efx->mac_lock);
}

/* Asynchronous work item for changing MAC promiscuity and multicast
* hash. Avoid a drain/rx_ingress enable by reconfiguring the current
* MAC directly. */
Expand Down Expand Up @@ -768,9 +755,6 @@ static int efx_init_port(struct efx_nic *efx)
return rc;
}

/* Allow efx_reconfigure_port() to be scheduled, and close the window
* between efx_stop_port and efx_flush_all whereby a previously scheduled
* efx_phy_work()/efx_mac_work() may have been cancelled */
static void efx_start_port(struct efx_nic *efx)
{
EFX_LOG(efx, "start port\n");
Expand All @@ -787,10 +771,7 @@ static void efx_start_port(struct efx_nic *efx)
mutex_unlock(&efx->mac_lock);
}

/* Prevent efx_phy_work, efx_mac_work, and efx_monitor() from executing,
* and efx_set_multicast_list() from scheduling efx_phy_work. efx_phy_work
* and efx_mac_work may still be scheduled via NAPI processing until
* efx_flush_all() is called */
/* Prevent efx_mac_work() and efx_monitor() from working */
static void efx_stop_port(struct efx_nic *efx)
{
EFX_LOG(efx, "stop port\n");
Expand Down Expand Up @@ -1188,8 +1169,6 @@ static void efx_flush_all(struct efx_nic *efx)

/* Stop scheduled port reconfigurations */
cancel_work_sync(&efx->mac_work);
cancel_work_sync(&efx->phy_work);

}

/* Quiesce hardware and software without bringing the link down.
Expand Down Expand Up @@ -1227,7 +1206,7 @@ static void efx_stop_all(struct efx_nic *efx)
* window to loose phy events */
efx_stop_port(efx);

/* Flush efx_phy_work, efx_mac_work, refill_workqueue, monitor_work */
/* Flush efx_mac_work(), refill_workqueue, monitor_work */
efx_flush_all(efx);

/* Isolate the MAC from the TX and RX engines, so that queue
Expand Down Expand Up @@ -1907,6 +1886,10 @@ void efx_port_dummy_op_void(struct efx_nic *efx) {}
void efx_port_dummy_op_set_id_led(struct efx_nic *efx, enum efx_led_mode mode)
{
}
bool efx_port_dummy_op_poll(struct efx_nic *efx)
{
return false;
}

static struct efx_mac_operations efx_dummy_mac_operations = {
.reconfigure = efx_port_dummy_op_void,
Expand All @@ -1915,9 +1898,8 @@ static struct efx_mac_operations efx_dummy_mac_operations = {
static struct efx_phy_operations efx_dummy_phy_operations = {
.init = efx_port_dummy_op_int,
.reconfigure = efx_port_dummy_op_void,
.poll = efx_port_dummy_op_void,
.poll = efx_port_dummy_op_poll,
.fini = efx_port_dummy_op_void,
.clear_interrupt = efx_port_dummy_op_void,
};

/**************************************************************************
Expand Down Expand Up @@ -1957,7 +1939,6 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
efx->mac_op = &efx_dummy_mac_operations;
efx->phy_op = &efx_dummy_phy_operations;
efx->mdio.dev = net_dev;
INIT_WORK(&efx->phy_work, efx_phy_work);
INIT_WORK(&efx->mac_work, efx_mac_work);
atomic_set(&efx->netif_stop_count, 1);

Expand Down
3 changes: 3 additions & 0 deletions trunk/drivers/net/sfc/efx.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ extern int efx_port_dummy_op_int(struct efx_nic *efx);
extern void efx_port_dummy_op_void(struct efx_nic *efx);
extern void
efx_port_dummy_op_set_id_led(struct efx_nic *efx, enum efx_led_mode mode);
extern bool efx_port_dummy_op_poll(struct efx_nic *efx);

/* MTD */
#ifdef CONFIG_SFC_MTD
Expand All @@ -113,4 +114,6 @@ static inline void efx_schedule_channel(struct efx_channel *channel)
napi_schedule(&channel->napi_str);
}

extern void efx_link_status_changed(struct efx_nic *efx);

#endif /* EFX_EFX_H */
69 changes: 42 additions & 27 deletions trunk/drivers/net/sfc/falcon.c
Original file line number Diff line number Diff line change
Expand Up @@ -893,8 +893,7 @@ static void falcon_handle_global_event(struct efx_channel *channel,
if (EFX_QWORD_FIELD(*event, FSF_AB_GLB_EV_G_PHY0_INTR) ||
EFX_QWORD_FIELD(*event, FSF_AB_GLB_EV_XG_PHY0_INTR) ||
EFX_QWORD_FIELD(*event, FSF_AB_GLB_EV_XFP_PHY0_INTR)) {
efx->phy_op->clear_interrupt(efx);
queue_work(efx->workqueue, &efx->phy_work);
/* Ignored */
handled = true;
}

Expand Down Expand Up @@ -1140,20 +1139,6 @@ void falcon_generate_test_event(struct efx_channel *channel, unsigned int magic)
falcon_generate_event(channel, &test_event);
}

void falcon_sim_phy_event(struct efx_nic *efx)
{
efx_qword_t phy_event;

EFX_POPULATE_QWORD_1(phy_event, FSF_AZ_EV_CODE,
FSE_AZ_EV_CODE_GLOBAL_EV);
if (EFX_IS10G(efx))
EFX_SET_QWORD_FIELD(phy_event, FSF_AB_GLB_EV_XG_PHY0_INTR, 1);
else
EFX_SET_QWORD_FIELD(phy_event, FSF_AB_GLB_EV_G_PHY0_INTR, 1);

falcon_generate_event(&efx->channel[0], &phy_event);
}

/**************************************************************************
*
* Flush handling
Expand Down Expand Up @@ -2063,6 +2048,25 @@ static void falcon_stats_timer_func(unsigned long context)
spin_unlock(&efx->stats_lock);
}

static bool falcon_loopback_link_poll(struct efx_nic *efx)
{
struct efx_link_state old_state = efx->link_state;

WARN_ON(!mutex_is_locked(&efx->mac_lock));
WARN_ON(!LOOPBACK_INTERNAL(efx));

efx->link_state.fd = true;
efx->link_state.fc = efx->wanted_fc;
efx->link_state.up = true;

if (efx->loopback_mode == LOOPBACK_GMAC)
efx->link_state.speed = 1000;
else
efx->link_state.speed = 10000;

return !efx_link_state_equal(&efx->link_state, &old_state);
}

/**************************************************************************
*
* PHY access via GMII
Expand Down Expand Up @@ -2225,15 +2229,6 @@ int falcon_switch_mac(struct efx_nic *efx)
/* Don't try to fetch MAC stats while we're switching MACs */
falcon_stop_nic_stats(efx);

/* Internal loopbacks override the phy speed setting */
if (efx->loopback_mode == LOOPBACK_GMAC) {
efx->link_state.speed = 1000;
efx->link_state.fd = true;
} else if (LOOPBACK_INTERNAL(efx)) {
efx->link_state.speed = 10000;
efx->link_state.fd = true;
}

WARN_ON(!mutex_is_locked(&efx->mac_lock));
efx->mac_op = (EFX_IS10G(efx) ?
&falcon_xmac_operations : &falcon_gmac_operations);
Expand Down Expand Up @@ -2610,16 +2605,36 @@ int falcon_reset_hw(struct efx_nic *efx, enum reset_type method)

void falcon_monitor(struct efx_nic *efx)
{
bool link_changed;
int rc;

BUG_ON(!mutex_is_locked(&efx->mac_lock));

rc = falcon_board(efx)->type->monitor(efx);
if (rc) {
EFX_ERR(efx, "Board sensor %s; shutting down PHY\n",
(rc == -ERANGE) ? "reported fault" : "failed");
efx->phy_mode |= PHY_MODE_LOW_POWER;
falcon_sim_phy_event(efx);
__efx_reconfigure_port(efx);
}
efx->phy_op->poll(efx);

if (LOOPBACK_INTERNAL(efx))
link_changed = falcon_loopback_link_poll(efx);
else
link_changed = efx->phy_op->poll(efx);

if (link_changed) {
falcon_stop_nic_stats(efx);
falcon_deconfigure_mac_wrapper(efx);

falcon_switch_mac(efx);
efx->mac_op->reconfigure(efx);

falcon_start_nic_stats(efx);

efx_link_status_changed(efx);
}

if (EFX_IS10G(efx))
falcon_poll_xmac(efx);
}
Expand Down
1 change: 0 additions & 1 deletion trunk/drivers/net/sfc/falcon.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,6 @@ extern int falcon_init_interrupt(struct efx_nic *efx);
extern void falcon_enable_interrupts(struct efx_nic *efx);
extern void falcon_generate_test_event(struct efx_channel *channel,
unsigned int magic);
extern void falcon_sim_phy_event(struct efx_nic *efx);
extern void falcon_generate_interrupt(struct efx_nic *efx);
extern void falcon_set_int_moderation(struct efx_channel *channel);
extern void falcon_disable_interrupts(struct efx_nic *efx);
Expand Down
24 changes: 14 additions & 10 deletions trunk/drivers/net/sfc/net_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,13 @@ struct efx_link_state {
unsigned int speed;
};

static inline bool efx_link_state_equal(const struct efx_link_state *left,
const struct efx_link_state *right)
{
return left->up == right->up && left->fd == right->fd &&
left->fc == right->fc && left->speed == right->speed;
}

/**
* struct efx_mac_operations - Efx MAC operations table
* @reconfigure: Reconfigure MAC. Serialised by the mac_lock
Expand All @@ -520,8 +527,8 @@ struct efx_mac_operations {
* @init: Initialise PHY
* @fini: Shut down PHY
* @reconfigure: Reconfigure PHY (e.g. for new link parameters)
* @clear_interrupt: Clear down interrupt
* @poll: Poll for hardware state. Serialised by the mac_lock.
* @poll: Update @link_state and report whether it changed.
* Serialised by the mac_lock.
* @get_settings: Get ethtool settings. Serialised by the mac_lock.
* @set_settings: Set ethtool settings. Serialised by the mac_lock.
* @set_npage_adv: Set abilities advertised in (Extended) Next Page
Expand All @@ -538,8 +545,7 @@ struct efx_phy_operations {
int (*init) (struct efx_nic *efx);
void (*fini) (struct efx_nic *efx);
void (*reconfigure) (struct efx_nic *efx);
void (*clear_interrupt) (struct efx_nic *efx);
void (*poll) (struct efx_nic *efx);
bool (*poll) (struct efx_nic *efx);
void (*get_settings) (struct efx_nic *efx,
struct ethtool_cmd *ecmd);
int (*set_settings) (struct efx_nic *efx,
Expand Down Expand Up @@ -700,10 +706,10 @@ union efx_multicast_hash {
* @mac_lock: MAC access lock. Protects @port_enabled, @phy_mode,
* @port_inhibited, efx_monitor() and efx_reconfigure_port()
* @port_enabled: Port enabled indicator.
* Serialises efx_stop_all(), efx_start_all(), efx_monitor(),
* efx_phy_work(), and efx_mac_work() with kernel interfaces. Safe to read
* under any one of the rtnl_lock, mac_lock, or netif_tx_lock, but all
* three must be held to modify it.
* Serialises efx_stop_all(), efx_start_all(), efx_monitor() and
* efx_mac_work() with kernel interfaces. Safe to read under any
* one of the rtnl_lock, mac_lock, or netif_tx_lock, but all three must
* be held to modify it.
* @port_inhibited: If set, the netif_carrier is always off. Hold the mac_lock
* @port_initialized: Port initialized?
* @net_dev: Operating system network device. Consider holding the rtnl lock
Expand All @@ -729,7 +735,6 @@ union efx_multicast_hash {
* @promiscuous: Promiscuous flag. Protected by netif_tx_lock.
* @multicast_hash: Multicast hash table
* @wanted_fc: Wanted flow control flags
* @phy_work: work item for dealing with PHY events
* @mac_work: Work item for changing MAC promiscuity and multicast hash
* @loopback_mode: Loopback status
* @loopback_modes: Supported loopback mode bitmask
Expand Down Expand Up @@ -802,7 +807,6 @@ struct efx_nic {

enum phy_type phy_type;
spinlock_t phy_lock;
struct work_struct phy_work;
struct efx_phy_operations *phy_op;
void *phy_data;
struct mdio_if_info mdio;
Expand Down
26 changes: 9 additions & 17 deletions trunk/drivers/net/sfc/qt202x_phy.c
Original file line number Diff line number Diff line change
Expand Up @@ -167,29 +167,26 @@ static int qt202x_phy_init(struct efx_nic *efx)
return rc;
}

static void qt202x_phy_clear_interrupt(struct efx_nic *efx)
{
/* Read to clear link status alarm */
efx_mdio_read(efx, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_STAT);
}

static int qt202x_link_ok(struct efx_nic *efx)
{
return efx_mdio_links_ok(efx, QT202X_REQUIRED_DEVS);
}

static void qt202x_phy_poll(struct efx_nic *efx)
static bool qt202x_phy_poll(struct efx_nic *efx)
{
int link_up = qt202x_link_ok(efx);
/* Simulate a PHY event if link state has changed */
if (link_up != efx->link_state.up)
falcon_sim_phy_event(efx);
bool was_up = efx->link_state.up;

efx->link_state.up = qt202x_link_ok(efx);
efx->link_state.speed = 10000;
efx->link_state.fd = true;
efx->link_state.fc = efx->wanted_fc;

return efx->link_state.up != was_up;
}

static void qt202x_phy_reconfigure(struct efx_nic *efx)
{
struct qt202x_phy_data *phy_data = efx->phy_data;
struct efx_link_state *link_state = &efx->link_state;

if (efx->phy_type == PHY_TYPE_QT2025C) {
/* There are several different register bits which can
Expand All @@ -216,10 +213,6 @@ static void qt202x_phy_reconfigure(struct efx_nic *efx)
efx_mdio_phy_reconfigure(efx);

phy_data->phy_mode = efx->phy_mode;
link_state->up = qt202x_link_ok(efx);
link_state->speed = 10000;
link_state->fd = true;
link_state->fc = efx->wanted_fc;
}

static void qt202x_phy_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
Expand All @@ -240,7 +233,6 @@ struct efx_phy_operations falcon_qt202x_phy_ops = {
.reconfigure = qt202x_phy_reconfigure,
.poll = qt202x_phy_poll,
.fini = qt202x_phy_fini,
.clear_interrupt = qt202x_phy_clear_interrupt,
.get_settings = qt202x_phy_get_settings,
.set_settings = efx_mdio_set_settings,
.mmds = QT202X_REQUIRED_DEVS,
Expand Down
Loading

0 comments on commit 37d945c

Please sign in to comment.