aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/ethernet/emulex/benet/be_main.c62
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
845static int be_ipv6_tx_stall_chk(struct be_adapter *adapter, struct sk_buff *skb) 845static 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
851static netdev_tx_t be_xmit(struct sk_buff *skb, 851static 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;
911tx_drop:
912 dev_kfree_skb_any(skb);
913 return NULL;
914}
915
916static 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 }
944tx_drop:
945 return NETDEV_TX_OK; 959 return NETDEV_TX_OK;
946} 960}
947 961