{
        struct qdio_buffer_element *element = *__element;
        struct qdio_buffer *buffer = qethbuffer->buffer;
+       unsigned int headroom, linear_len;
        int offset = *__offset;
        bool use_rx_sg = false;
-       unsigned int headroom;
        struct sk_buff *skb;
        int skb_len = 0;
        void *data_ptr;
        *hdr = element->addr + offset;
 
        offset += sizeof(struct qeth_hdr);
+       skb = NULL;
+
        switch ((*hdr)->hdr.l2.id) {
        case QETH_HEADER_TYPE_LAYER2:
                skb_len = (*hdr)->hdr.l2.pkt_length;
+               linear_len = ETH_HLEN;
                headroom = 0;
                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;
                }
 
+               if ((*hdr)->hdr.l3.flags & QETH_HDR_PASSTHRU) {
+                       linear_len = ETH_HLEN;
+                       headroom = 0;
+                       break;
+               }
+
+               if ((*hdr)->hdr.l3.flags & QETH_HDR_IPV6)
+                       linear_len = sizeof(struct ipv6hdr);
+               else
+                       linear_len = sizeof(struct iphdr);
                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;
                }
 
+               linear_len = skb_len;
                headroom = sizeof(struct qeth_hdr);
                break;
        default:
                return NULL;
        }
 
-       if (!skb_len)
-               return NULL;
+       if (skb_len < linear_len) {
+               QETH_CARD_STAT_INC(card, rx_dropped_runt);
+               goto walk_packet;
+       }
 
        use_rx_sg = (card->options.cq == QETH_CQ_ENABLED) ||
                    ((skb_len >= card->options.rx_sg_cb) &&
                           card->stats.rx_frame_errors +
                           card->stats.rx_fifo_errors;
        stats->rx_dropped = card->stats.rx_dropped_nomem +
-                           card->stats.rx_dropped_notsupp;
+                           card->stats.rx_dropped_notsupp +
+                           card->stats.rx_dropped_runt;
        stats->multicast = card->stats.rx_multicast;
        stats->rx_length_errors = card->stats.rx_length_errors;
        stats->rx_frame_errors = card->stats.rx_frame_errors;
 
        QETH_CARD_STAT("rx0 SG page allocs", rx_sg_alloc_page),
        QETH_CARD_STAT("rx0 dropped, no memory", rx_dropped_nomem),
        QETH_CARD_STAT("rx0 dropped, bad format", rx_dropped_notsupp),
+       QETH_CARD_STAT("rx0 dropped, runt", rx_dropped_runt),
 };
 
 #define TXQ_STATS_LEN  ARRAY_SIZE(txq_stats)