aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sfc/efx.c
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2009-11-25 11:12:16 -0500
committerDavid S. Miller <davem@davemloft.net>2009-11-26 18:59:49 -0500
commit8be4f3e6f7b670529bd67aa1f0319bec1e29ebcf (patch)
tree1d92fa5b1b1046f052c20d8bdaa17ffce6881446 /drivers/net/sfc/efx.c
parent9007b9fa368b172e6b9a985899080fbebb7d3204 (diff)
sfc: Change MAC promiscuity and multicast hash at the same time
From: Steve Hodgson <shodgson@solarflare.com> Currently we can set multicast hash immediately (in atomic context) but must delay setting MAC promiscuity. There is not that much point in deferring one but not the other, and setting the multicast hash on Siena will involve a firmware request. So process them both in efx_mac_work(). Also, set the broadcast bit in the multicast hash in efx_set_multicast_list(), since this is required for both Falcon and Siena. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/sfc/efx.c')
-rw-r--r--drivers/net/sfc/efx.c38
1 files changed, 24 insertions, 14 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 = {