aboutsummaryrefslogtreecommitdiffstats
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
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>
-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