aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sfc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/sfc')
-rw-r--r--drivers/net/sfc/efx.c38
-rw-r--r--drivers/net/sfc/falcon.c10
-rw-r--r--drivers/net/sfc/falcon.h2
-rw-r--r--drivers/net/sfc/net_driver.h2
4 files changed, 29 insertions, 23 deletions
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index 15616dd9ed41..1009d1eeba82 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -688,11 +688,18 @@ static void efx_phy_work(struct work_struct *data)
688 mutex_unlock(&efx->mac_lock); 688 mutex_unlock(&efx->mac_lock);
689} 689}
690 690
691/* Asynchronous work item for changing MAC promiscuity and multicast
692 * hash. Avoid a drain/rx_ingress enable by reconfiguring the current
693 * MAC directly. */
691static void efx_mac_work(struct work_struct *data) 694static void efx_mac_work(struct work_struct *data)
692{ 695{
693 struct efx_nic *efx = container_of(data, struct efx_nic, mac_work); 696 struct efx_nic *efx = container_of(data, struct efx_nic, mac_work);
694 697
695 mutex_lock(&efx->mac_lock); 698 mutex_lock(&efx->mac_lock);
699 if (efx->port_enabled) {
700 falcon_push_multicast_hash(efx);
701 efx->mac_op->reconfigure(efx);
702 }
696 mutex_unlock(&efx->mac_lock); 703 mutex_unlock(&efx->mac_lock);
697} 704}
698 705
@@ -771,7 +778,12 @@ static void efx_start_port(struct efx_nic *efx)
771 778
772 mutex_lock(&efx->mac_lock); 779 mutex_lock(&efx->mac_lock);
773 efx->port_enabled = true; 780 efx->port_enabled = true;
774 __efx_reconfigure_port(efx); 781
782 /* efx_mac_work() might have been scheduled after efx_stop_port(),
783 * and then cancelled by efx_flush_all() */
784 falcon_push_multicast_hash(efx);
785 efx->mac_op->reconfigure(efx);
786
775 mutex_unlock(&efx->mac_lock); 787 mutex_unlock(&efx->mac_lock);
776} 788}
777 789
@@ -1534,16 +1546,14 @@ static void efx_set_multicast_list(struct net_device *net_dev)
1534 struct efx_nic *efx = netdev_priv(net_dev); 1546 struct efx_nic *efx = netdev_priv(net_dev);
1535 struct dev_mc_list *mc_list = net_dev->mc_list; 1547 struct dev_mc_list *mc_list = net_dev->mc_list;
1536 union efx_multicast_hash *mc_hash = &efx->multicast_hash; 1548 union efx_multicast_hash *mc_hash = &efx->multicast_hash;
1537 bool promiscuous = !!(net_dev->flags & IFF_PROMISC);
1538 bool changed = (efx->promiscuous != promiscuous);
1539 u32 crc; 1549 u32 crc;
1540 int bit; 1550 int bit;
1541 int i; 1551 int i;
1542 1552
1543 efx->promiscuous = promiscuous; 1553 efx->promiscuous = !!(net_dev->flags & IFF_PROMISC);
1544 1554
1545 /* Build multicast hash table */ 1555 /* Build multicast hash table */
1546 if (promiscuous || (net_dev->flags & IFF_ALLMULTI)) { 1556 if (efx->promiscuous || (net_dev->flags & IFF_ALLMULTI)) {
1547 memset(mc_hash, 0xff, sizeof(*mc_hash)); 1557 memset(mc_hash, 0xff, sizeof(*mc_hash));
1548 } else { 1558 } else {
1549 memset(mc_hash, 0x00, sizeof(*mc_hash)); 1559 memset(mc_hash, 0x00, sizeof(*mc_hash));
@@ -1553,17 +1563,17 @@ static void efx_set_multicast_list(struct net_device *net_dev)
1553 set_bit_le(bit, mc_hash->byte); 1563 set_bit_le(bit, mc_hash->byte);
1554 mc_list = mc_list->next; 1564 mc_list = mc_list->next;
1555 } 1565 }
1556 }
1557 1566
1558 if (!efx->port_enabled) 1567 /* Broadcast packets go through the multicast hash filter.
1559 /* Delay pushing settings until efx_start_port() */ 1568 * ether_crc_le() of the broadcast address is 0xbe2612ff
1560 return; 1569 * so we always add bit 0xff to the mask.
1561 1570 */
1562 if (changed) 1571 set_bit_le(0xff, mc_hash->byte);
1563 queue_work(efx->workqueue, &efx->phy_work); 1572 }
1564 1573
1565 /* Create and activate new global multicast hash table */ 1574 if (efx->port_enabled)
1566 falcon_set_multicast_hash(efx); 1575 queue_work(efx->workqueue, &efx->mac_work);
1576 /* Otherwise efx_start_port() will do this */
1567} 1577}
1568 1578
1569static const struct net_device_ops efx_netdev_ops = { 1579static const struct net_device_ops efx_netdev_ops = {
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c
index fac534a274c8..e26043eb01b5 100644
--- a/drivers/net/sfc/falcon.c
+++ b/drivers/net/sfc/falcon.c
@@ -1993,7 +1993,7 @@ void falcon_reconfigure_mac_wrapper(struct efx_nic *efx)
1993 efx_writeo(efx, &reg, FR_AB_MAC_CTRL); 1993 efx_writeo(efx, &reg, FR_AB_MAC_CTRL);
1994 1994
1995 /* Restore the multicast hash registers. */ 1995 /* Restore the multicast hash registers. */
1996 falcon_set_multicast_hash(efx); 1996 falcon_push_multicast_hash(efx);
1997 1997
1998 /* Transmission of pause frames when RX crosses the threshold is 1998 /* Transmission of pause frames when RX crosses the threshold is
1999 * covered by RX_XOFF_MAC_EN and XM_TX_CFG_REG:XM_FCNTL. 1999 * covered by RX_XOFF_MAC_EN and XM_TX_CFG_REG:XM_FCNTL.
@@ -2327,15 +2327,11 @@ void falcon_remove_port(struct efx_nic *efx)
2327 ************************************************************************** 2327 **************************************************************************
2328 */ 2328 */
2329 2329
2330void falcon_set_multicast_hash(struct efx_nic *efx) 2330void falcon_push_multicast_hash(struct efx_nic *efx)
2331{ 2331{
2332 union efx_multicast_hash *mc_hash = &efx->multicast_hash; 2332 union efx_multicast_hash *mc_hash = &efx->multicast_hash;
2333 2333
2334 /* Broadcast packets go through the multicast hash filter. 2334 WARN_ON(!mutex_is_locked(&efx->mac_lock));
2335 * ether_crc_le() of the broadcast address is 0xbe2612ff
2336 * so we always add bit 0xff to the mask.
2337 */
2338 set_bit_le(0xff, mc_hash->byte);
2339 2335
2340 efx_writeo(efx, &mc_hash->oword[0], FR_AB_MAC_MC_HASH_REG0); 2336 efx_writeo(efx, &mc_hash->oword[0], FR_AB_MAC_MC_HASH_REG0);
2341 efx_writeo(efx, &mc_hash->oword[1], FR_AB_MAC_MC_HASH_REG1); 2337 efx_writeo(efx, &mc_hash->oword[1], FR_AB_MAC_MC_HASH_REG1);
diff --git a/drivers/net/sfc/falcon.h b/drivers/net/sfc/falcon.h
index 9ae1b6c8474e..c70bb084216f 100644
--- a/drivers/net/sfc/falcon.h
+++ b/drivers/net/sfc/falcon.h
@@ -163,7 +163,7 @@ extern void falcon_remove_nic(struct efx_nic *efx);
163extern void falcon_update_nic_stats(struct efx_nic *efx); 163extern void falcon_update_nic_stats(struct efx_nic *efx);
164extern void falcon_start_nic_stats(struct efx_nic *efx); 164extern void falcon_start_nic_stats(struct efx_nic *efx);
165extern void falcon_stop_nic_stats(struct efx_nic *efx); 165extern void falcon_stop_nic_stats(struct efx_nic *efx);
166extern void falcon_set_multicast_hash(struct efx_nic *efx); 166extern void falcon_push_multicast_hash(struct efx_nic *efx);
167extern int falcon_reset_xaui(struct efx_nic *efx); 167extern int falcon_reset_xaui(struct efx_nic *efx);
168 168
169/* Tests */ 169/* Tests */
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h
index cc1a97b0a0d3..ead1c982365b 100644
--- a/drivers/net/sfc/net_driver.h
+++ b/drivers/net/sfc/net_driver.h
@@ -730,7 +730,7 @@ union efx_multicast_hash {
730 * @multicast_hash: Multicast hash table 730 * @multicast_hash: Multicast hash table
731 * @wanted_fc: Wanted flow control flags 731 * @wanted_fc: Wanted flow control flags
732 * @phy_work: work item for dealing with PHY events 732 * @phy_work: work item for dealing with PHY events
733 * @mac_work: work item for dealing with MAC events 733 * @mac_work: Work item for changing MAC promiscuity and multicast hash
734 * @loopback_mode: Loopback status 734 * @loopback_mode: Loopback status
735 * @loopback_modes: Supported loopback mode bitmask 735 * @loopback_modes: Supported loopback mode bitmask
736 * @loopback_selftest: Offline self-test private state 736 * @loopback_selftest: Offline self-test private state