Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Edward Cree and committed by
David S. Miller
84e7fc25 f72c38fa

+59 -3
+3
drivers/net/ethernet/sfc/ef100_netdev.c
··· 85 85 netif_dbg(efx, ifdown, efx->net_dev, "closing on CPU %d\n", 86 86 raw_smp_processor_id()); 87 87 88 + efx_detach_reps(efx); 88 89 netif_stop_queue(net_dev); 89 90 efx_stop_all(efx); 90 91 efx_mcdi_mac_fini_stats(efx); ··· 177 176 mutex_unlock(&efx->mac_lock); 178 177 179 178 efx->state = STATE_NET_UP; 179 + if (netif_running(efx->net_dev)) 180 + efx_attach_reps(efx); 180 181 181 182 return 0; 182 183
+9 -2
drivers/net/ethernet/sfc/ef100_rep.c
··· 132 132 spin_lock_bh(&efx->vf_reps_lock); 133 133 list_add_tail(&efv->list, &efx->vf_reps); 134 134 spin_unlock_bh(&efx->vf_reps_lock); 135 - netif_carrier_off(net_dev); 136 - netif_tx_stop_all_queues(net_dev); 135 + if (netif_running(efx->net_dev) && efx->state == STATE_NET_UP) { 136 + netif_device_attach(net_dev); 137 + netif_carrier_on(net_dev); 138 + } else { 139 + netif_carrier_off(net_dev); 140 + netif_tx_stop_all_queues(net_dev); 141 + } 137 142 rtnl_unlock(); 138 143 139 144 net_dev->netdev_ops = &efx_ef100_rep_netdev_ops; ··· 176 171 { 177 172 struct efx_nic *efx = efv->parent; 178 173 174 + rtnl_lock(); 179 175 spin_lock_bh(&efx->vf_reps_lock); 180 176 list_del(&efv->list); 181 177 spin_unlock_bh(&efx->vf_reps_lock); 178 + rtnl_unlock(); 182 179 free_netdev(efv->net_dev); 183 180 } 184 181
+8 -1
drivers/net/ethernet/sfc/efx.h
··· 12 12 #include "net_driver.h" 13 13 #include "ef100_rx.h" 14 14 #include "ef100_tx.h" 15 + #include "efx_common.h" 15 16 #include "filter.h" 16 17 17 18 int efx_net_open(struct net_device *net_dev); ··· 207 206 { 208 207 struct net_device *dev = efx->net_dev; 209 208 209 + /* We must stop reps (which use our TX) before we stop ourselves. */ 210 + efx_detach_reps(efx); 211 + 210 212 /* Lock/freeze all TX queues so that we can be sure the 211 213 * TX scheduler is stopped when we're done and before 212 214 * netif_device_present() becomes false. ··· 221 217 222 218 static inline void efx_device_attach_if_not_resetting(struct efx_nic *efx) 223 219 { 224 - if ((efx->state != STATE_DISABLED) && !efx->reset_pending) 220 + if ((efx->state != STATE_DISABLED) && !efx->reset_pending) { 225 221 netif_device_attach(efx->net_dev); 222 + if (efx->state == STATE_NET_UP) 223 + efx_attach_reps(efx); 224 + } 226 225 } 227 226 228 227 static inline bool efx_rwsem_assert_write_locked(struct rw_semaphore *sem)
+36
drivers/net/ethernet/sfc/efx_common.c
··· 24 24 #include "mcdi_port_common.h" 25 25 #include "io.h" 26 26 #include "mcdi_pcol.h" 27 + #include "ef100_rep.h" 27 28 28 29 static unsigned int debug = (NETIF_MSG_DRV | NETIF_MSG_PROBE | 29 30 NETIF_MSG_LINK | NETIF_MSG_IFDOWN | ··· 1391 1390 if (snprintf(name, len, "p%u", efx->port_num) >= len) 1392 1391 return -EINVAL; 1393 1392 return 0; 1393 + } 1394 + 1395 + void efx_detach_reps(struct efx_nic *efx) 1396 + { 1397 + struct net_device *rep_dev; 1398 + struct efx_rep *efv; 1399 + 1400 + ASSERT_RTNL(); 1401 + netif_dbg(efx, drv, efx->net_dev, "Detaching VF representors\n"); 1402 + list_for_each_entry(efv, &efx->vf_reps, list) { 1403 + rep_dev = efv->net_dev; 1404 + if (!rep_dev) 1405 + continue; 1406 + netif_carrier_off(rep_dev); 1407 + /* See efx_device_detach_sync() */ 1408 + netif_tx_lock_bh(rep_dev); 1409 + netif_tx_stop_all_queues(rep_dev); 1410 + netif_tx_unlock_bh(rep_dev); 1411 + } 1412 + } 1413 + 1414 + void efx_attach_reps(struct efx_nic *efx) 1415 + { 1416 + struct net_device *rep_dev; 1417 + struct efx_rep *efv; 1418 + 1419 + ASSERT_RTNL(); 1420 + netif_dbg(efx, drv, efx->net_dev, "Attaching VF representors\n"); 1421 + list_for_each_entry(efv, &efx->vf_reps, list) { 1422 + rep_dev = efv->net_dev; 1423 + if (!rep_dev) 1424 + continue; 1425 + netif_tx_wake_all_queues(rep_dev); 1426 + netif_carrier_on(rep_dev); 1427 + } 1394 1428 }
+3
drivers/net/ethernet/sfc/efx_common.h
··· 111 111 112 112 int efx_get_phys_port_name(struct net_device *net_dev, 113 113 char *name, size_t len); 114 + 115 + void efx_detach_reps(struct efx_nic *efx); 116 + void efx_attach_reps(struct efx_nic *efx); 114 117 #endif