mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-11 00:08:50 +00:00
sfc: attach/detach EF100 representors along with their owning PF
Since representors piggy-back on the PF's queues for TX, they can only accept new TXes while the PF is up. Thus, any operation which detaches the PF must first detach all its VFreps. Signed-off-by: Edward Cree <ecree.xilinx@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
f72c38fad2
commit
84e7fc2591
@ -85,6 +85,7 @@ static int ef100_net_stop(struct net_device *net_dev)
|
||||
netif_dbg(efx, ifdown, efx->net_dev, "closing on CPU %d\n",
|
||||
raw_smp_processor_id());
|
||||
|
||||
efx_detach_reps(efx);
|
||||
netif_stop_queue(net_dev);
|
||||
efx_stop_all(efx);
|
||||
efx_mcdi_mac_fini_stats(efx);
|
||||
@ -176,6 +177,8 @@ static int ef100_net_open(struct net_device *net_dev)
|
||||
mutex_unlock(&efx->mac_lock);
|
||||
|
||||
efx->state = STATE_NET_UP;
|
||||
if (netif_running(efx->net_dev))
|
||||
efx_attach_reps(efx);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -132,8 +132,13 @@ static struct efx_rep *efx_ef100_rep_create_netdev(struct efx_nic *efx,
|
||||
spin_lock_bh(&efx->vf_reps_lock);
|
||||
list_add_tail(&efv->list, &efx->vf_reps);
|
||||
spin_unlock_bh(&efx->vf_reps_lock);
|
||||
netif_carrier_off(net_dev);
|
||||
netif_tx_stop_all_queues(net_dev);
|
||||
if (netif_running(efx->net_dev) && efx->state == STATE_NET_UP) {
|
||||
netif_device_attach(net_dev);
|
||||
netif_carrier_on(net_dev);
|
||||
} else {
|
||||
netif_carrier_off(net_dev);
|
||||
netif_tx_stop_all_queues(net_dev);
|
||||
}
|
||||
rtnl_unlock();
|
||||
|
||||
net_dev->netdev_ops = &efx_ef100_rep_netdev_ops;
|
||||
@ -171,9 +176,11 @@ static void efx_ef100_rep_destroy_netdev(struct efx_rep *efv)
|
||||
{
|
||||
struct efx_nic *efx = efv->parent;
|
||||
|
||||
rtnl_lock();
|
||||
spin_lock_bh(&efx->vf_reps_lock);
|
||||
list_del(&efv->list);
|
||||
spin_unlock_bh(&efx->vf_reps_lock);
|
||||
rtnl_unlock();
|
||||
free_netdev(efv->net_dev);
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "net_driver.h"
|
||||
#include "ef100_rx.h"
|
||||
#include "ef100_tx.h"
|
||||
#include "efx_common.h"
|
||||
#include "filter.h"
|
||||
|
||||
int efx_net_open(struct net_device *net_dev);
|
||||
@ -206,6 +207,9 @@ static inline void efx_device_detach_sync(struct efx_nic *efx)
|
||||
{
|
||||
struct net_device *dev = efx->net_dev;
|
||||
|
||||
/* We must stop reps (which use our TX) before we stop ourselves. */
|
||||
efx_detach_reps(efx);
|
||||
|
||||
/* Lock/freeze all TX queues so that we can be sure the
|
||||
* TX scheduler is stopped when we're done and before
|
||||
* netif_device_present() becomes false.
|
||||
@ -217,8 +221,11 @@ static inline void efx_device_detach_sync(struct efx_nic *efx)
|
||||
|
||||
static inline void efx_device_attach_if_not_resetting(struct efx_nic *efx)
|
||||
{
|
||||
if ((efx->state != STATE_DISABLED) && !efx->reset_pending)
|
||||
if ((efx->state != STATE_DISABLED) && !efx->reset_pending) {
|
||||
netif_device_attach(efx->net_dev);
|
||||
if (efx->state == STATE_NET_UP)
|
||||
efx_attach_reps(efx);
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool efx_rwsem_assert_write_locked(struct rw_semaphore *sem)
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "mcdi_port_common.h"
|
||||
#include "io.h"
|
||||
#include "mcdi_pcol.h"
|
||||
#include "ef100_rep.h"
|
||||
|
||||
static unsigned int debug = (NETIF_MSG_DRV | NETIF_MSG_PROBE |
|
||||
NETIF_MSG_LINK | NETIF_MSG_IFDOWN |
|
||||
@ -1391,3 +1392,38 @@ int efx_get_phys_port_name(struct net_device *net_dev, char *name, size_t len)
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void efx_detach_reps(struct efx_nic *efx)
|
||||
{
|
||||
struct net_device *rep_dev;
|
||||
struct efx_rep *efv;
|
||||
|
||||
ASSERT_RTNL();
|
||||
netif_dbg(efx, drv, efx->net_dev, "Detaching VF representors\n");
|
||||
list_for_each_entry(efv, &efx->vf_reps, list) {
|
||||
rep_dev = efv->net_dev;
|
||||
if (!rep_dev)
|
||||
continue;
|
||||
netif_carrier_off(rep_dev);
|
||||
/* See efx_device_detach_sync() */
|
||||
netif_tx_lock_bh(rep_dev);
|
||||
netif_tx_stop_all_queues(rep_dev);
|
||||
netif_tx_unlock_bh(rep_dev);
|
||||
}
|
||||
}
|
||||
|
||||
void efx_attach_reps(struct efx_nic *efx)
|
||||
{
|
||||
struct net_device *rep_dev;
|
||||
struct efx_rep *efv;
|
||||
|
||||
ASSERT_RTNL();
|
||||
netif_dbg(efx, drv, efx->net_dev, "Attaching VF representors\n");
|
||||
list_for_each_entry(efv, &efx->vf_reps, list) {
|
||||
rep_dev = efv->net_dev;
|
||||
if (!rep_dev)
|
||||
continue;
|
||||
netif_tx_wake_all_queues(rep_dev);
|
||||
netif_carrier_on(rep_dev);
|
||||
}
|
||||
}
|
||||
|
@ -111,4 +111,7 @@ int efx_get_phys_port_id(struct net_device *net_dev,
|
||||
|
||||
int efx_get_phys_port_name(struct net_device *net_dev,
|
||||
char *name, size_t len);
|
||||
|
||||
void efx_detach_reps(struct efx_nic *efx);
|
||||
void efx_attach_reps(struct efx_nic *efx);
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user