aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/mwl8k.c
diff options
context:
space:
mode:
authorLennert Buytenhek <buytenh@wantstofly.org>2009-10-22 14:19:41 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-11-04 18:44:43 -0500
commitd5e308457e8e9b4988fbd69d38c30782125b3f65 (patch)
treed3ddf0ad2dcee1e739a726debd626908d4bd67b5 /drivers/net/wireless/mwl8k.c
parent88de754ad59025eba797e7a8375807755577f450 (diff)
mwl8k: fix multicast address filter programming
mwl8k's ->prepare_multicast() currently just enables reception of all multicast packets, which is somewhat ineffective. Fix this by either disabling all multicast RX, enabling multicast RX according to the multicast address filter table, or enabling all multicast RX, depending on whether ->prepare_multicast() was given any multicast addresses and whether the hardware multicast address filter table is large enough to fit all requested addresses. Signed-off-by: Lennert Buytenhek <buytenh@marvell.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/mwl8k.c')
-rw-r--r--drivers/net/wireless/mwl8k.c40
1 files changed, 27 insertions, 13 deletions
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index ba7b8efea778..0b4fa14aa176 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -1539,7 +1539,10 @@ struct mwl8k_cmd_mac_multicast_adr {
1539 __u8 addr[0][ETH_ALEN]; 1539 __u8 addr[0][ETH_ALEN];
1540}; 1540};
1541 1541
1542#define MWL8K_ENABLE_RX_MULTICAST 0x000F 1542#define MWL8K_ENABLE_RX_DIRECTED 0x0001
1543#define MWL8K_ENABLE_RX_MULTICAST 0x0002
1544#define MWL8K_ENABLE_RX_ALL_MULTICAST 0x0004
1545#define MWL8K_ENABLE_RX_BROADCAST 0x0008
1543 1546
1544static struct mwl8k_cmd_pkt * 1547static struct mwl8k_cmd_pkt *
1545__mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw, 1548__mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw,
@@ -1547,11 +1550,14 @@ __mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw,
1547{ 1550{
1548 struct mwl8k_priv *priv = hw->priv; 1551 struct mwl8k_priv *priv = hw->priv;
1549 struct mwl8k_cmd_mac_multicast_adr *cmd; 1552 struct mwl8k_cmd_mac_multicast_adr *cmd;
1553 int allmulti;
1550 int size; 1554 int size;
1551 int i;
1552 1555
1553 if (mc_count > priv->num_mcaddrs) 1556 allmulti = 0;
1554 mc_count = priv->num_mcaddrs; 1557 if (mc_count > priv->num_mcaddrs) {
1558 allmulti = 1;
1559 mc_count = 0;
1560 }
1555 1561
1556 size = sizeof(*cmd) + mc_count * ETH_ALEN; 1562 size = sizeof(*cmd) + mc_count * ETH_ALEN;
1557 1563
@@ -1561,16 +1567,24 @@ __mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw,
1561 1567
1562 cmd->header.code = cpu_to_le16(MWL8K_CMD_MAC_MULTICAST_ADR); 1568 cmd->header.code = cpu_to_le16(MWL8K_CMD_MAC_MULTICAST_ADR);
1563 cmd->header.length = cpu_to_le16(size); 1569 cmd->header.length = cpu_to_le16(size);
1564 cmd->action = cpu_to_le16(MWL8K_ENABLE_RX_MULTICAST); 1570 cmd->action = cpu_to_le16(MWL8K_ENABLE_RX_DIRECTED |
1565 cmd->numaddr = cpu_to_le16(mc_count); 1571 MWL8K_ENABLE_RX_BROADCAST);
1566 1572
1567 for (i = 0; i < mc_count && mclist; i++) { 1573 if (allmulti) {
1568 if (mclist->da_addrlen != ETH_ALEN) { 1574 cmd->action |= cpu_to_le16(MWL8K_ENABLE_RX_ALL_MULTICAST);
1569 kfree(cmd); 1575 } else if (mc_count) {
1570 return NULL; 1576 int i;
1577
1578 cmd->action |= cpu_to_le16(MWL8K_ENABLE_RX_MULTICAST);
1579 cmd->numaddr = cpu_to_le16(mc_count);
1580 for (i = 0; i < mc_count && mclist; i++) {
1581 if (mclist->da_addrlen != ETH_ALEN) {
1582 kfree(cmd);
1583 return NULL;
1584 }
1585 memcpy(cmd->addr[i], mclist->da_addr, ETH_ALEN);
1586 mclist = mclist->next;
1571 } 1587 }
1572 memcpy(cmd->addr[i], mclist->da_addr, ETH_ALEN);
1573 mclist = mclist->next;
1574 } 1588 }
1575 1589
1576 return &cmd->header; 1590 return &cmd->header;