diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_main.c | 62 |
1 files changed, 38 insertions, 24 deletions
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index a444110b060f..7892361af0ac 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c | |||
@@ -842,32 +842,27 @@ static int be_vlan_tag_tx_chk(struct be_adapter *adapter, struct sk_buff *skb) | |||
842 | return vlan_tx_tag_present(skb) || adapter->pvid || adapter->qnq_vid; | 842 | return vlan_tx_tag_present(skb) || adapter->pvid || adapter->qnq_vid; |
843 | } | 843 | } |
844 | 844 | ||
845 | static int be_ipv6_tx_stall_chk(struct be_adapter *adapter, struct sk_buff *skb) | 845 | static int be_ipv6_tx_stall_chk(struct be_adapter *adapter, |
846 | struct sk_buff *skb) | ||
846 | { | 847 | { |
847 | return BE3_chip(adapter) && | 848 | return BE3_chip(adapter) && be_ipv6_exthdr_check(skb); |
848 | be_ipv6_exthdr_check(skb); | ||
849 | } | 849 | } |
850 | 850 | ||
851 | static netdev_tx_t be_xmit(struct sk_buff *skb, | 851 | static struct sk_buff *be_xmit_workarounds(struct be_adapter *adapter, |
852 | struct net_device *netdev) | 852 | struct sk_buff *skb, |
853 | bool *skip_hw_vlan) | ||
853 | { | 854 | { |
854 | struct be_adapter *adapter = netdev_priv(netdev); | ||
855 | struct be_tx_obj *txo = &adapter->tx_obj[skb_get_queue_mapping(skb)]; | ||
856 | struct be_queue_info *txq = &txo->q; | ||
857 | struct iphdr *ip = NULL; | ||
858 | u32 wrb_cnt = 0, copied = 0; | ||
859 | u32 start = txq->head, eth_hdr_len; | ||
860 | bool dummy_wrb, stopped = false; | ||
861 | bool skip_hw_vlan = false; | ||
862 | struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data; | 855 | struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data; |
863 | 856 | unsigned int eth_hdr_len; | |
864 | eth_hdr_len = ntohs(skb->protocol) == ETH_P_8021Q ? | 857 | struct iphdr *ip; |
865 | VLAN_ETH_HLEN : ETH_HLEN; | ||
866 | 858 | ||
867 | /* For padded packets, BE HW modifies tot_len field in IP header | 859 | /* For padded packets, BE HW modifies tot_len field in IP header |
868 | * incorrecly when VLAN tag is inserted by HW. | 860 | * incorrecly when VLAN tag is inserted by HW. |
869 | */ | 861 | */ |
870 | if (skb->len <= 60 && vlan_tx_tag_present(skb) && is_ipv4_pkt(skb)) { | 862 | eth_hdr_len = ntohs(skb->protocol) == ETH_P_8021Q ? |
863 | VLAN_ETH_HLEN : ETH_HLEN; | ||
864 | if (skb->len <= 60 && vlan_tx_tag_present(skb) && | ||
865 | is_ipv4_pkt(skb)) { | ||
871 | ip = (struct iphdr *)ip_hdr(skb); | 866 | ip = (struct iphdr *)ip_hdr(skb); |
872 | pskb_trim(skb, eth_hdr_len + ntohs(ip->tot_len)); | 867 | pskb_trim(skb, eth_hdr_len + ntohs(ip->tot_len)); |
873 | } | 868 | } |
@@ -877,15 +872,15 @@ static netdev_tx_t be_xmit(struct sk_buff *skb, | |||
877 | */ | 872 | */ |
878 | if ((adapter->function_mode & UMC_ENABLED) && | 873 | if ((adapter->function_mode & UMC_ENABLED) && |
879 | veh->h_vlan_proto == htons(ETH_P_8021Q)) | 874 | veh->h_vlan_proto == htons(ETH_P_8021Q)) |
880 | skip_hw_vlan = true; | 875 | *skip_hw_vlan = true; |
881 | 876 | ||
882 | /* HW has a bug wherein it will calculate CSUM for VLAN | 877 | /* HW has a bug wherein it will calculate CSUM for VLAN |
883 | * pkts even though it is disabled. | 878 | * pkts even though it is disabled. |
884 | * Manually insert VLAN in pkt. | 879 | * Manually insert VLAN in pkt. |
885 | */ | 880 | */ |
886 | if (skb->ip_summed != CHECKSUM_PARTIAL && | 881 | if (skb->ip_summed != CHECKSUM_PARTIAL && |
887 | vlan_tx_tag_present(skb)) { | 882 | vlan_tx_tag_present(skb)) { |
888 | skb = be_insert_vlan_in_pkt(adapter, skb, &skip_hw_vlan); | 883 | skb = be_insert_vlan_in_pkt(adapter, skb, skip_hw_vlan); |
889 | if (unlikely(!skb)) | 884 | if (unlikely(!skb)) |
890 | goto tx_drop; | 885 | goto tx_drop; |
891 | } | 886 | } |
@@ -895,8 +890,8 @@ static netdev_tx_t be_xmit(struct sk_buff *skb, | |||
895 | * skip HW tagging is not enabled by FW. | 890 | * skip HW tagging is not enabled by FW. |
896 | */ | 891 | */ |
897 | if (unlikely(be_ipv6_tx_stall_chk(adapter, skb) && | 892 | if (unlikely(be_ipv6_tx_stall_chk(adapter, skb) && |
898 | (adapter->pvid || adapter->qnq_vid) && | 893 | (adapter->pvid || adapter->qnq_vid) && |
899 | !qnq_async_evt_rcvd(adapter))) | 894 | !qnq_async_evt_rcvd(adapter))) |
900 | goto tx_drop; | 895 | goto tx_drop; |
901 | 896 | ||
902 | /* Manual VLAN tag insertion to prevent: | 897 | /* Manual VLAN tag insertion to prevent: |
@@ -907,11 +902,31 @@ static netdev_tx_t be_xmit(struct sk_buff *skb, | |||
907 | */ | 902 | */ |
908 | if (be_ipv6_tx_stall_chk(adapter, skb) && | 903 | if (be_ipv6_tx_stall_chk(adapter, skb) && |
909 | be_vlan_tag_tx_chk(adapter, skb)) { | 904 | be_vlan_tag_tx_chk(adapter, skb)) { |
910 | skb = be_insert_vlan_in_pkt(adapter, skb, &skip_hw_vlan); | 905 | skb = be_insert_vlan_in_pkt(adapter, skb, skip_hw_vlan); |
911 | if (unlikely(!skb)) | 906 | if (unlikely(!skb)) |
912 | goto tx_drop; | 907 | goto tx_drop; |
913 | } | 908 | } |
914 | 909 | ||
910 | return skb; | ||
911 | tx_drop: | ||
912 | dev_kfree_skb_any(skb); | ||
913 | return NULL; | ||
914 | } | ||
915 | |||
916 | static netdev_tx_t be_xmit(struct sk_buff *skb, struct net_device *netdev) | ||
917 | { | ||
918 | struct be_adapter *adapter = netdev_priv(netdev); | ||
919 | struct be_tx_obj *txo = &adapter->tx_obj[skb_get_queue_mapping(skb)]; | ||
920 | struct be_queue_info *txq = &txo->q; | ||
921 | bool dummy_wrb, stopped = false; | ||
922 | u32 wrb_cnt = 0, copied = 0; | ||
923 | bool skip_hw_vlan = false; | ||
924 | u32 start = txq->head; | ||
925 | |||
926 | skb = be_xmit_workarounds(adapter, skb, &skip_hw_vlan); | ||
927 | if (!skb) | ||
928 | return NETDEV_TX_OK; | ||
929 | |||
915 | wrb_cnt = wrb_cnt_for_skb(adapter, skb, &dummy_wrb); | 930 | wrb_cnt = wrb_cnt_for_skb(adapter, skb, &dummy_wrb); |
916 | 931 | ||
917 | copied = make_tx_wrbs(adapter, txq, skb, wrb_cnt, dummy_wrb, | 932 | copied = make_tx_wrbs(adapter, txq, skb, wrb_cnt, dummy_wrb, |
@@ -941,7 +956,6 @@ static netdev_tx_t be_xmit(struct sk_buff *skb, | |||
941 | txq->head = start; | 956 | txq->head = start; |
942 | dev_kfree_skb_any(skb); | 957 | dev_kfree_skb_any(skb); |
943 | } | 958 | } |
944 | tx_drop: | ||
945 | return NETDEV_TX_OK; | 959 | return NETDEV_TX_OK; |
946 | } | 960 | } |
947 | 961 | ||