wc->vendor_err = cqe->vendor_err_syndrome;
 }
 
-static int mlx4_ib_ipoib_csum_ok(__be16 status, __be16 checksum)
+static int mlx4_ib_ipoib_csum_ok(__be16 status, u8 badfcs_enc, __be16 checksum)
 {
-       return ((status & cpu_to_be16(MLX4_CQE_STATUS_IPV4      |
-                                     MLX4_CQE_STATUS_IPV4F     |
-                                     MLX4_CQE_STATUS_IPV4OPT   |
-                                     MLX4_CQE_STATUS_IPV6      |
-                                     MLX4_CQE_STATUS_IPOK)) ==
-               cpu_to_be16(MLX4_CQE_STATUS_IPV4        |
-                           MLX4_CQE_STATUS_IPOK))              &&
-               (status & cpu_to_be16(MLX4_CQE_STATUS_UDP       |
-                                     MLX4_CQE_STATUS_TCP))     &&
-               checksum == cpu_to_be16(0xffff);
+       return ((badfcs_enc & MLX4_CQE_STATUS_L4_CSUM) ||
+               ((status & cpu_to_be16(MLX4_CQE_STATUS_IPOK)) &&
+                (status & cpu_to_be16(MLX4_CQE_STATUS_TCP |
+                                      MLX4_CQE_STATUS_UDP)) &&
+                (checksum == cpu_to_be16(0xffff))));
 }
 
 static void use_tunnel_data(struct mlx4_ib_qp *qp, struct mlx4_ib_cq *cq, struct ib_wc *wc,
                wc->wc_flags      |= g_mlpath_rqpn & 0x80000000 ? IB_WC_GRH : 0;
                wc->pkey_index     = be32_to_cpu(cqe->immed_rss_invalid) & 0x7f;
                wc->wc_flags      |= mlx4_ib_ipoib_csum_ok(cqe->status,
+                                       cqe->badfcs_enc,
                                        cqe->checksum) ? IB_WC_IP_CSUM_OK : 0;
                if (is_eth) {
                        wc->slid = 0;
 
        MLX4_CQE_STATUS_IPOK            = 1 << 12,
 };
 
+/* L4_CSUM is logically part of status, but has to checked against badfcs_enc */
+enum {
+       MLX4_CQE_STATUS_L4_CSUM         = 1 << 2,
+};
+
 enum {
        MLX4_CQE_LLC                     = 1,
        MLX4_CQE_SNAP                    = 1 << 1,