diff options
Diffstat (limited to 'drivers/net/sfc')
-rw-r--r-- | drivers/net/sfc/efx.c | 38 | ||||
-rw-r--r-- | drivers/net/sfc/falcon.c | 10 | ||||
-rw-r--r-- | drivers/net/sfc/falcon.h | 2 | ||||
-rw-r--r-- | drivers/net/sfc/net_driver.h | 2 |
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. */ | ||
691 | static void efx_mac_work(struct work_struct *data) | 694 | static 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 | ||
1569 | static const struct net_device_ops efx_netdev_ops = { | 1579 | static 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, ®, FR_AB_MAC_CTRL); | 1993 | efx_writeo(efx, ®, 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 | ||
2330 | void falcon_set_multicast_hash(struct efx_nic *efx) | 2330 | void 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); | |||
163 | extern void falcon_update_nic_stats(struct efx_nic *efx); | 163 | extern void falcon_update_nic_stats(struct efx_nic *efx); |
164 | extern void falcon_start_nic_stats(struct efx_nic *efx); | 164 | extern void falcon_start_nic_stats(struct efx_nic *efx); |
165 | extern void falcon_stop_nic_stats(struct efx_nic *efx); | 165 | extern void falcon_stop_nic_stats(struct efx_nic *efx); |
166 | extern void falcon_set_multicast_hash(struct efx_nic *efx); | 166 | extern void falcon_push_multicast_hash(struct efx_nic *efx); |
167 | extern int falcon_reset_xaui(struct efx_nic *efx); | 167 | extern 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 |