aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/qlcnic/qlcnic_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/qlcnic/qlcnic_main.c')
-rw-r--r--drivers/net/qlcnic/qlcnic_main.c123
1 files changed, 123 insertions, 0 deletions
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}