Skip to content

Commit 2863c61

Browse files
Eugene Crosserdavem330
authored andcommitted
qeth: refactor calculation of SBALE count
Rewrite the functions that calculate the required number of buffer elements needed to represent SKB data, to make them hopefully more comprehensible. Plus a few cleanups. Signed-off-by: Eugene Crosser <[email protected]> Signed-off-by: Ursula Braun <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 1b05cf6 commit 2863c61

File tree

3 files changed

+85
-41
lines changed

3 files changed

+85
-41
lines changed

drivers/s390/net/qeth_core.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -844,6 +844,19 @@ struct qeth_trap_id {
844844
/*some helper functions*/
845845
#define QETH_CARD_IFNAME(card) (((card)->dev)? (card)->dev->name : "")
846846

847+
/**
848+
* qeth_get_elements_for_range() - find number of SBALEs to cover range.
849+
* @start: Start of the address range.
850+
* @end: Address after the end of the range.
851+
*
852+
* Returns the number of pages, and thus QDIO buffer elements, needed to cover
853+
* the specified address range.
854+
*/
855+
static inline int qeth_get_elements_for_range(addr_t start, addr_t end)
856+
{
857+
return PFN_UP(end - 1) - PFN_DOWN(start);
858+
}
859+
847860
static inline int qeth_get_micros(void)
848861
{
849862
return (int) (get_tod_clock() >> 12);

drivers/s390/net/qeth_core_main.c

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3810,41 +3810,54 @@ int qeth_get_priority_queue(struct qeth_card *card, struct sk_buff *skb,
38103810
}
38113811
EXPORT_SYMBOL_GPL(qeth_get_priority_queue);
38123812

3813+
/**
3814+
* qeth_get_elements_for_frags() - find number of SBALEs for skb frags.
3815+
* @skb: SKB address
3816+
*
3817+
* Returns the number of pages, and thus QDIO buffer elements, needed to cover
3818+
* fragmented part of the SKB. Returns zero for linear SKB.
3819+
*/
38133820
int qeth_get_elements_for_frags(struct sk_buff *skb)
38143821
{
3815-
int cnt, length, e, elements = 0;
3816-
struct skb_frag_struct *frag;
3817-
char *data;
3822+
int cnt, elements = 0;
38183823

38193824
for (cnt = 0; cnt < skb_shinfo(skb)->nr_frags; cnt++) {
3820-
frag = &skb_shinfo(skb)->frags[cnt];
3821-
data = (char *)page_to_phys(skb_frag_page(frag)) +
3822-
frag->page_offset;
3823-
length = frag->size;
3824-
e = PFN_UP((unsigned long)data + length - 1) -
3825-
PFN_DOWN((unsigned long)data);
3826-
elements += e;
3825+
struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[cnt];
3826+
3827+
elements += qeth_get_elements_for_range(
3828+
(addr_t)skb_frag_address(frag),
3829+
(addr_t)skb_frag_address(frag) + skb_frag_size(frag));
38273830
}
38283831
return elements;
38293832
}
38303833
EXPORT_SYMBOL_GPL(qeth_get_elements_for_frags);
38313834

3835+
/**
3836+
* qeth_get_elements_no() - find number of SBALEs for skb data, inc. frags.
3837+
* @card: qeth card structure, to check max. elems.
3838+
* @skb: SKB address
3839+
* @extra_elems: extra elems needed, to check against max.
3840+
*
3841+
* Returns the number of pages, and thus QDIO buffer elements, needed to cover
3842+
* skb data, including linear part and fragments. Checks if the result plus
3843+
* extra_elems fits under the limit for the card. Returns 0 if it does not.
3844+
* Note: extra_elems is not included in the returned result.
3845+
*/
38323846
int qeth_get_elements_no(struct qeth_card *card,
3833-
struct sk_buff *skb, int elems)
3847+
struct sk_buff *skb, int extra_elems)
38343848
{
3835-
int dlen = skb->len - skb->data_len;
3836-
int elements_needed = PFN_UP((unsigned long)skb->data + dlen - 1) -
3837-
PFN_DOWN((unsigned long)skb->data);
3838-
3839-
elements_needed += qeth_get_elements_for_frags(skb);
3849+
int elements = qeth_get_elements_for_range(
3850+
(addr_t)skb->data,
3851+
(addr_t)skb->data + skb_headlen(skb)) +
3852+
qeth_get_elements_for_frags(skb);
38403853

3841-
if ((elements_needed + elems) > QETH_MAX_BUFFER_ELEMENTS(card)) {
3854+
if ((elements + extra_elems) > QETH_MAX_BUFFER_ELEMENTS(card)) {
38423855
QETH_DBF_MESSAGE(2, "Invalid size of IP packet "
38433856
"(Number=%d / Length=%d). Discarded.\n",
3844-
(elements_needed+elems), skb->len);
3857+
elements + extra_elems, skb->len);
38453858
return 0;
38463859
}
3847-
return elements_needed;
3860+
return elements;
38483861
}
38493862
EXPORT_SYMBOL_GPL(qeth_get_elements_no);
38503863

@@ -3859,7 +3872,7 @@ int qeth_hdr_chk_and_bounce(struct sk_buff *skb, struct qeth_hdr **hdr, int len)
38593872
rest = len - inpage;
38603873
if (rest > hroom)
38613874
return 1;
3862-
memmove(skb->data - rest, skb->data, skb->len - skb->data_len);
3875+
memmove(skb->data - rest, skb->data, skb_headlen(skb));
38633876
skb->data -= rest;
38643877
skb->tail -= rest;
38653878
*hdr = (struct qeth_hdr *)skb->data;
@@ -3873,7 +3886,7 @@ static inline void __qeth_fill_buffer(struct sk_buff *skb,
38733886
struct qdio_buffer *buffer, int is_tso, int *next_element_to_fill,
38743887
int offset)
38753888
{
3876-
int length = skb->len - skb->data_len;
3889+
int length = skb_headlen(skb);
38773890
int length_here;
38783891
int element;
38793892
char *data;

drivers/s390/net/qeth_l3_main.c

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2793,15 +2793,34 @@ static void qeth_tso_fill_header(struct qeth_card *card,
27932793
}
27942794
}
27952795

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)
27972811
{
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);
28042817

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+
}
28052824
return elements;
28062825
}
28072826

@@ -2810,8 +2829,8 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
28102829
int rc;
28112830
u16 *tag;
28122831
struct qeth_hdr *hdr = NULL;
2813-
int elements_needed = 0;
2814-
int elems;
2832+
int hdr_elements = 0;
2833+
int elements;
28152834
struct qeth_card *card = dev->ml_priv;
28162835
struct sk_buff *new_skb = NULL;
28172836
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)
28592878
hdr = kmem_cache_alloc(qeth_core_header_cache, GFP_ATOMIC);
28602879
if (!hdr)
28612880
goto tx_drop;
2862-
elements_needed++;
2881+
hdr_elements++;
28632882
} else {
28642883
/* create a clone with writeable headroom */
28652884
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)
28952914
* chaining we can not send long frag lists
28962915
*/
28972916
if (large_send) {
2898-
if (qeth_l3_tso_elements(new_skb) + 1 > 16) {
2917+
if (!qeth_get_elements_no_tso(card, new_skb, 1)) {
28992918
if (skb_linearize(new_skb))
29002919
goto tx_drop;
29012920
if (card->options.performance_stats)
@@ -2909,7 +2928,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
29092928
memset(hdr, 0, sizeof(struct qeth_hdr_tso));
29102929
qeth_l3_fill_header(card, hdr, new_skb, ipv, cast_type);
29112930
qeth_tso_fill_header(card, hdr, new_skb);
2912-
elements_needed++;
2931+
hdr_elements++;
29132932
} else {
29142933
if (data_offset < 0) {
29152934
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)
29302949
qeth_l3_hdr_csum(card, hdr, new_skb);
29312950
}
29322951

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) {
29352954
if (data_offset >= 0)
29362955
kmem_cache_free(qeth_core_header_cache, hdr);
29372956
goto tx_drop;
29382957
}
2939-
elements_needed += elems;
2940-
nr_frags = skb_shinfo(new_skb)->nr_frags;
2958+
elements += hdr_elements;
29412959

29422960
if (card->info.type != QETH_CARD_TYPE_IQD) {
29432961
int len;
29442962
if (large_send)
29452963
len = ((unsigned long)tcp_hdr(new_skb) +
2946-
tcp_hdr(new_skb)->doff * 4) -
2964+
tcp_hdrlen(new_skb)) -
29472965
(unsigned long)new_skb->data;
29482966
else
29492967
len = sizeof(struct qeth_hdr_layer3);
29502968

29512969
if (qeth_hdr_chk_and_bounce(new_skb, &hdr, len))
29522970
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);
29552972
} else
29562973
rc = qeth_do_send_packet_fast(card, queue, new_skb, hdr,
2957-
elements_needed, data_offset, 0);
2974+
elements, data_offset, 0);
29582975

29592976
if (!rc) {
29602977
card->stats.tx_packets++;
29612978
card->stats.tx_bytes += tx_bytes;
29622979
if (new_skb != skb)
29632980
dev_kfree_skb_any(skb);
29642981
if (card->options.performance_stats) {
2982+
nr_frags = skb_shinfo(new_skb)->nr_frags;
29652983
if (large_send) {
29662984
card->perf_stats.large_send_bytes += tx_bytes;
29672985
card->perf_stats.large_send_cnt++;

0 commit comments

Comments
 (0)