aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/qlcnic/qlcnic.h20
-rw-r--r--drivers/net/qlcnic/qlcnic_hw.c48
-rw-r--r--drivers/net/qlcnic/qlcnic_main.c123
3 files changed, 191 insertions, 0 deletions
diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index cd1a2e6f59d2..4727204a2450 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -926,6 +926,21 @@ struct qlcnic_mac_req {
926#define QLCNIC_INTERRUPT_TEST 1 926#define QLCNIC_INTERRUPT_TEST 1
927#define QLCNIC_LOOPBACK_TEST 2 927#define QLCNIC_LOOPBACK_TEST 2
928 928
929#define QLCNIC_FILTER_AGE 80
930#define QLCNIC_LB_MAX_FILTERS 64
931
932struct qlcnic_filter {
933 struct hlist_node fnode;
934 u8 faddr[ETH_ALEN];
935 unsigned long ftime;
936};
937
938struct qlcnic_filter_hash {
939 struct hlist_head *fhead;
940 u8 fnum;
941 u8 fmax;
942};
943
929struct qlcnic_adapter { 944struct qlcnic_adapter {
930 struct qlcnic_hardware_context ahw; 945 struct qlcnic_hardware_context ahw;
931 946
@@ -934,6 +949,7 @@ struct qlcnic_adapter {
934 struct list_head mac_list; 949 struct list_head mac_list;
935 950
936 spinlock_t tx_clean_lock; 951 spinlock_t tx_clean_lock;
952 spinlock_t mac_learn_lock;
937 953
938 u16 num_txd; 954 u16 num_txd;
939 u16 num_rxd; 955 u16 num_rxd;
@@ -1013,6 +1029,8 @@ struct qlcnic_adapter {
1013 1029
1014 struct qlcnic_nic_intr_coalesce coal; 1030 struct qlcnic_nic_intr_coalesce coal;
1015 1031
1032 struct qlcnic_filter_hash fhash;
1033
1016 unsigned long state; 1034 unsigned long state;
1017 __le32 file_prd_off; /*File fw product offset*/ 1035 __le32 file_prd_off; /*File fw product offset*/
1018 u32 fw_version; 1036 u32 fw_version;
@@ -1211,6 +1229,8 @@ void qlcnic_pcie_sem_unlock(struct qlcnic_adapter *, int);
1211int qlcnic_get_board_info(struct qlcnic_adapter *adapter); 1229int qlcnic_get_board_info(struct qlcnic_adapter *adapter);
1212int qlcnic_wol_supported(struct qlcnic_adapter *adapter); 1230int qlcnic_wol_supported(struct qlcnic_adapter *adapter);
1213int qlcnic_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate); 1231int qlcnic_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate);
1232void qlcnic_prune_lb_filters(struct qlcnic_adapter *adapter);
1233void qlcnic_delete_lb_filters(struct qlcnic_adapter *adapter);
1214 1234
1215/* Functions from qlcnic_init.c */ 1235/* Functions from qlcnic_init.c */
1216int qlcnic_load_firmware(struct qlcnic_adapter *adapter); 1236int qlcnic_load_firmware(struct qlcnic_adapter *adapter);
diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/qlcnic/qlcnic_hw.c
index 670a54a84ba6..5b2bce59498d 100644
--- a/drivers/net/qlcnic/qlcnic_hw.c
+++ b/drivers/net/qlcnic/qlcnic_hw.c
@@ -491,6 +491,54 @@ void qlcnic_free_mac_list(struct qlcnic_adapter *adapter)
491 } 491 }
492} 492}
493 493
494void qlcnic_prune_lb_filters(struct qlcnic_adapter *adapter)
495{
496 struct qlcnic_filter *tmp_fil;
497 struct hlist_node *tmp_hnode, *n;
498 struct hlist_head *head;
499 int i;
500
501 for (i = 0; i < adapter->fhash.fmax; i++) {
502 head = &(adapter->fhash.fhead[i]);
503
504 hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode)
505 {
506 if (jiffies >
507 (QLCNIC_FILTER_AGE * HZ + tmp_fil->ftime)) {
508 qlcnic_sre_macaddr_change(adapter,
509 tmp_fil->faddr, QLCNIC_MAC_DEL);
510 spin_lock_bh(&adapter->mac_learn_lock);
511 adapter->fhash.fnum--;
512 hlist_del(&tmp_fil->fnode);
513 spin_unlock_bh(&adapter->mac_learn_lock);
514 kfree(tmp_fil);
515 }
516 }
517 }
518}
519
520void qlcnic_delete_lb_filters(struct qlcnic_adapter *adapter)
521{
522 struct qlcnic_filter *tmp_fil;
523 struct hlist_node *tmp_hnode, *n;
524 struct hlist_head *head;
525 int i;
526
527 for (i = 0; i < adapter->fhash.fmax; i++) {
528 head = &(adapter->fhash.fhead[i]);
529
530 hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode) {
531 qlcnic_sre_macaddr_change(adapter,
532 tmp_fil->faddr, QLCNIC_MAC_DEL);
533 spin_lock_bh(&adapter->mac_learn_lock);
534 adapter->fhash.fnum--;
535 hlist_del(&tmp_fil->fnode);
536 spin_unlock_bh(&adapter->mac_learn_lock);
537 kfree(tmp_fil);
538 }
539 }
540}
541
494#define QLCNIC_CONFIG_INTR_COALESCE 3 542#define QLCNIC_CONFIG_INTR_COALESCE 3
495 543
496/* 544/*
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 130f4dbe2f4b..0fbfb53f2594 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -50,6 +50,10 @@ static int port_mode = QLCNIC_PORT_MODE_AUTO_NEG;
50/* Default to restricted 1G auto-neg mode */ 50/* Default to restricted 1G auto-neg mode */
51static int wol_port_mode = 5; 51static int wol_port_mode = 5;
52 52
53static int qlcnic_mac_learn;
54module_param(qlcnic_mac_learn, int, 0644);
55MODULE_PARM_DESC(qlcnic_mac_learn, "Mac Filter (0=disabled, 1=enabled)");
56
53static int use_msi = 1; 57static int use_msi = 1;
54module_param(use_msi, int, 0644); 58module_param(use_msi, int, 0644);
55MODULE_PARM_DESC(use_msi, "MSI interrupt (0=disabled, 1=enabled"); 59MODULE_PARM_DESC(use_msi, "MSI interrupt (0=disabled, 1=enabled");
@@ -106,6 +110,8 @@ static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev);
106static void qlcnic_config_indev_addr(struct net_device *dev, unsigned long); 110static void qlcnic_config_indev_addr(struct net_device *dev, unsigned long);
107static int qlcnic_start_firmware(struct qlcnic_adapter *); 111static int qlcnic_start_firmware(struct qlcnic_adapter *);
108 112
113static void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter);
114static void qlcnic_free_lb_filters_mem(struct qlcnic_adapter *adapter);
109static void qlcnic_dev_set_npar_ready(struct qlcnic_adapter *); 115static void qlcnic_dev_set_npar_ready(struct qlcnic_adapter *);
110static int qlcnicvf_config_led(struct qlcnic_adapter *, u32, u32); 116static int qlcnicvf_config_led(struct qlcnic_adapter *, u32, u32);
111static int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *, u32); 117static int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *, u32);
@@ -1201,6 +1207,9 @@ __qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev)
1201 1207
1202 qlcnic_free_mac_list(adapter); 1208 qlcnic_free_mac_list(adapter);
1203 1209
1210 if (adapter->fhash.fnum)
1211 qlcnic_delete_lb_filters(adapter);
1212
1204 qlcnic_nic_set_promisc(adapter, QLCNIC_NIU_NON_PROMISC_MODE); 1213 qlcnic_nic_set_promisc(adapter, QLCNIC_NIU_NON_PROMISC_MODE);
1205 1214
1206 qlcnic_napi_disable(adapter); 1215 qlcnic_napi_disable(adapter);
@@ -1596,6 +1605,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
1596 break; 1605 break;
1597 } 1606 }
1598 1607
1608 qlcnic_alloc_lb_filters_mem(adapter);
1599 qlcnic_create_diag_entries(adapter); 1609 qlcnic_create_diag_entries(adapter);
1600 1610
1601 return 0; 1611 return 0;
@@ -1647,6 +1657,8 @@ static void __devexit qlcnic_remove(struct pci_dev *pdev)
1647 1657
1648 clear_bit(__QLCNIC_RESETTING, &adapter->state); 1658 clear_bit(__QLCNIC_RESETTING, &adapter->state);
1649 1659
1660 qlcnic_free_lb_filters_mem(adapter);
1661
1650 qlcnic_teardown_intr(adapter); 1662 qlcnic_teardown_intr(adapter);
1651 1663
1652 qlcnic_remove_diag_entries(adapter); 1664 qlcnic_remove_diag_entries(adapter);
@@ -1782,6 +1794,111 @@ static int qlcnic_close(struct net_device *netdev)
1782} 1794}
1783 1795
1784static void 1796static void
1797qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter)
1798{
1799 void *head;
1800 int i;
1801
1802 if (!qlcnic_mac_learn)
1803 return;
1804
1805 spin_lock_init(&adapter->mac_learn_lock);
1806
1807 head = kcalloc(QLCNIC_LB_MAX_FILTERS, sizeof(struct hlist_head),
1808 GFP_KERNEL);
1809 if (!head)
1810 return;
1811
1812 adapter->fhash.fmax = QLCNIC_LB_MAX_FILTERS;
1813 adapter->fhash.fhead = (struct hlist_head *)head;
1814
1815 for (i = 0; i < adapter->fhash.fmax; i++)
1816 INIT_HLIST_HEAD(&adapter->fhash.fhead[i]);
1817}
1818
1819static void qlcnic_free_lb_filters_mem(struct qlcnic_adapter *adapter)
1820{
1821 if (adapter->fhash.fmax && adapter->fhash.fhead)
1822 kfree(adapter->fhash.fhead);
1823
1824 adapter->fhash.fhead = NULL;
1825 adapter->fhash.fmax = 0;
1826}
1827
1828static void qlcnic_change_filter(struct qlcnic_adapter *adapter,
1829 u64 uaddr, struct qlcnic_host_tx_ring *tx_ring)
1830{
1831 struct cmd_desc_type0 *hwdesc;
1832 struct qlcnic_nic_req *req;
1833 struct qlcnic_mac_req *mac_req;
1834 u32 producer;
1835 u64 word;
1836
1837 producer = tx_ring->producer;
1838 hwdesc = &tx_ring->desc_head[tx_ring->producer];
1839
1840 req = (struct qlcnic_nic_req *)hwdesc;
1841 memset(req, 0, sizeof(struct qlcnic_nic_req));
1842 req->qhdr = cpu_to_le64(QLCNIC_REQUEST << 23);
1843
1844 word = QLCNIC_MAC_EVENT | ((u64)(adapter->portnum) << 16);
1845 req->req_hdr = cpu_to_le64(word);
1846
1847 mac_req = (struct qlcnic_mac_req *)&(req->words[0]);
1848 mac_req->op = QLCNIC_MAC_ADD;
1849 memcpy(mac_req->mac_addr, &uaddr, ETH_ALEN);
1850
1851 tx_ring->producer = get_next_index(producer, tx_ring->num_desc);
1852}
1853
1854#define QLCNIC_MAC_HASH(MAC)\
1855 ((((MAC) & 0x70000) >> 0x10) | (((MAC) & 0x70000000000ULL) >> 0x25))
1856
1857static void
1858qlcnic_send_filter(struct qlcnic_adapter *adapter,
1859 struct qlcnic_host_tx_ring *tx_ring,
1860 struct cmd_desc_type0 *first_desc,
1861 struct sk_buff *skb)
1862{
1863 struct ethhdr *phdr = (struct ethhdr *)(skb->data);
1864 struct qlcnic_filter *fil, *tmp_fil;
1865 struct hlist_node *tmp_hnode, *n;
1866 struct hlist_head *head;
1867 u64 src_addr = 0;
1868 u8 hindex;
1869
1870 if (!compare_ether_addr(phdr->h_source, adapter->mac_addr))
1871 return;
1872
1873 if (adapter->fhash.fnum >= adapter->fhash.fmax)
1874 return;
1875
1876 memcpy(&src_addr, phdr->h_source, ETH_ALEN);
1877 hindex = QLCNIC_MAC_HASH(src_addr) & (QLCNIC_LB_MAX_FILTERS - 1);
1878 head = &(adapter->fhash.fhead[hindex]);
1879
1880 hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode) {
1881 if (!memcmp(tmp_fil->faddr, &src_addr, ETH_ALEN)) {
1882 tmp_fil->ftime = jiffies;
1883 return;
1884 }
1885 }
1886
1887 fil = kzalloc(sizeof(struct qlcnic_filter), GFP_ATOMIC);
1888 if (!fil)
1889 return;
1890
1891 qlcnic_change_filter(adapter, src_addr, tx_ring);
1892
1893 fil->ftime = jiffies;
1894 memcpy(fil->faddr, &src_addr, ETH_ALEN);
1895 spin_lock(&adapter->mac_learn_lock);
1896 hlist_add_head(&(fil->fnode), head);
1897 adapter->fhash.fnum++;
1898 spin_unlock(&adapter->mac_learn_lock);
1899}
1900
1901static void
1785qlcnic_tso_check(struct net_device *netdev, 1902qlcnic_tso_check(struct net_device *netdev,
1786 struct qlcnic_host_tx_ring *tx_ring, 1903 struct qlcnic_host_tx_ring *tx_ring,
1787 struct cmd_desc_type0 *first_desc, 1904 struct cmd_desc_type0 *first_desc,
@@ -2090,6 +2207,9 @@ qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
2090 2207
2091 qlcnic_tso_check(netdev, tx_ring, first_desc, skb); 2208 qlcnic_tso_check(netdev, tx_ring, first_desc, skb);
2092 2209
2210 if (qlcnic_mac_learn)
2211 qlcnic_send_filter(adapter, tx_ring, first_desc, skb);
2212
2093 qlcnic_update_cmd_producer(adapter, tx_ring); 2213 qlcnic_update_cmd_producer(adapter, tx_ring);
2094 2214
2095 adapter->stats.txbytes += skb->len; 2215 adapter->stats.txbytes += skb->len;
@@ -2900,6 +3020,9 @@ qlcnic_fw_poll_work(struct work_struct *work)
2900 if (qlcnic_check_health(adapter)) 3020 if (qlcnic_check_health(adapter))
2901 return; 3021 return;
2902 3022
3023 if (adapter->fhash.fnum)
3024 qlcnic_prune_lb_filters(adapter);
3025
2903reschedule: 3026reschedule:
2904 qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, FW_POLL_DELAY); 3027 qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, FW_POLL_DELAY);
2905} 3028}