diff options
author | Amit Kumar Salecha <amit.salecha@qlogic.com> | 2010-08-25 00:03:03 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-08-25 17:15:27 -0400 |
commit | 8cf61f890ac4c2a15acb24658feba13c9c838b52 (patch) | |
tree | 35a476615af3563c56b7ca3022b44fb194010944 /drivers/net/qlcnic/qlcnic_main.c | |
parent | e9a47700cb35bc84d4954f762a193b150722612e (diff) |
qlcnic: support port vlan id
On NIC Partition capable adapter, Administrator can configure to
tag packet with particular vlan id. Packet will be tagged and strip with
that vlan id. Also if 'Tagging' flag is disable, other packet will be drop.
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/qlcnic/qlcnic_main.c')
-rw-r--r-- | drivers/net/qlcnic/qlcnic_main.c | 89 |
1 files changed, 69 insertions, 20 deletions
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 | ||