aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic.h1
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c2
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c1
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c8
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c3
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c80
6 files changed, 64 insertions, 31 deletions
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index 8d7aa4ceac90..a68b145b3451 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -1079,6 +1079,7 @@ struct qlcnic_adapter {
1079 u64 dev_rst_time; 1079 u64 dev_rst_time;
1080 bool drv_mac_learn; 1080 bool drv_mac_learn;
1081 bool fdb_mac_learn; 1081 bool fdb_mac_learn;
1082 u8 rx_mac_learn;
1082 unsigned long vlans[BITS_TO_LONGS(VLAN_N_VID)]; 1083 unsigned long vlans[BITS_TO_LONGS(VLAN_N_VID)];
1083 u8 flash_mfg_id; 1084 u8 flash_mfg_id;
1084 struct qlcnic_npar_info *npars; 1085 struct qlcnic_npar_info *npars;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
index ca221601e4a2..03f70e8940b3 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
@@ -1591,7 +1591,9 @@ static void qlcnic_83xx_set_interface_id_promisc(struct qlcnic_adapter *adapter,
1591 u32 *interface_id) 1591 u32 *interface_id)
1592{ 1592{
1593 if (qlcnic_sriov_pf_check(adapter)) { 1593 if (qlcnic_sriov_pf_check(adapter)) {
1594 qlcnic_alloc_lb_filters_mem(adapter);
1594 qlcnic_pf_set_interface_id_promisc(adapter, interface_id); 1595 qlcnic_pf_set_interface_id_promisc(adapter, interface_id);
1596 adapter->rx_mac_learn = 1;
1595 } else { 1597 } else {
1596 if (!qlcnic_sriov_vf_check(adapter)) 1598 if (!qlcnic_sriov_vf_check(adapter))
1597 *interface_id = adapter->recv_ctx->context_id << 16; 1599 *interface_id = adapter->recv_ctx->context_id << 16;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
index 22ae884728b8..abe3924c61c5 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
@@ -2214,6 +2214,7 @@ int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac)
2214 struct qlcnic_hardware_context *ahw = adapter->ahw; 2214 struct qlcnic_hardware_context *ahw = adapter->ahw;
2215 int err = 0; 2215 int err = 0;
2216 2216
2217 adapter->rx_mac_learn = 0;
2217 ahw->msix_supported = !!qlcnic_use_msi_x; 2218 ahw->msix_supported = !!qlcnic_use_msi_x;
2218 2219
2219 qlcnic_83xx_init_rings(adapter); 2220 qlcnic_83xx_init_rings(adapter);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c
index 474320a5f0c1..23c4fd10e505 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c
@@ -224,10 +224,14 @@ int qlcnic_83xx_config_vnic_opmode(struct qlcnic_adapter *adapter)
224 return -EIO; 224 return -EIO;
225 } 225 }
226 226
227 if (ahw->capabilities & QLC_83XX_ESWITCH_CAPABILITY) 227 if (ahw->capabilities & QLC_83XX_ESWITCH_CAPABILITY) {
228 adapter->flags |= QLCNIC_ESWITCH_ENABLED; 228 adapter->flags |= QLCNIC_ESWITCH_ENABLED;
229 else 229 if (adapter->drv_mac_learn)
230 adapter->rx_mac_learn = 1;
231 } else {
230 adapter->flags &= ~QLCNIC_ESWITCH_ENABLED; 232 adapter->flags &= ~QLCNIC_ESWITCH_ENABLED;
233 adapter->rx_mac_learn = 0;
234 }
231 235
232 ahw->idc.vnic_state = QLCNIC_DEV_NPAR_NON_OPER; 236 ahw->idc.vnic_state = QLCNIC_DEV_NPAR_NON_OPER;
233 ahw->idc.vnic_wait_limit = QLCNIC_DEV_NPAR_OPER_TIMEO; 237 ahw->idc.vnic_wait_limit = QLCNIC_DEV_NPAR_OPER_TIMEO;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
index a9a149b82375..18cc365bc7ea 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
@@ -546,8 +546,11 @@ void __qlcnic_set_multi(struct net_device *netdev, u16 vlan)
546 !adapter->fdb_mac_learn) { 546 !adapter->fdb_mac_learn) {
547 qlcnic_alloc_lb_filters_mem(adapter); 547 qlcnic_alloc_lb_filters_mem(adapter);
548 adapter->drv_mac_learn = 1; 548 adapter->drv_mac_learn = 1;
549 if (adapter->flags & QLCNIC_ESWITCH_ENABLED)
550 adapter->rx_mac_learn = 1;
549 } else { 551 } else {
550 adapter->drv_mac_learn = 0; 552 adapter->drv_mac_learn = 0;
553 adapter->rx_mac_learn = 0;
551 } 554 }
552 555
553 qlcnic_nic_set_promisc(adapter, mode); 556 qlcnic_nic_set_promisc(adapter, mode);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
index 6373f6022486..cbe4a30abd79 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
@@ -156,9 +156,9 @@ static inline void qlcnic_83xx_disable_tx_intr(struct qlcnic_adapter *adapter,
156 writel(1, tx_ring->crb_intr_mask); 156 writel(1, tx_ring->crb_intr_mask);
157} 157}
158 158
159static inline u8 qlcnic_mac_hash(u64 mac) 159static inline u8 qlcnic_mac_hash(u64 mac, u16 vlan)
160{ 160{
161 return (u8)((mac & 0xff) ^ ((mac >> 40) & 0xff)); 161 return (u8)((mac & 0xff) ^ ((mac >> 40) & 0xff) ^ (vlan & 0xff));
162} 162}
163 163
164static inline u32 qlcnic_get_ref_handle(struct qlcnic_adapter *adapter, 164static inline u32 qlcnic_get_ref_handle(struct qlcnic_adapter *adapter,
@@ -221,8 +221,11 @@ void qlcnic_add_lb_filter(struct qlcnic_adapter *adapter, struct sk_buff *skb,
221 u8 hindex, op; 221 u8 hindex, op;
222 int ret; 222 int ret;
223 223
224 if (!qlcnic_sriov_pf_check(adapter) || (vlan_id == 0xffff))
225 vlan_id = 0;
226
224 memcpy(&src_addr, phdr->h_source, ETH_ALEN); 227 memcpy(&src_addr, phdr->h_source, ETH_ALEN);
225 hindex = qlcnic_mac_hash(src_addr) & 228 hindex = qlcnic_mac_hash(src_addr, vlan_id) &
226 (adapter->fhash.fbucket_size - 1); 229 (adapter->fhash.fbucket_size - 1);
227 230
228 if (loopback_pkt) { 231 if (loopback_pkt) {
@@ -322,27 +325,43 @@ static void qlcnic_send_filter(struct qlcnic_adapter *adapter,
322 struct cmd_desc_type0 *first_desc, 325 struct cmd_desc_type0 *first_desc,
323 struct sk_buff *skb) 326 struct sk_buff *skb)
324{ 327{
328 struct vlan_ethhdr *vh = (struct vlan_ethhdr *)(skb->data);
329 struct ethhdr *phdr = (struct ethhdr *)(skb->data);
330 struct net_device *netdev = adapter->netdev;
331 u16 protocol = ntohs(skb->protocol);
325 struct qlcnic_filter *fil, *tmp_fil; 332 struct qlcnic_filter *fil, *tmp_fil;
326 struct hlist_node *n;
327 struct hlist_head *head; 333 struct hlist_head *head;
328 struct net_device *netdev = adapter->netdev; 334 struct hlist_node *n;
329 struct ethhdr *phdr = (struct ethhdr *)(skb->data);
330 u64 src_addr = 0; 335 u64 src_addr = 0;
331 u16 vlan_id = 0; 336 u16 vlan_id = 0;
332 u8 hindex; 337 u8 hindex, hval;
333 338
334 if (ether_addr_equal(phdr->h_source, adapter->mac_addr)) 339 if (!qlcnic_sriov_pf_check(adapter)) {
335 return; 340 if (ether_addr_equal(phdr->h_source, adapter->mac_addr))
341 return;
342 } else {
343 if (protocol == ETH_P_8021Q) {
344 vh = (struct vlan_ethhdr *)skb->data;
345 vlan_id = ntohs(vh->h_vlan_TCI);
346 } else if (vlan_tx_tag_present(skb)) {
347 vlan_id = vlan_tx_tag_get(skb);
348 }
349
350 if (ether_addr_equal(phdr->h_source, adapter->mac_addr) &&
351 !vlan_id)
352 return;
353 }
336 354
337 if (adapter->fhash.fnum >= adapter->fhash.fmax) { 355 if (adapter->fhash.fnum >= adapter->fhash.fmax) {
338 adapter->stats.mac_filter_limit_overrun++; 356 adapter->stats.mac_filter_limit_overrun++;
339 netdev_info(netdev, "Can not add more than %d mac addresses\n", 357 netdev_info(netdev, "Can not add more than %d mac-vlan filters, configured %d\n",
340 adapter->fhash.fmax); 358 adapter->fhash.fmax, adapter->fhash.fnum);
341 return; 359 return;
342 } 360 }
343 361
344 memcpy(&src_addr, phdr->h_source, ETH_ALEN); 362 memcpy(&src_addr, phdr->h_source, ETH_ALEN);
345 hindex = qlcnic_mac_hash(src_addr) & (adapter->fhash.fbucket_size - 1); 363 hval = qlcnic_mac_hash(src_addr, vlan_id);
364 hindex = hval & (adapter->fhash.fbucket_size - 1);
346 head = &(adapter->fhash.fhead[hindex]); 365 head = &(adapter->fhash.fhead[hindex]);
347 366
348 hlist_for_each_entry_safe(tmp_fil, n, head, fnode) { 367 hlist_for_each_entry_safe(tmp_fil, n, head, fnode) {
@@ -1599,7 +1618,8 @@ qlcnic_83xx_process_rcv(struct qlcnic_adapter *adapter,
1599 struct sk_buff *skb; 1618 struct sk_buff *skb;
1600 struct qlcnic_host_rds_ring *rds_ring; 1619 struct qlcnic_host_rds_ring *rds_ring;
1601 int index, length, cksum, is_lb_pkt; 1620 int index, length, cksum, is_lb_pkt;
1602 u16 vid = 0xffff, t_vid; 1621 u16 vid = 0xffff;
1622 int err;
1603 1623
1604 if (unlikely(ring >= adapter->max_rds_rings)) 1624 if (unlikely(ring >= adapter->max_rds_rings))
1605 return NULL; 1625 return NULL;
@@ -1617,19 +1637,19 @@ qlcnic_83xx_process_rcv(struct qlcnic_adapter *adapter,
1617 if (!skb) 1637 if (!skb)
1618 return buffer; 1638 return buffer;
1619 1639
1620 if (adapter->drv_mac_learn &&
1621 (adapter->flags & QLCNIC_ESWITCH_ENABLED)) {
1622 t_vid = 0;
1623 is_lb_pkt = qlcnic_83xx_is_lb_pkt(sts_data[1], 0);
1624 qlcnic_add_lb_filter(adapter, skb, is_lb_pkt, t_vid);
1625 }
1626
1627 if (length > rds_ring->skb_size) 1640 if (length > rds_ring->skb_size)
1628 skb_put(skb, rds_ring->skb_size); 1641 skb_put(skb, rds_ring->skb_size);
1629 else 1642 else
1630 skb_put(skb, length); 1643 skb_put(skb, length);
1631 1644
1632 if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) { 1645 err = qlcnic_check_rx_tagging(adapter, skb, &vid);
1646
1647 if (adapter->rx_mac_learn) {
1648 is_lb_pkt = qlcnic_83xx_is_lb_pkt(sts_data[1], 0);
1649 qlcnic_add_lb_filter(adapter, skb, is_lb_pkt, vid);
1650 }
1651
1652 if (unlikely(err)) {
1633 adapter->stats.rxdropped++; 1653 adapter->stats.rxdropped++;
1634 dev_kfree_skb(skb); 1654 dev_kfree_skb(skb);
1635 return buffer; 1655 return buffer;
@@ -1664,7 +1684,8 @@ qlcnic_83xx_process_lro(struct qlcnic_adapter *adapter,
1664 int l2_hdr_offset, l4_hdr_offset; 1684 int l2_hdr_offset, l4_hdr_offset;
1665 int index, is_lb_pkt; 1685 int index, is_lb_pkt;
1666 u16 lro_length, length, data_offset, gso_size; 1686 u16 lro_length, length, data_offset, gso_size;
1667 u16 vid = 0xffff, t_vid; 1687 u16 vid = 0xffff;
1688 int err;
1668 1689
1669 if (unlikely(ring > adapter->max_rds_rings)) 1690 if (unlikely(ring > adapter->max_rds_rings))
1670 return NULL; 1691 return NULL;
@@ -1686,12 +1707,6 @@ qlcnic_83xx_process_lro(struct qlcnic_adapter *adapter,
1686 if (!skb) 1707 if (!skb)
1687 return buffer; 1708 return buffer;
1688 1709
1689 if (adapter->drv_mac_learn &&
1690 (adapter->flags & QLCNIC_ESWITCH_ENABLED)) {
1691 t_vid = 0;
1692 is_lb_pkt = qlcnic_83xx_is_lb_pkt(sts_data[1], 1);
1693 qlcnic_add_lb_filter(adapter, skb, is_lb_pkt, t_vid);
1694 }
1695 if (qlcnic_83xx_is_tstamp(sts_data[1])) 1710 if (qlcnic_83xx_is_tstamp(sts_data[1]))
1696 data_offset = l4_hdr_offset + QLCNIC_TCP_TS_HDR_SIZE; 1711 data_offset = l4_hdr_offset + QLCNIC_TCP_TS_HDR_SIZE;
1697 else 1712 else
@@ -1700,7 +1715,14 @@ qlcnic_83xx_process_lro(struct qlcnic_adapter *adapter,
1700 skb_put(skb, lro_length + data_offset); 1715 skb_put(skb, lro_length + data_offset);
1701 skb_pull(skb, l2_hdr_offset); 1716 skb_pull(skb, l2_hdr_offset);
1702 1717
1703 if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) { 1718 err = qlcnic_check_rx_tagging(adapter, skb, &vid);
1719
1720 if (adapter->rx_mac_learn) {
1721 is_lb_pkt = qlcnic_83xx_is_lb_pkt(sts_data[1], 1);
1722 qlcnic_add_lb_filter(adapter, skb, is_lb_pkt, vid);
1723 }
1724
1725 if (unlikely(err)) {
1704 adapter->stats.rxdropped++; 1726 adapter->stats.rxdropped++;
1705 dev_kfree_skb(skb); 1727 dev_kfree_skb(skb);
1706 return buffer; 1728 return buffer;