diff options
Diffstat (limited to 'drivers/net/qlcnic')
-rw-r--r-- | drivers/net/qlcnic/qlcnic.h | 4 | ||||
-rw-r--r-- | drivers/net/qlcnic/qlcnic_init.c | 39 | ||||
-rw-r--r-- | drivers/net/qlcnic/qlcnic_main.c | 89 |
3 files changed, 111 insertions, 21 deletions
diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h index 508d531a55e5..d15de63ed0bb 100644 --- a/drivers/net/qlcnic/qlcnic.h +++ b/drivers/net/qlcnic/qlcnic.h | |||
@@ -175,7 +175,7 @@ | |||
175 | ((_desc)->port_ctxid = ((_port) & 0xf) | (((_port) << 4) & 0xf0)) | 175 | ((_desc)->port_ctxid = ((_port) & 0xf) | (((_port) << 4) & 0xf0)) |
176 | 176 | ||
177 | #define qlcnic_set_tx_flags_opcode(_desc, _flags, _opcode) \ | 177 | #define qlcnic_set_tx_flags_opcode(_desc, _flags, _opcode) \ |
178 | ((_desc)->flags_opcode = \ | 178 | ((_desc)->flags_opcode |= \ |
179 | cpu_to_le16(((_flags) & 0x7f) | (((_opcode) & 0x3f) << 7))) | 179 | cpu_to_le16(((_flags) & 0x7f) | (((_opcode) & 0x3f) << 7))) |
180 | 180 | ||
181 | #define qlcnic_set_tx_frags_len(_desc, _frags, _len) \ | 181 | #define qlcnic_set_tx_frags_len(_desc, _frags, _len) \ |
@@ -902,6 +902,7 @@ struct qlcnic_mac_req { | |||
902 | #define QLCNIC_BRIDGE_ENABLED 0X10 | 902 | #define QLCNIC_BRIDGE_ENABLED 0X10 |
903 | #define QLCNIC_DIAG_ENABLED 0x20 | 903 | #define QLCNIC_DIAG_ENABLED 0x20 |
904 | #define QLCNIC_ESWITCH_ENABLED 0x40 | 904 | #define QLCNIC_ESWITCH_ENABLED 0x40 |
905 | #define QLCNIC_TAGGING_ENABLED 0x100 | ||
905 | #define QLCNIC_MACSPOOF 0x200 | 906 | #define QLCNIC_MACSPOOF 0x200 |
906 | #define QLCNIC_IS_MSI_FAMILY(adapter) \ | 907 | #define QLCNIC_IS_MSI_FAMILY(adapter) \ |
907 | ((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED)) | 908 | ((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED)) |
@@ -967,6 +968,7 @@ struct qlcnic_adapter { | |||
967 | u16 max_tx_ques; | 968 | u16 max_tx_ques; |
968 | u16 max_rx_ques; | 969 | u16 max_rx_ques; |
969 | u16 max_mtu; | 970 | u16 max_mtu; |
971 | u16 pvid; | ||
970 | 972 | ||
971 | u32 fw_hal_version; | 973 | u32 fw_hal_version; |
972 | u32 capabilities; | 974 | u32 capabilities; |
diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c index a174521daa63..df91b754bb70 100644 --- a/drivers/net/qlcnic/qlcnic_init.c +++ b/drivers/net/qlcnic/qlcnic_init.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/netdevice.h> | 25 | #include <linux/netdevice.h> |
26 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/if_vlan.h> | ||
28 | #include "qlcnic.h" | 29 | #include "qlcnic.h" |
29 | 30 | ||
30 | struct crb_addr_pair { | 31 | struct crb_addr_pair { |
@@ -1302,6 +1303,27 @@ static struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *adapter, | |||
1302 | return skb; | 1303 | return skb; |
1303 | } | 1304 | } |
1304 | 1305 | ||
1306 | static int | ||
1307 | qlcnic_check_rx_tagging(struct qlcnic_adapter *adapter, struct sk_buff *skb) | ||
1308 | { | ||
1309 | u16 vlan_tag; | ||
1310 | struct ethhdr *eth_hdr; | ||
1311 | |||
1312 | if (!__vlan_get_tag(skb, &vlan_tag)) { | ||
1313 | if (vlan_tag == adapter->pvid) { | ||
1314 | /* strip the tag from the packet and send it up */ | ||
1315 | eth_hdr = (struct ethhdr *) skb->data; | ||
1316 | memmove(skb->data + VLAN_HLEN, eth_hdr, ETH_ALEN * 2); | ||
1317 | skb_pull(skb, VLAN_HLEN); | ||
1318 | return 0; | ||
1319 | } | ||
1320 | } | ||
1321 | if (adapter->flags & QLCNIC_TAGGING_ENABLED) | ||
1322 | return 0; | ||
1323 | |||
1324 | return -EIO; | ||
1325 | } | ||
1326 | |||
1305 | static struct qlcnic_rx_buffer * | 1327 | static struct qlcnic_rx_buffer * |
1306 | qlcnic_process_rcv(struct qlcnic_adapter *adapter, | 1328 | qlcnic_process_rcv(struct qlcnic_adapter *adapter, |
1307 | struct qlcnic_host_sds_ring *sds_ring, | 1329 | struct qlcnic_host_sds_ring *sds_ring, |
@@ -1342,6 +1364,15 @@ qlcnic_process_rcv(struct qlcnic_adapter *adapter, | |||
1342 | skb_pull(skb, pkt_offset); | 1364 | skb_pull(skb, pkt_offset); |
1343 | 1365 | ||
1344 | skb->truesize = skb->len + sizeof(struct sk_buff); | 1366 | skb->truesize = skb->len + sizeof(struct sk_buff); |
1367 | |||
1368 | if (unlikely(adapter->pvid)) { | ||
1369 | if (qlcnic_check_rx_tagging(adapter, skb)) { | ||
1370 | adapter->stats.rxdropped++; | ||
1371 | dev_kfree_skb_any(skb); | ||
1372 | return buffer; | ||
1373 | } | ||
1374 | } | ||
1375 | |||
1345 | skb->protocol = eth_type_trans(skb, netdev); | 1376 | skb->protocol = eth_type_trans(skb, netdev); |
1346 | 1377 | ||
1347 | napi_gro_receive(&sds_ring->napi, skb); | 1378 | napi_gro_receive(&sds_ring->napi, skb); |
@@ -1406,6 +1437,14 @@ qlcnic_process_lro(struct qlcnic_adapter *adapter, | |||
1406 | skb->truesize = skb->len + sizeof(struct sk_buff) + skb_headroom(skb); | 1437 | skb->truesize = skb->len + sizeof(struct sk_buff) + skb_headroom(skb); |
1407 | 1438 | ||
1408 | skb_pull(skb, l2_hdr_offset); | 1439 | skb_pull(skb, l2_hdr_offset); |
1440 | |||
1441 | if (unlikely(adapter->pvid)) { | ||
1442 | if (qlcnic_check_rx_tagging(adapter, skb)) { | ||
1443 | adapter->stats.rxdropped++; | ||
1444 | dev_kfree_skb_any(skb); | ||
1445 | return buffer; | ||
1446 | } | ||
1447 | } | ||
1409 | skb->protocol = eth_type_trans(skb, netdev); | 1448 | skb->protocol = eth_type_trans(skb, netdev); |
1410 | 1449 | ||
1411 | iph = (struct iphdr *)skb->data; | 1450 | iph = (struct iphdr *)skb->data; |
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index 5d93b464681a..089212214ad4 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c | |||
@@ -759,6 +759,21 @@ qlcnic_check_options(struct qlcnic_adapter *adapter) | |||
759 | } | 759 | } |
760 | 760 | ||
761 | static void | 761 | static void |
762 | qlcnic_set_vlan_config(struct qlcnic_adapter *adapter, | ||
763 | struct qlcnic_esw_func_cfg *esw_cfg) | ||
764 | { | ||
765 | if (esw_cfg->discard_tagged) | ||
766 | adapter->flags &= ~QLCNIC_TAGGING_ENABLED; | ||
767 | else | ||
768 | adapter->flags |= QLCNIC_TAGGING_ENABLED; | ||
769 | |||
770 | if (esw_cfg->vlan_id) | ||
771 | adapter->pvid = esw_cfg->vlan_id; | ||
772 | else | ||
773 | adapter->pvid = 0; | ||
774 | } | ||
775 | |||
776 | static void | ||
762 | qlcnic_set_eswitch_port_features(struct qlcnic_adapter *adapter, | 777 | qlcnic_set_eswitch_port_features(struct qlcnic_adapter *adapter, |
763 | struct qlcnic_esw_func_cfg *esw_cfg) | 778 | struct qlcnic_esw_func_cfg *esw_cfg) |
764 | { | 779 | { |
@@ -781,6 +796,7 @@ qlcnic_set_eswitch_port_config(struct qlcnic_adapter *adapter) | |||
781 | esw_cfg.pci_func = adapter->ahw.pci_func; | 796 | esw_cfg.pci_func = adapter->ahw.pci_func; |
782 | if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg)) | 797 | if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg)) |
783 | return -EIO; | 798 | return -EIO; |
799 | qlcnic_set_vlan_config(adapter, &esw_cfg); | ||
784 | qlcnic_set_eswitch_port_features(adapter, &esw_cfg); | 800 | qlcnic_set_eswitch_port_features(adapter, &esw_cfg); |
785 | 801 | ||
786 | return 0; | 802 | return 0; |
@@ -1728,26 +1744,13 @@ qlcnic_tso_check(struct net_device *netdev, | |||
1728 | { | 1744 | { |
1729 | u8 opcode = TX_ETHER_PKT; | 1745 | u8 opcode = TX_ETHER_PKT; |
1730 | __be16 protocol = skb->protocol; | 1746 | __be16 protocol = skb->protocol; |
1731 | u16 flags = 0, vid = 0; | 1747 | u16 flags = 0; |
1732 | int copied, offset, copy_len, hdr_len = 0, tso = 0, vlan_oob = 0; | 1748 | int copied, offset, copy_len, hdr_len = 0, tso = 0; |
1733 | struct cmd_desc_type0 *hwdesc; | 1749 | struct cmd_desc_type0 *hwdesc; |
1734 | struct vlan_ethhdr *vh; | 1750 | struct vlan_ethhdr *vh; |
1735 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | 1751 | struct qlcnic_adapter *adapter = netdev_priv(netdev); |
1736 | u32 producer = tx_ring->producer; | 1752 | u32 producer = tx_ring->producer; |
1737 | 1753 | int vlan_oob = first_desc->flags_opcode & cpu_to_le16(FLAGS_VLAN_OOB); | |
1738 | if (protocol == cpu_to_be16(ETH_P_8021Q)) { | ||
1739 | |||
1740 | vh = (struct vlan_ethhdr *)skb->data; | ||
1741 | protocol = vh->h_vlan_encapsulated_proto; | ||
1742 | flags = FLAGS_VLAN_TAGGED; | ||
1743 | |||
1744 | } else if (vlan_tx_tag_present(skb)) { | ||
1745 | |||
1746 | flags = FLAGS_VLAN_OOB; | ||
1747 | vid = vlan_tx_tag_get(skb); | ||
1748 | qlcnic_set_tx_vlan_tci(first_desc, vid); | ||
1749 | vlan_oob = 1; | ||
1750 | } | ||
1751 | 1754 | ||
1752 | if (*(skb->data) & BIT_0) { | 1755 | if (*(skb->data) & BIT_0) { |
1753 | flags |= BIT_0; | 1756 | flags |= BIT_0; |
@@ -1818,7 +1821,7 @@ qlcnic_tso_check(struct net_device *netdev, | |||
1818 | vh = (struct vlan_ethhdr *)((char *)hwdesc + 2); | 1821 | vh = (struct vlan_ethhdr *)((char *)hwdesc + 2); |
1819 | skb_copy_from_linear_data(skb, vh, 12); | 1822 | skb_copy_from_linear_data(skb, vh, 12); |
1820 | vh->h_vlan_proto = htons(ETH_P_8021Q); | 1823 | vh->h_vlan_proto = htons(ETH_P_8021Q); |
1821 | vh->h_vlan_TCI = htons(vid); | 1824 | vh->h_vlan_TCI = htons(first_desc->vlan_TCI); |
1822 | skb_copy_from_linear_data_offset(skb, 12, | 1825 | skb_copy_from_linear_data_offset(skb, 12, |
1823 | (char *)vh + 16, copy_len - 16); | 1826 | (char *)vh + 16, copy_len - 16); |
1824 | 1827 | ||
@@ -1898,11 +1901,47 @@ out_err: | |||
1898 | return -ENOMEM; | 1901 | return -ENOMEM; |
1899 | } | 1902 | } |
1900 | 1903 | ||
1904 | static int | ||
1905 | qlcnic_check_tx_tagging(struct qlcnic_adapter *adapter, | ||
1906 | struct sk_buff *skb, | ||
1907 | struct cmd_desc_type0 *first_desc) | ||
1908 | { | ||
1909 | u8 opcode = 0; | ||
1910 | u16 flags = 0; | ||
1911 | __be16 protocol = skb->protocol; | ||
1912 | struct vlan_ethhdr *vh; | ||
1913 | |||
1914 | if (protocol == cpu_to_be16(ETH_P_8021Q)) { | ||
1915 | vh = (struct vlan_ethhdr *)skb->data; | ||
1916 | protocol = vh->h_vlan_encapsulated_proto; | ||
1917 | flags = FLAGS_VLAN_TAGGED; | ||
1918 | qlcnic_set_tx_vlan_tci(first_desc, ntohs(vh->h_vlan_TCI)); | ||
1919 | } else if (vlan_tx_tag_present(skb)) { | ||
1920 | flags = FLAGS_VLAN_OOB; | ||
1921 | qlcnic_set_tx_vlan_tci(first_desc, vlan_tx_tag_get(skb)); | ||
1922 | } | ||
1923 | if (unlikely(adapter->pvid)) { | ||
1924 | if (first_desc->vlan_TCI && | ||
1925 | !(adapter->flags & QLCNIC_TAGGING_ENABLED)) | ||
1926 | return -EIO; | ||
1927 | if (first_desc->vlan_TCI && | ||
1928 | (adapter->flags & QLCNIC_TAGGING_ENABLED)) | ||
1929 | goto set_flags; | ||
1930 | |||
1931 | flags = FLAGS_VLAN_OOB; | ||
1932 | qlcnic_set_tx_vlan_tci(first_desc, adapter->pvid); | ||
1933 | } | ||
1934 | set_flags: | ||
1935 | qlcnic_set_tx_flags_opcode(first_desc, flags, opcode); | ||
1936 | return 0; | ||
1937 | } | ||
1938 | |||
1901 | static inline void | 1939 | static inline void |
1902 | qlcnic_clear_cmddesc(u64 *desc) | 1940 | qlcnic_clear_cmddesc(u64 *desc) |
1903 | { | 1941 | { |
1904 | desc[0] = 0ULL; | 1942 | desc[0] = 0ULL; |
1905 | desc[2] = 0ULL; | 1943 | desc[2] = 0ULL; |
1944 | desc[7] = 0ULL; | ||
1906 | } | 1945 | } |
1907 | 1946 | ||
1908 | netdev_tx_t | 1947 | netdev_tx_t |
@@ -1952,6 +1991,12 @@ qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
1952 | 1991 | ||
1953 | pdev = adapter->pdev; | 1992 | pdev = adapter->pdev; |
1954 | 1993 | ||
1994 | first_desc = hwdesc = &tx_ring->desc_head[producer]; | ||
1995 | qlcnic_clear_cmddesc((u64 *)hwdesc); | ||
1996 | |||
1997 | if (qlcnic_check_tx_tagging(adapter, skb, first_desc)) | ||
1998 | goto drop_packet; | ||
1999 | |||
1955 | if (qlcnic_map_tx_skb(pdev, skb, pbuf)) { | 2000 | if (qlcnic_map_tx_skb(pdev, skb, pbuf)) { |
1956 | adapter->stats.tx_dma_map_error++; | 2001 | adapter->stats.tx_dma_map_error++; |
1957 | goto drop_packet; | 2002 | goto drop_packet; |
@@ -1960,9 +2005,6 @@ qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
1960 | pbuf->skb = skb; | 2005 | pbuf->skb = skb; |
1961 | pbuf->frag_count = frag_count; | 2006 | pbuf->frag_count = frag_count; |
1962 | 2007 | ||
1963 | first_desc = hwdesc = &tx_ring->desc_head[producer]; | ||
1964 | qlcnic_clear_cmddesc((u64 *)hwdesc); | ||
1965 | |||
1966 | qlcnic_set_tx_frags_len(first_desc, frag_count, skb->len); | 2008 | qlcnic_set_tx_frags_len(first_desc, frag_count, skb->len); |
1967 | qlcnic_set_tx_port(first_desc, adapter->portnum); | 2009 | qlcnic_set_tx_port(first_desc, adapter->portnum); |
1968 | 2010 | ||
@@ -3349,6 +3391,13 @@ qlcnic_sysfs_write_esw_config(struct file *file, struct kobject *kobj, | |||
3349 | case QLCNIC_PORT_DEFAULTS: | 3391 | case QLCNIC_PORT_DEFAULTS: |
3350 | qlcnic_set_eswitch_port_features(adapter, &esw_cfg[i]); | 3392 | qlcnic_set_eswitch_port_features(adapter, &esw_cfg[i]); |
3351 | break; | 3393 | break; |
3394 | case QLCNIC_ADD_VLAN: | ||
3395 | qlcnic_set_vlan_config(adapter, &esw_cfg[i]); | ||
3396 | break; | ||
3397 | case QLCNIC_DEL_VLAN: | ||
3398 | esw_cfg[i].vlan_id = 0; | ||
3399 | qlcnic_set_vlan_config(adapter, &esw_cfg[i]); | ||
3400 | break; | ||
3352 | } | 3401 | } |
3353 | } | 3402 | } |
3354 | 3403 | ||