diff options
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/net/qeth_core_main.c | 32 | ||||
-rw-r--r-- | drivers/s390/net/qeth_l2_main.c | 27 | ||||
-rw-r--r-- | drivers/s390/net/qeth_l3_main.c | 26 |
3 files changed, 44 insertions, 41 deletions
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index c52241df980b..467a9173058c 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -5072,6 +5072,7 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card, int headroom = 0; int use_rx_sg = 0; +next_packet: /* qeth_hdr must not cross element boundaries */ while (element->length < offset + sizeof(struct qeth_hdr)) { if (qeth_is_last_sbale(element)) @@ -5088,10 +5089,22 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card, break; case QETH_HEADER_TYPE_LAYER3: skb_len = (*hdr)->hdr.l3.length; + if (!IS_LAYER3(card)) { + QETH_CARD_STAT_INC(card, rx_dropped_notsupp); + skb = NULL; + goto walk_packet; + } + headroom = ETH_HLEN; break; case QETH_HEADER_TYPE_OSN: skb_len = (*hdr)->hdr.osn.pdu_length; + if (!IS_OSN(card)) { + QETH_CARD_STAT_INC(card, rx_dropped_notsupp); + skb = NULL; + goto walk_packet; + } + headroom = sizeof(struct qeth_hdr); break; default: @@ -5100,7 +5113,8 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card, else QETH_CARD_STAT_INC(card, rx_dropped_notsupp); - break; + /* Can't determine packet length, drop the whole buffer. */ + return NULL; } if (!skb_len) @@ -5126,10 +5140,12 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card, if (headroom) skb_reserve(skb, headroom); +walk_packet: data_ptr = element->addr + offset; while (skb_len) { data_len = min(skb_len, (int)(element->length - offset)); - if (data_len) { + + if (skb && data_len) { if (use_rx_sg) qeth_create_skb_frag(element, skb, offset, data_len); @@ -5141,8 +5157,11 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card, if (qeth_is_last_sbale(element)) { QETH_CARD_TEXT(card, 4, "unexeob"); QETH_CARD_HEX(card, 2, buffer, sizeof(void *)); - dev_kfree_skb_any(skb); - QETH_CARD_STAT_INC(card, rx_length_errors); + if (skb) { + dev_kfree_skb_any(skb); + QETH_CARD_STAT_INC(card, + rx_length_errors); + } return NULL; } element++; @@ -5152,6 +5171,11 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card, offset += data_len; } } + + /* This packet was skipped, go get another one: */ + if (!skb) + goto next_packet; + *__element = element; *__offset = offset; if (use_rx_sg) { diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 1e85956f95c6..ae69c981650d 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -315,30 +315,19 @@ static int qeth_l2_process_inbound_buffer(struct qeth_card *card, *done = 1; break; } - switch (hdr->hdr.l2.id) { - case QETH_HEADER_TYPE_LAYER2: + + if (hdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2) { skb->protocol = eth_type_trans(skb, skb->dev); qeth_rx_csum(card, skb, hdr->hdr.l2.flags[1]); len = skb->len; napi_gro_receive(&card->napi, skb); - break; - case QETH_HEADER_TYPE_OSN: - if (IS_OSN(card)) { - skb_push(skb, sizeof(struct qeth_hdr)); - skb_copy_to_linear_data(skb, hdr, - sizeof(struct qeth_hdr)); - len = skb->len; - card->osn_info.data_cb(skb); - break; - } - /* Else, fall through */ - default: - dev_kfree_skb_any(skb); - QETH_CARD_TEXT(card, 3, "inbunkno"); - QETH_DBF_HEX(CTRL, 3, hdr, sizeof(*hdr)); - QETH_CARD_STAT_INC(card, rx_dropped_notsupp); - continue; + } else { + skb_push(skb, sizeof(*hdr)); + skb_copy_to_linear_data(skb, hdr, sizeof(*hdr)); + len = skb->len; + card->osn_info.data_cb(skb); } + work_done++; budget--; QETH_CARD_STAT_INC(card, rx_packets); diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 72c61faae3f9..3b901f3676c1 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -1366,7 +1366,6 @@ static int qeth_l3_process_inbound_buffer(struct qeth_card *card, int work_done = 0; struct sk_buff *skb; struct qeth_hdr *hdr; - unsigned int len; *done = 0; WARN_ON_ONCE(!budget); @@ -1378,26 +1377,17 @@ static int qeth_l3_process_inbound_buffer(struct qeth_card *card, *done = 1; break; } - switch (hdr->hdr.l3.id) { - case QETH_HEADER_TYPE_LAYER3: + + if (hdr->hdr.l3.id == QETH_HEADER_TYPE_LAYER3) qeth_l3_rebuild_skb(card, skb, hdr); - /* fall through */ - case QETH_HEADER_TYPE_LAYER2: /* for HiperSockets sniffer */ - skb->protocol = eth_type_trans(skb, skb->dev); - len = skb->len; - napi_gro_receive(&card->napi, skb); - break; - default: - dev_kfree_skb_any(skb); - QETH_CARD_TEXT(card, 3, "inbunkno"); - QETH_DBF_HEX(CTRL, 3, hdr, sizeof(*hdr)); - QETH_CARD_STAT_INC(card, rx_dropped_notsupp); - continue; - } + + skb->protocol = eth_type_trans(skb, skb->dev); + QETH_CARD_STAT_INC(card, rx_packets); + QETH_CARD_STAT_ADD(card, rx_bytes, skb->len); + + napi_gro_receive(&card->napi, skb); work_done++; budget--; - QETH_CARD_STAT_INC(card, rx_packets); - QETH_CARD_STAT_ADD(card, rx_bytes, len); } return work_done; } |