s390/qeth: use napi_gro_frags() for SG skbs
For non-linear packets, get the skb for attaching the page fragments from napi_get_frags() so that it can be recycled during GRO. Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
c04b116a28
commit
dcdcf8670d
@ -5106,8 +5106,9 @@ static void qeth_l3_rebuild_skb(struct qeth_card *card, struct sk_buff *skb,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void qeth_receive_skb(struct qeth_card *card, struct sk_buff *skb,
|
static void qeth_receive_skb(struct qeth_card *card, struct sk_buff *skb,
|
||||||
struct qeth_hdr *hdr)
|
struct qeth_hdr *hdr, bool uses_frags)
|
||||||
{
|
{
|
||||||
|
struct napi_struct *napi = &card->napi;
|
||||||
bool is_cso;
|
bool is_cso;
|
||||||
|
|
||||||
switch (hdr->hdr.l2.id) {
|
switch (hdr->hdr.l2.id) {
|
||||||
@ -5130,7 +5131,10 @@ static void qeth_receive_skb(struct qeth_card *card, struct sk_buff *skb,
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* never happens */
|
/* never happens */
|
||||||
dev_kfree_skb_any(skb);
|
if (uses_frags)
|
||||||
|
napi_free_frags(napi);
|
||||||
|
else
|
||||||
|
dev_kfree_skb_any(skb);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5141,8 +5145,6 @@ static void qeth_receive_skb(struct qeth_card *card, struct sk_buff *skb,
|
|||||||
skb->ip_summed = CHECKSUM_NONE;
|
skb->ip_summed = CHECKSUM_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
skb->protocol = eth_type_trans(skb, skb->dev);
|
|
||||||
|
|
||||||
QETH_CARD_STAT_ADD(card, rx_bytes, skb->len);
|
QETH_CARD_STAT_ADD(card, rx_bytes, skb->len);
|
||||||
QETH_CARD_STAT_INC(card, rx_packets);
|
QETH_CARD_STAT_INC(card, rx_packets);
|
||||||
if (skb_is_nonlinear(skb)) {
|
if (skb_is_nonlinear(skb)) {
|
||||||
@ -5151,7 +5153,12 @@ static void qeth_receive_skb(struct qeth_card *card, struct sk_buff *skb,
|
|||||||
skb_shinfo(skb)->nr_frags);
|
skb_shinfo(skb)->nr_frags);
|
||||||
}
|
}
|
||||||
|
|
||||||
napi_gro_receive(&card->napi, skb);
|
if (uses_frags) {
|
||||||
|
napi_gro_frags(napi);
|
||||||
|
} else {
|
||||||
|
skb->protocol = eth_type_trans(skb, skb->dev);
|
||||||
|
napi_gro_receive(napi, skb);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void qeth_create_skb_frag(struct sk_buff *skb, char *data, int data_len)
|
static void qeth_create_skb_frag(struct sk_buff *skb, char *data, int data_len)
|
||||||
@ -5177,7 +5184,9 @@ static int qeth_extract_skb(struct qeth_card *card,
|
|||||||
{
|
{
|
||||||
struct qdio_buffer_element *element = *__element;
|
struct qdio_buffer_element *element = *__element;
|
||||||
struct qdio_buffer *buffer = qethbuffer->buffer;
|
struct qdio_buffer *buffer = qethbuffer->buffer;
|
||||||
|
struct napi_struct *napi = &card->napi;
|
||||||
unsigned int linear_len = 0;
|
unsigned int linear_len = 0;
|
||||||
|
bool uses_frags = false;
|
||||||
int offset = *__offset;
|
int offset = *__offset;
|
||||||
bool use_rx_sg = false;
|
bool use_rx_sg = false;
|
||||||
unsigned int headroom;
|
unsigned int headroom;
|
||||||
@ -5253,21 +5262,42 @@ next_packet:
|
|||||||
!atomic_read(&card->force_alloc_skb) &&
|
!atomic_read(&card->force_alloc_skb) &&
|
||||||
!IS_OSN(card));
|
!IS_OSN(card));
|
||||||
|
|
||||||
if (use_rx_sg && qethbuffer->rx_skb) {
|
if (use_rx_sg) {
|
||||||
/* QETH_CQ_ENABLED only: */
|
/* QETH_CQ_ENABLED only: */
|
||||||
skb = qethbuffer->rx_skb;
|
if (qethbuffer->rx_skb) {
|
||||||
qethbuffer->rx_skb = NULL;
|
skb = qethbuffer->rx_skb;
|
||||||
} else {
|
qethbuffer->rx_skb = NULL;
|
||||||
if (!use_rx_sg)
|
goto use_skb;
|
||||||
linear_len = skb_len;
|
}
|
||||||
skb = napi_alloc_skb(&card->napi, linear_len + headroom);
|
|
||||||
|
skb = napi_get_frags(napi);
|
||||||
|
if (!skb) {
|
||||||
|
/* -ENOMEM, no point in falling back further. */
|
||||||
|
QETH_CARD_STAT_INC(card, rx_dropped_nomem);
|
||||||
|
goto walk_packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (skb_tailroom(skb) >= linear_len + headroom) {
|
||||||
|
uses_frags = true;
|
||||||
|
goto use_skb;
|
||||||
|
}
|
||||||
|
|
||||||
|
netdev_info_once(card->dev,
|
||||||
|
"Insufficient linear space in NAPI frags skb, need %u but have %u\n",
|
||||||
|
linear_len + headroom, skb_tailroom(skb));
|
||||||
|
/* Shouldn't happen. Don't optimize, fall back to linear skb. */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!skb)
|
linear_len = skb_len;
|
||||||
|
skb = napi_alloc_skb(napi, linear_len + headroom);
|
||||||
|
if (!skb) {
|
||||||
QETH_CARD_STAT_INC(card, rx_dropped_nomem);
|
QETH_CARD_STAT_INC(card, rx_dropped_nomem);
|
||||||
else if (headroom)
|
goto walk_packet;
|
||||||
skb_reserve(skb, headroom);
|
}
|
||||||
|
|
||||||
|
use_skb:
|
||||||
|
if (headroom)
|
||||||
|
skb_reserve(skb, headroom);
|
||||||
walk_packet:
|
walk_packet:
|
||||||
while (skb_len) {
|
while (skb_len) {
|
||||||
int data_len = min(skb_len, (int)(element->length - offset));
|
int data_len = min(skb_len, (int)(element->length - offset));
|
||||||
@ -5300,7 +5330,10 @@ walk_packet:
|
|||||||
QETH_CARD_TEXT(card, 4, "unexeob");
|
QETH_CARD_TEXT(card, 4, "unexeob");
|
||||||
QETH_CARD_HEX(card, 2, buffer, sizeof(void *));
|
QETH_CARD_HEX(card, 2, buffer, sizeof(void *));
|
||||||
if (skb) {
|
if (skb) {
|
||||||
dev_kfree_skb_any(skb);
|
if (uses_frags)
|
||||||
|
napi_free_frags(napi);
|
||||||
|
else
|
||||||
|
dev_kfree_skb_any(skb);
|
||||||
QETH_CARD_STAT_INC(card,
|
QETH_CARD_STAT_INC(card,
|
||||||
rx_length_errors);
|
rx_length_errors);
|
||||||
}
|
}
|
||||||
@ -5318,7 +5351,7 @@ walk_packet:
|
|||||||
*__element = element;
|
*__element = element;
|
||||||
*__offset = offset;
|
*__offset = offset;
|
||||||
|
|
||||||
qeth_receive_skb(card, skb, hdr);
|
qeth_receive_skb(card, skb, hdr, uses_frags);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user