@@ -2793,15 +2793,34 @@ static void qeth_tso_fill_header(struct qeth_card *card,
2793
2793
}
2794
2794
}
2795
2795
2796
- static inline int qeth_l3_tso_elements (struct sk_buff * skb )
2796
+ /**
2797
+ * qeth_get_elements_no_tso() - find number of SBALEs for skb data, inc. frags.
2798
+ * @card: qeth card structure, to check max. elems.
2799
+ * @skb: SKB address
2800
+ * @extra_elems: extra elems needed, to check against max.
2801
+ *
2802
+ * Returns the number of pages, and thus QDIO buffer elements, needed to cover
2803
+ * skb data, including linear part and fragments, but excluding TCP header.
2804
+ * (Exclusion of TCP header distinguishes it from qeth_get_elements_no().)
2805
+ * Checks if the result plus extra_elems fits under the limit for the card.
2806
+ * Returns 0 if it does not.
2807
+ * Note: extra_elems is not included in the returned result.
2808
+ */
2809
+ static int qeth_get_elements_no_tso (struct qeth_card * card ,
2810
+ struct sk_buff * skb , int extra_elems )
2797
2811
{
2798
- unsigned long tcpd = (unsigned long )tcp_hdr (skb ) +
2799
- tcp_hdr (skb )-> doff * 4 ;
2800
- int tcpd_len = skb_headlen (skb ) - (tcpd - (unsigned long )skb -> data );
2801
- int elements = PFN_UP (tcpd + tcpd_len - 1 ) - PFN_DOWN (tcpd );
2802
-
2803
- elements += qeth_get_elements_for_frags (skb );
2812
+ addr_t tcpdptr = (addr_t )tcp_hdr (skb ) + tcp_hdrlen (skb );
2813
+ int elements = qeth_get_elements_for_range (
2814
+ tcpdptr ,
2815
+ (addr_t )skb -> data + skb_headlen (skb )) +
2816
+ qeth_get_elements_for_frags (skb );
2804
2817
2818
+ if ((elements + extra_elems ) > QETH_MAX_BUFFER_ELEMENTS (card )) {
2819
+ QETH_DBF_MESSAGE (2 ,
2820
+ "Invalid size of TSO IP packet (Number=%d / Length=%d). Discarded.\n" ,
2821
+ elements + extra_elems , skb -> len );
2822
+ return 0 ;
2823
+ }
2805
2824
return elements ;
2806
2825
}
2807
2826
@@ -2810,8 +2829,8 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
2810
2829
int rc ;
2811
2830
u16 * tag ;
2812
2831
struct qeth_hdr * hdr = NULL ;
2813
- int elements_needed = 0 ;
2814
- int elems ;
2832
+ int hdr_elements = 0 ;
2833
+ int elements ;
2815
2834
struct qeth_card * card = dev -> ml_priv ;
2816
2835
struct sk_buff * new_skb = NULL ;
2817
2836
int ipv = qeth_get_ip_version (skb );
@@ -2859,7 +2878,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
2859
2878
hdr = kmem_cache_alloc (qeth_core_header_cache , GFP_ATOMIC );
2860
2879
if (!hdr )
2861
2880
goto tx_drop ;
2862
- elements_needed ++ ;
2881
+ hdr_elements ++ ;
2863
2882
} else {
2864
2883
/* create a clone with writeable headroom */
2865
2884
new_skb = skb_realloc_headroom (skb , sizeof (struct qeth_hdr_tso )
@@ -2895,7 +2914,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
2895
2914
* chaining we can not send long frag lists
2896
2915
*/
2897
2916
if (large_send ) {
2898
- if (qeth_l3_tso_elements ( new_skb ) + 1 > 16 ) {
2917
+ if (! qeth_get_elements_no_tso ( card , new_skb , 1 ) ) {
2899
2918
if (skb_linearize (new_skb ))
2900
2919
goto tx_drop ;
2901
2920
if (card -> options .performance_stats )
@@ -2909,7 +2928,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
2909
2928
memset (hdr , 0 , sizeof (struct qeth_hdr_tso ));
2910
2929
qeth_l3_fill_header (card , hdr , new_skb , ipv , cast_type );
2911
2930
qeth_tso_fill_header (card , hdr , new_skb );
2912
- elements_needed ++ ;
2931
+ hdr_elements ++ ;
2913
2932
} else {
2914
2933
if (data_offset < 0 ) {
2915
2934
hdr = (struct qeth_hdr * )skb_push (new_skb ,
@@ -2930,38 +2949,37 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
2930
2949
qeth_l3_hdr_csum (card , hdr , new_skb );
2931
2950
}
2932
2951
2933
- elems = qeth_get_elements_no (card , new_skb , elements_needed );
2934
- if (!elems ) {
2952
+ elements = qeth_get_elements_no (card , new_skb , hdr_elements );
2953
+ if (!elements ) {
2935
2954
if (data_offset >= 0 )
2936
2955
kmem_cache_free (qeth_core_header_cache , hdr );
2937
2956
goto tx_drop ;
2938
2957
}
2939
- elements_needed += elems ;
2940
- nr_frags = skb_shinfo (new_skb )-> nr_frags ;
2958
+ elements += hdr_elements ;
2941
2959
2942
2960
if (card -> info .type != QETH_CARD_TYPE_IQD ) {
2943
2961
int len ;
2944
2962
if (large_send )
2945
2963
len = ((unsigned long )tcp_hdr (new_skb ) +
2946
- tcp_hdr (new_skb )-> doff * 4 ) -
2964
+ tcp_hdrlen (new_skb )) -
2947
2965
(unsigned long )new_skb -> data ;
2948
2966
else
2949
2967
len = sizeof (struct qeth_hdr_layer3 );
2950
2968
2951
2969
if (qeth_hdr_chk_and_bounce (new_skb , & hdr , len ))
2952
2970
goto tx_drop ;
2953
- rc = qeth_do_send_packet (card , queue , new_skb , hdr ,
2954
- elements_needed );
2971
+ rc = qeth_do_send_packet (card , queue , new_skb , hdr , elements );
2955
2972
} else
2956
2973
rc = qeth_do_send_packet_fast (card , queue , new_skb , hdr ,
2957
- elements_needed , data_offset , 0 );
2974
+ elements , data_offset , 0 );
2958
2975
2959
2976
if (!rc ) {
2960
2977
card -> stats .tx_packets ++ ;
2961
2978
card -> stats .tx_bytes += tx_bytes ;
2962
2979
if (new_skb != skb )
2963
2980
dev_kfree_skb_any (skb );
2964
2981
if (card -> options .performance_stats ) {
2982
+ nr_frags = skb_shinfo (new_skb )-> nr_frags ;
2965
2983
if (large_send ) {
2966
2984
card -> perf_stats .large_send_bytes += tx_bytes ;
2967
2985
card -> perf_stats .large_send_cnt ++ ;
0 commit comments