aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/emulex
diff options
context:
space:
mode:
authorSriharsha Basavapatna <sriharsha.basavapatna@emulex.com>2015-02-15 21:33:45 -0500
committerDavid S. Miller <davem@davemloft.net>2015-02-20 14:06:57 -0500
commit804abcdbdbb68df5ca8cf7e70366522f02298029 (patch)
tree490961cb191ae80d1b598cc893fa9e00cb02ae48 /drivers/net/ethernet/emulex
parent69994d17abe90c4ae449dfcefbae9754f92c36bd (diff)
be2net: Refactor wrb_fill_hdr() routine
The WRB header is setup by wrb_fill_hdr() routine. This routine currently gets some of the WRB params as args and figures out rest of the WRB params by looking at various fields in skb (like gso, checksum, vlan-tag etc). All these params could instead be retrieved from the skb into a structure and passed to this routine. This separates wrb_fill_hdr() to only provide chip-specific code to fill the WRB. This also makes it simple to support chips with different WRB formats. Signed-off-by: Sriharsha Basavapatna <sriharsha.basavapatna@emulex.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/emulex')
-rw-r--r--drivers/net/ethernet/emulex/benet/be.h33
-rw-r--r--drivers/net/ethernet/emulex/benet/be_main.c105
2 files changed, 99 insertions, 39 deletions
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
index 27de37aa90af..bc7f3d6872f4 100644
--- a/drivers/net/ethernet/emulex/benet/be.h
+++ b/drivers/net/ethernet/emulex/benet/be.h
@@ -417,6 +417,39 @@ struct rss_info {
417 u8 rss_hkey[RSS_HASH_KEY_LEN]; 417 u8 rss_hkey[RSS_HASH_KEY_LEN];
418}; 418};
419 419
420/* Macros to read/write the 'features' word of be_wrb_params structure.
421 */
422#define BE_WRB_F_BIT(name) BE_WRB_F_##name##_BIT
423#define BE_WRB_F_MASK(name) BIT_MASK(BE_WRB_F_##name##_BIT)
424
425#define BE_WRB_F_GET(word, name) \
426 (((word) & (BE_WRB_F_MASK(name))) >> BE_WRB_F_BIT(name))
427
428#define BE_WRB_F_SET(word, name, val) \
429 ((word) |= (((val) << BE_WRB_F_BIT(name)) & BE_WRB_F_MASK(name)))
430
431/* Feature/offload bits */
432enum {
433 BE_WRB_F_CRC_BIT, /* Ethernet CRC */
434 BE_WRB_F_IPCS_BIT, /* IP csum */
435 BE_WRB_F_TCPCS_BIT, /* TCP csum */
436 BE_WRB_F_UDPCS_BIT, /* UDP csum */
437 BE_WRB_F_LSO_BIT, /* LSO */
438 BE_WRB_F_LSO6_BIT, /* LSO6 */
439 BE_WRB_F_VLAN_BIT, /* VLAN */
440 BE_WRB_F_VLAN_SKIP_HW_BIT /* Skip VLAN tag (workaround) */
441};
442
443/* The structure below provides a HW-agnostic abstraction of WRB params
444 * retrieved from a TX skb. This is in turn passed to chip specific routines
445 * during transmit, to set the corresponding params in the WRB.
446 */
447struct be_wrb_params {
448 u32 features; /* Feature bits */
449 u16 vlan_tag; /* VLAN tag */
450 u16 lso_mss; /* MSS for LSO */
451};
452
420struct be_adapter { 453struct be_adapter {
421 struct pci_dev *pdev; 454 struct pci_dev *pdev;
422 struct net_device *netdev; 455 struct net_device *netdev;
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 0a816859aca5..8477fb4de614 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -727,48 +727,71 @@ static u16 skb_ip_proto(struct sk_buff *skb)
727 ip_hdr(skb)->protocol : ipv6_hdr(skb)->nexthdr; 727 ip_hdr(skb)->protocol : ipv6_hdr(skb)->nexthdr;
728} 728}
729 729
730static void wrb_fill_hdr(struct be_adapter *adapter, struct be_eth_hdr_wrb *hdr, 730static void be_get_wrb_params_from_skb(struct be_adapter *adapter,
731 struct sk_buff *skb, u32 wrb_cnt, u32 len, 731 struct sk_buff *skb,
732 bool skip_hw_vlan) 732 struct be_wrb_params *wrb_params)
733{ 733{
734 u16 vlan_tag, proto; 734 u16 proto;
735
736 memset(hdr, 0, sizeof(*hdr));
737
738 SET_TX_WRB_HDR_BITS(crc, hdr, 1);
739 735
740 if (skb_is_gso(skb)) { 736 if (skb_is_gso(skb)) {
741 SET_TX_WRB_HDR_BITS(lso, hdr, 1); 737 BE_WRB_F_SET(wrb_params->features, LSO, 1);
742 SET_TX_WRB_HDR_BITS(lso_mss, hdr, skb_shinfo(skb)->gso_size); 738 wrb_params->lso_mss = skb_shinfo(skb)->gso_size;
743 if (skb_is_gso_v6(skb) && !lancer_chip(adapter)) 739 if (skb_is_gso_v6(skb) && !lancer_chip(adapter))
744 SET_TX_WRB_HDR_BITS(lso6, hdr, 1); 740 BE_WRB_F_SET(wrb_params->features, LSO6, 1);
745 } else if (skb->ip_summed == CHECKSUM_PARTIAL) { 741 } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
746 if (skb->encapsulation) { 742 if (skb->encapsulation) {
747 SET_TX_WRB_HDR_BITS(ipcs, hdr, 1); 743 BE_WRB_F_SET(wrb_params->features, IPCS, 1);
748 proto = skb_inner_ip_proto(skb); 744 proto = skb_inner_ip_proto(skb);
749 } else { 745 } else {
750 proto = skb_ip_proto(skb); 746 proto = skb_ip_proto(skb);
751 } 747 }
752 if (proto == IPPROTO_TCP) 748 if (proto == IPPROTO_TCP)
753 SET_TX_WRB_HDR_BITS(tcpcs, hdr, 1); 749 BE_WRB_F_SET(wrb_params->features, TCPCS, 1);
754 else if (proto == IPPROTO_UDP) 750 else if (proto == IPPROTO_UDP)
755 SET_TX_WRB_HDR_BITS(udpcs, hdr, 1); 751 BE_WRB_F_SET(wrb_params->features, UDPCS, 1);
756 } 752 }
757 753
758 if (skb_vlan_tag_present(skb)) { 754 if (skb_vlan_tag_present(skb)) {
759 SET_TX_WRB_HDR_BITS(vlan, hdr, 1); 755 BE_WRB_F_SET(wrb_params->features, VLAN, 1);
760 vlan_tag = be_get_tx_vlan_tag(adapter, skb); 756 wrb_params->vlan_tag = be_get_tx_vlan_tag(adapter, skb);
761 SET_TX_WRB_HDR_BITS(vlan_tag, hdr, vlan_tag);
762 } 757 }
763 758
764 SET_TX_WRB_HDR_BITS(num_wrb, hdr, wrb_cnt); 759 BE_WRB_F_SET(wrb_params->features, CRC, 1);
765 SET_TX_WRB_HDR_BITS(len, hdr, len); 760}
761
762static void wrb_fill_hdr(struct be_adapter *adapter,
763 struct be_eth_hdr_wrb *hdr,
764 struct be_wrb_params *wrb_params,
765 struct sk_buff *skb)
766{
767 memset(hdr, 0, sizeof(*hdr));
766 768
767 /* Hack to skip HW VLAN tagging needs evt = 1, compl = 0 769 SET_TX_WRB_HDR_BITS(crc, hdr,
768 * When this hack is not needed, the evt bit is set while ringing DB 770 BE_WRB_F_GET(wrb_params->features, CRC));
771 SET_TX_WRB_HDR_BITS(ipcs, hdr,
772 BE_WRB_F_GET(wrb_params->features, IPCS));
773 SET_TX_WRB_HDR_BITS(tcpcs, hdr,
774 BE_WRB_F_GET(wrb_params->features, TCPCS));
775 SET_TX_WRB_HDR_BITS(udpcs, hdr,
776 BE_WRB_F_GET(wrb_params->features, UDPCS));
777
778 SET_TX_WRB_HDR_BITS(lso, hdr,
779 BE_WRB_F_GET(wrb_params->features, LSO));
780 SET_TX_WRB_HDR_BITS(lso6, hdr,
781 BE_WRB_F_GET(wrb_params->features, LSO6));
782 SET_TX_WRB_HDR_BITS(lso_mss, hdr, wrb_params->lso_mss);
783
784 /* Hack to skip HW VLAN tagging needs evt = 1, compl = 0. When this
785 * hack is not needed, the evt bit is set while ringing DB.
769 */ 786 */
770 if (skip_hw_vlan) 787 SET_TX_WRB_HDR_BITS(event, hdr,
771 SET_TX_WRB_HDR_BITS(event, hdr, 1); 788 BE_WRB_F_GET(wrb_params->features, VLAN_SKIP_HW));
789 SET_TX_WRB_HDR_BITS(vlan, hdr,
790 BE_WRB_F_GET(wrb_params->features, VLAN));
791 SET_TX_WRB_HDR_BITS(vlan_tag, hdr, wrb_params->vlan_tag);
792
793 SET_TX_WRB_HDR_BITS(num_wrb, hdr, skb_wrb_cnt(skb));
794 SET_TX_WRB_HDR_BITS(len, hdr, skb->len);
772} 795}
773 796
774static void unmap_tx_frag(struct device *dev, struct be_eth_wrb *wrb, 797static void unmap_tx_frag(struct device *dev, struct be_eth_wrb *wrb,
@@ -790,7 +813,8 @@ static void unmap_tx_frag(struct device *dev, struct be_eth_wrb *wrb,
790 813
791/* Returns the number of WRBs used up by the skb */ 814/* Returns the number of WRBs used up by the skb */
792static u32 be_xmit_enqueue(struct be_adapter *adapter, struct be_tx_obj *txo, 815static u32 be_xmit_enqueue(struct be_adapter *adapter, struct be_tx_obj *txo,
793 struct sk_buff *skb, bool skip_hw_vlan) 816 struct sk_buff *skb,
817 struct be_wrb_params *wrb_params)
794{ 818{
795 u32 i, copied = 0, wrb_cnt = skb_wrb_cnt(skb); 819 u32 i, copied = 0, wrb_cnt = skb_wrb_cnt(skb);
796 struct device *dev = &adapter->pdev->dev; 820 struct device *dev = &adapter->pdev->dev;
@@ -802,7 +826,7 @@ static u32 be_xmit_enqueue(struct be_adapter *adapter, struct be_tx_obj *txo,
802 u16 head = txq->head; 826 u16 head = txq->head;
803 827
804 hdr = queue_head_node(txq); 828 hdr = queue_head_node(txq);
805 wrb_fill_hdr(adapter, hdr, skb, wrb_cnt, skb->len, skip_hw_vlan); 829 wrb_fill_hdr(adapter, hdr, wrb_params, skb);
806 be_dws_cpu_to_le(hdr, sizeof(*hdr)); 830 be_dws_cpu_to_le(hdr, sizeof(*hdr));
807 831
808 queue_head_inc(txq); 832 queue_head_inc(txq);
@@ -869,7 +893,8 @@ static inline int qnq_async_evt_rcvd(struct be_adapter *adapter)
869 893
870static struct sk_buff *be_insert_vlan_in_pkt(struct be_adapter *adapter, 894static struct sk_buff *be_insert_vlan_in_pkt(struct be_adapter *adapter,
871 struct sk_buff *skb, 895 struct sk_buff *skb,
872 bool *skip_hw_vlan) 896 struct be_wrb_params
897 *wrb_params)
873{ 898{
874 u16 vlan_tag = 0; 899 u16 vlan_tag = 0;
875 900
@@ -886,8 +911,7 @@ static struct sk_buff *be_insert_vlan_in_pkt(struct be_adapter *adapter,
886 /* f/w workaround to set skip_hw_vlan = 1, informs the F/W to 911 /* f/w workaround to set skip_hw_vlan = 1, informs the F/W to
887 * skip VLAN insertion 912 * skip VLAN insertion
888 */ 913 */
889 if (skip_hw_vlan) 914 BE_WRB_F_SET(wrb_params->features, VLAN_SKIP_HW, 1);
890 *skip_hw_vlan = true;
891 } 915 }
892 916
893 if (vlan_tag) { 917 if (vlan_tag) {
@@ -905,8 +929,7 @@ static struct sk_buff *be_insert_vlan_in_pkt(struct be_adapter *adapter,
905 vlan_tag); 929 vlan_tag);
906 if (unlikely(!skb)) 930 if (unlikely(!skb))
907 return skb; 931 return skb;
908 if (skip_hw_vlan) 932 BE_WRB_F_SET(wrb_params->features, VLAN_SKIP_HW, 1);
909 *skip_hw_vlan = true;
910 } 933 }
911 934
912 return skb; 935 return skb;
@@ -946,7 +969,8 @@ static int be_ipv6_tx_stall_chk(struct be_adapter *adapter, struct sk_buff *skb)
946 969
947static struct sk_buff *be_lancer_xmit_workarounds(struct be_adapter *adapter, 970static struct sk_buff *be_lancer_xmit_workarounds(struct be_adapter *adapter,
948 struct sk_buff *skb, 971 struct sk_buff *skb,
949 bool *skip_hw_vlan) 972 struct be_wrb_params
973 *wrb_params)
950{ 974{
951 struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data; 975 struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data;
952 unsigned int eth_hdr_len; 976 unsigned int eth_hdr_len;
@@ -970,7 +994,7 @@ static struct sk_buff *be_lancer_xmit_workarounds(struct be_adapter *adapter,
970 */ 994 */
971 if (be_pvid_tagging_enabled(adapter) && 995 if (be_pvid_tagging_enabled(adapter) &&
972 veh->h_vlan_proto == htons(ETH_P_8021Q)) 996 veh->h_vlan_proto == htons(ETH_P_8021Q))
973 *skip_hw_vlan = true; 997 BE_WRB_F_SET(wrb_params->features, VLAN_SKIP_HW, 1);
974 998
975 /* HW has a bug wherein it will calculate CSUM for VLAN 999 /* HW has a bug wherein it will calculate CSUM for VLAN
976 * pkts even though it is disabled. 1000 * pkts even though it is disabled.
@@ -978,7 +1002,7 @@ static struct sk_buff *be_lancer_xmit_workarounds(struct be_adapter *adapter,
978 */ 1002 */
979 if (skb->ip_summed != CHECKSUM_PARTIAL && 1003 if (skb->ip_summed != CHECKSUM_PARTIAL &&
980 skb_vlan_tag_present(skb)) { 1004 skb_vlan_tag_present(skb)) {
981 skb = be_insert_vlan_in_pkt(adapter, skb, skip_hw_vlan); 1005 skb = be_insert_vlan_in_pkt(adapter, skb, wrb_params);
982 if (unlikely(!skb)) 1006 if (unlikely(!skb))
983 goto err; 1007 goto err;
984 } 1008 }
@@ -1000,7 +1024,7 @@ static struct sk_buff *be_lancer_xmit_workarounds(struct be_adapter *adapter,
1000 */ 1024 */
1001 if (be_ipv6_tx_stall_chk(adapter, skb) && 1025 if (be_ipv6_tx_stall_chk(adapter, skb) &&
1002 be_vlan_tag_tx_chk(adapter, skb)) { 1026 be_vlan_tag_tx_chk(adapter, skb)) {
1003 skb = be_insert_vlan_in_pkt(adapter, skb, skip_hw_vlan); 1027 skb = be_insert_vlan_in_pkt(adapter, skb, wrb_params);
1004 if (unlikely(!skb)) 1028 if (unlikely(!skb))
1005 goto err; 1029 goto err;
1006 } 1030 }
@@ -1014,7 +1038,7 @@ err:
1014 1038
1015static struct sk_buff *be_xmit_workarounds(struct be_adapter *adapter, 1039static struct sk_buff *be_xmit_workarounds(struct be_adapter *adapter,
1016 struct sk_buff *skb, 1040 struct sk_buff *skb,
1017 bool *skip_hw_vlan) 1041 struct be_wrb_params *wrb_params)
1018{ 1042{
1019 /* Lancer, SH-R ASICs have a bug wherein Packets that are 32 bytes or 1043 /* Lancer, SH-R ASICs have a bug wherein Packets that are 32 bytes or
1020 * less may cause a transmit stall on that port. So the work-around is 1044 * less may cause a transmit stall on that port. So the work-around is
@@ -1026,7 +1050,7 @@ static struct sk_buff *be_xmit_workarounds(struct be_adapter *adapter,
1026 } 1050 }
1027 1051
1028 if (BEx_chip(adapter) || lancer_chip(adapter)) { 1052 if (BEx_chip(adapter) || lancer_chip(adapter)) {
1029 skb = be_lancer_xmit_workarounds(adapter, skb, skip_hw_vlan); 1053 skb = be_lancer_xmit_workarounds(adapter, skb, wrb_params);
1030 if (!skb) 1054 if (!skb)
1031 return NULL; 1055 return NULL;
1032 } 1056 }
@@ -1060,18 +1084,21 @@ static void be_xmit_flush(struct be_adapter *adapter, struct be_tx_obj *txo)
1060 1084
1061static netdev_tx_t be_xmit(struct sk_buff *skb, struct net_device *netdev) 1085static netdev_tx_t be_xmit(struct sk_buff *skb, struct net_device *netdev)
1062{ 1086{
1063 bool skip_hw_vlan = false, flush = !skb->xmit_more;
1064 struct be_adapter *adapter = netdev_priv(netdev); 1087 struct be_adapter *adapter = netdev_priv(netdev);
1065 u16 q_idx = skb_get_queue_mapping(skb); 1088 u16 q_idx = skb_get_queue_mapping(skb);
1066 struct be_tx_obj *txo = &adapter->tx_obj[q_idx]; 1089 struct be_tx_obj *txo = &adapter->tx_obj[q_idx];
1090 struct be_wrb_params wrb_params = { 0 };
1067 struct be_queue_info *txq = &txo->q; 1091 struct be_queue_info *txq = &txo->q;
1092 bool flush = !skb->xmit_more;
1068 u16 wrb_cnt; 1093 u16 wrb_cnt;
1069 1094
1070 skb = be_xmit_workarounds(adapter, skb, &skip_hw_vlan); 1095 skb = be_xmit_workarounds(adapter, skb, &wrb_params);
1071 if (unlikely(!skb)) 1096 if (unlikely(!skb))
1072 goto drop; 1097 goto drop;
1073 1098
1074 wrb_cnt = be_xmit_enqueue(adapter, txo, skb, skip_hw_vlan); 1099 be_get_wrb_params_from_skb(adapter, skb, &wrb_params);
1100
1101 wrb_cnt = be_xmit_enqueue(adapter, txo, skb, &wrb_params);
1075 if (unlikely(!wrb_cnt)) { 1102 if (unlikely(!wrb_cnt)) {
1076 dev_kfree_skb_any(skb); 1103 dev_kfree_skb_any(skb);
1077 goto drop; 1104 goto drop;