Commit fbf219f1 authored by Jiri Pirko's avatar Jiri Pirko Committed by David S. Miller

infiniband: convert to use netdev_for_each_mc_addr

Due to the loop complexicity in nes_nic.c, I'm using char* to copy mc addresses
to it.
Signed-off-by: default avatarJiri Pirko <jpirko@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6e17d45a
...@@ -810,6 +810,20 @@ static int nes_netdev_set_mac_address(struct net_device *netdev, void *p) ...@@ -810,6 +810,20 @@ static int nes_netdev_set_mac_address(struct net_device *netdev, void *p)
} }
static void set_allmulti(struct nes_device *nesdev, u32 nic_active_bit)
{
u32 nic_active;
nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL);
nic_active |= nic_active_bit;
nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL, nic_active);
nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL);
nic_active &= ~nic_active_bit;
nes_write_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL, nic_active);
}
#define get_addr(addrs, index) ((addrs) + (index) * ETH_ALEN)
/** /**
* nes_netdev_set_multicast_list * nes_netdev_set_multicast_list
*/ */
...@@ -818,7 +832,6 @@ static void nes_netdev_set_multicast_list(struct net_device *netdev) ...@@ -818,7 +832,6 @@ static void nes_netdev_set_multicast_list(struct net_device *netdev)
struct nes_vnic *nesvnic = netdev_priv(netdev); struct nes_vnic *nesvnic = netdev_priv(netdev);
struct nes_device *nesdev = nesvnic->nesdev; struct nes_device *nesdev = nesvnic->nesdev;
struct nes_adapter *nesadapter = nesvnic->nesdev->nesadapter; struct nes_adapter *nesadapter = nesvnic->nesdev->nesadapter;
struct dev_mc_list *multicast_addr;
u32 nic_active_bit; u32 nic_active_bit;
u32 nic_active; u32 nic_active;
u32 perfect_filter_register_address; u32 perfect_filter_register_address;
...@@ -831,6 +844,7 @@ static void nes_netdev_set_multicast_list(struct net_device *netdev) ...@@ -831,6 +844,7 @@ static void nes_netdev_set_multicast_list(struct net_device *netdev)
nics_per_function, 4); nics_per_function, 4);
u8 max_pft_entries_avaiable = NES_PFT_SIZE - pft_entries_preallocated; u8 max_pft_entries_avaiable = NES_PFT_SIZE - pft_entries_preallocated;
unsigned long flags; unsigned long flags;
int mc_count = netdev_mc_count(netdev);
spin_lock_irqsave(&nesadapter->resource_lock, flags); spin_lock_irqsave(&nesadapter->resource_lock, flags);
nic_active_bit = 1 << nesvnic->nic_index; nic_active_bit = 1 << nesvnic->nic_index;
...@@ -845,12 +859,7 @@ static void nes_netdev_set_multicast_list(struct net_device *netdev) ...@@ -845,12 +859,7 @@ static void nes_netdev_set_multicast_list(struct net_device *netdev)
mc_all_on = 1; mc_all_on = 1;
} else if ((netdev->flags & IFF_ALLMULTI) || } else if ((netdev->flags & IFF_ALLMULTI) ||
(nesvnic->nic_index > 3)) { (nesvnic->nic_index > 3)) {
nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL); set_allmulti(nesdev, nic_active_bit);
nic_active |= nic_active_bit;
nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL, nic_active);
nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL);
nic_active &= ~nic_active_bit;
nes_write_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL, nic_active);
mc_all_on = 1; mc_all_on = 1;
} else { } else {
nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL); nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL);
...@@ -862,19 +871,30 @@ static void nes_netdev_set_multicast_list(struct net_device *netdev) ...@@ -862,19 +871,30 @@ static void nes_netdev_set_multicast_list(struct net_device *netdev)
} }
nes_debug(NES_DBG_NIC_RX, "Number of MC entries = %d, Promiscous = %d, All Multicast = %d.\n", nes_debug(NES_DBG_NIC_RX, "Number of MC entries = %d, Promiscous = %d, All Multicast = %d.\n",
netdev_mc_count(netdev), !!(netdev->flags & IFF_PROMISC), mc_count, !!(netdev->flags & IFF_PROMISC),
!!(netdev->flags & IFF_ALLMULTI)); !!(netdev->flags & IFF_ALLMULTI));
if (!mc_all_on) { if (!mc_all_on) {
multicast_addr = netdev->mc_list; char *addrs;
int i;
struct dev_mc_list *mcaddr;
addrs = kmalloc(ETH_ALEN * mc_count, GFP_ATOMIC);
if (!addrs) {
set_allmulti(nesdev, nic_active_bit);
goto unlock;
}
i = 0;
netdev_for_each_mc_addr(mcaddr, netdev)
memcpy(get_addr(addrs, i++),
mcaddr->dmi_addr, ETH_ALEN);
perfect_filter_register_address = NES_IDX_PERFECT_FILTER_LOW + perfect_filter_register_address = NES_IDX_PERFECT_FILTER_LOW +
pft_entries_preallocated * 0x8; pft_entries_preallocated * 0x8;
for (mc_index = 0; mc_index < max_pft_entries_avaiable; for (i = 0, mc_index = 0; mc_index < max_pft_entries_avaiable;
mc_index++) { mc_index++) {
while (multicast_addr && nesvnic->mcrq_mcast_filter && while (i < mc_count && nesvnic->mcrq_mcast_filter &&
((mc_nic_index = nesvnic->mcrq_mcast_filter(nesvnic, ((mc_nic_index = nesvnic->mcrq_mcast_filter(nesvnic,
multicast_addr->dmi_addr)) == 0)) { get_addr(addrs, i++))) == 0));
multicast_addr = multicast_addr->next;
}
if (mc_nic_index < 0) if (mc_nic_index < 0)
mc_nic_index = nesvnic->nic_index; mc_nic_index = nesvnic->nic_index;
while (nesadapter->pft_mcast_map[mc_index] < 16 && while (nesadapter->pft_mcast_map[mc_index] < 16 &&
...@@ -890,17 +910,19 @@ static void nes_netdev_set_multicast_list(struct net_device *netdev) ...@@ -890,17 +910,19 @@ static void nes_netdev_set_multicast_list(struct net_device *netdev)
} }
if (mc_index >= max_pft_entries_avaiable) if (mc_index >= max_pft_entries_avaiable)
break; break;
if (multicast_addr) { if (i < mc_count) {
char *addr = get_addr(addrs, i++);
nes_debug(NES_DBG_NIC_RX, "Assigning MC Address %pM to register 0x%04X nic_idx=%d\n", nes_debug(NES_DBG_NIC_RX, "Assigning MC Address %pM to register 0x%04X nic_idx=%d\n",
multicast_addr->dmi_addr, addr,
perfect_filter_register_address+(mc_index * 8), perfect_filter_register_address+(mc_index * 8),
mc_nic_index); mc_nic_index);
macaddr_high = ((u16)multicast_addr->dmi_addr[0]) << 8; macaddr_high = ((u16) addr[0]) << 8;
macaddr_high += (u16)multicast_addr->dmi_addr[1]; macaddr_high += (u16) addr[1];
macaddr_low = ((u32)multicast_addr->dmi_addr[2]) << 24; macaddr_low = ((u32) addr[2]) << 24;
macaddr_low += ((u32)multicast_addr->dmi_addr[3]) << 16; macaddr_low += ((u32) addr[3]) << 16;
macaddr_low += ((u32)multicast_addr->dmi_addr[4]) << 8; macaddr_low += ((u32) addr[4]) << 8;
macaddr_low += (u32)multicast_addr->dmi_addr[5]; macaddr_low += (u32) addr[5];
nes_write_indexed(nesdev, nes_write_indexed(nesdev,
perfect_filter_register_address+(mc_index * 8), perfect_filter_register_address+(mc_index * 8),
macaddr_low); macaddr_low);
...@@ -908,7 +930,6 @@ static void nes_netdev_set_multicast_list(struct net_device *netdev) ...@@ -908,7 +930,6 @@ static void nes_netdev_set_multicast_list(struct net_device *netdev)
perfect_filter_register_address+4+(mc_index * 8), perfect_filter_register_address+4+(mc_index * 8),
(u32)macaddr_high | NES_MAC_ADDR_VALID | (u32)macaddr_high | NES_MAC_ADDR_VALID |
((((u32)(1<<mc_nic_index)) << 16))); ((((u32)(1<<mc_nic_index)) << 16)));
multicast_addr = multicast_addr->next;
nesadapter->pft_mcast_map[mc_index] = nesadapter->pft_mcast_map[mc_index] =
nesvnic->nic_index; nesvnic->nic_index;
} else { } else {
...@@ -920,21 +941,13 @@ static void nes_netdev_set_multicast_list(struct net_device *netdev) ...@@ -920,21 +941,13 @@ static void nes_netdev_set_multicast_list(struct net_device *netdev)
nesadapter->pft_mcast_map[mc_index] = 255; nesadapter->pft_mcast_map[mc_index] = 255;
} }
} }
kfree(addrs);
/* PFT is not large enough */ /* PFT is not large enough */
if (multicast_addr && multicast_addr->next) { if (i < mc_count)
nic_active = nes_read_indexed(nesdev, set_allmulti(nesdev, nic_active_bit);
NES_IDX_NIC_MULTICAST_ALL);
nic_active |= nic_active_bit;
nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL,
nic_active);
nic_active = nes_read_indexed(nesdev,
NES_IDX_NIC_UNICAST_ALL);
nic_active &= ~nic_active_bit;
nes_write_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL,
nic_active);
}
} }
unlock:
spin_unlock_irqrestore(&nesadapter->resource_lock, flags); spin_unlock_irqrestore(&nesadapter->resource_lock, flags);
} }
......
...@@ -767,11 +767,8 @@ void ipoib_mcast_dev_flush(struct net_device *dev) ...@@ -767,11 +767,8 @@ void ipoib_mcast_dev_flush(struct net_device *dev)
} }
} }
static int ipoib_mcast_addr_is_valid(const u8 *addr, unsigned int addrlen, static int ipoib_mcast_addr_is_valid(const u8 *addr, const u8 *broadcast)
const u8 *broadcast)
{ {
if (addrlen != INFINIBAND_ALEN)
return 0;
/* reserved QPN, prefix, scope */ /* reserved QPN, prefix, scope */
if (memcmp(addr, broadcast, 6)) if (memcmp(addr, broadcast, 6))
return 0; return 0;
...@@ -811,11 +808,10 @@ void ipoib_mcast_restart_task(struct work_struct *work) ...@@ -811,11 +808,10 @@ void ipoib_mcast_restart_task(struct work_struct *work)
clear_bit(IPOIB_MCAST_FLAG_FOUND, &mcast->flags); clear_bit(IPOIB_MCAST_FLAG_FOUND, &mcast->flags);
/* Mark all of the entries that are found or don't exist */ /* Mark all of the entries that are found or don't exist */
for (mclist = dev->mc_list; mclist; mclist = mclist->next) { netdev_for_each_mc_addr(mclist, dev) {
union ib_gid mgid; union ib_gid mgid;
if (!ipoib_mcast_addr_is_valid(mclist->dmi_addr, if (!ipoib_mcast_addr_is_valid(mclist->dmi_addr,
mclist->dmi_addrlen,
dev->broadcast)) dev->broadcast))
continue; continue;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment