Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

IB/ipath: Fix a data corruption

This patch fixes a problem where certain error packets are passed
to the InfiniBand layer for processing even though the packet
actually was received with an error.

Signed-off-by: Ralph Campbell <ralph.campbell@qlogic.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>

authored by

Ralph Campbell and committed by
Roland Dreier
3d37b9e2 1252c517

+36 -40
+36 -40
drivers/infiniband/hw/ipath/ipath_driver.c
··· 859 859 __ipath_layer_rcv_lid(dd, hdr); 860 860 } 861 861 862 + static void ipath_rcv_hdrerr(struct ipath_devdata *dd, 863 + u32 eflags, 864 + u32 l, 865 + u32 etail, 866 + u64 *rc) 867 + { 868 + char emsg[128]; 869 + struct ipath_message_header *hdr; 870 + 871 + get_rhf_errstring(eflags, emsg, sizeof emsg); 872 + hdr = (struct ipath_message_header *)&rc[1]; 873 + ipath_cdbg(PKT, "RHFerrs %x hdrqtail=%x typ=%u " 874 + "tlen=%x opcode=%x egridx=%x: %s\n", 875 + eflags, l, 876 + ipath_hdrget_rcv_type((__le32 *) rc), 877 + ipath_hdrget_length_in_bytes((__le32 *) rc), 878 + be32_to_cpu(hdr->bth[0]) >> 24, 879 + etail, emsg); 880 + 881 + /* Count local link integrity errors. */ 882 + if (eflags & (INFINIPATH_RHF_H_ICRCERR | INFINIPATH_RHF_H_VCRCERR)) { 883 + u8 n = (dd->ipath_ibcctrl >> 884 + INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT) & 885 + INFINIPATH_IBCC_PHYERRTHRESHOLD_MASK; 886 + 887 + if (++dd->ipath_lli_counter > n) { 888 + dd->ipath_lli_counter = 0; 889 + dd->ipath_lli_errors++; 890 + } 891 + } 892 + } 893 + 862 894 /* 863 895 * ipath_kreceive - receive a packet 864 896 * @dd: the infinipath device ··· 907 875 struct ipath_message_header *hdr; 908 876 u32 eflags, i, etype, tlen, pkttot = 0, updegr=0, reloop=0; 909 877 static u64 totcalls; /* stats, may eventually remove */ 910 - char emsg[128]; 911 878 912 879 if (!dd->ipath_hdrqtailptr) { 913 880 ipath_dev_err(dd, ··· 969 938 "%x\n", etype); 970 939 } 971 940 972 - if (eflags & ~(INFINIPATH_RHF_H_TIDERR | 973 - INFINIPATH_RHF_H_IHDRERR)) { 974 - get_rhf_errstring(eflags, emsg, sizeof emsg); 975 - ipath_cdbg(PKT, "RHFerrs %x hdrqtail=%x typ=%u " 976 - "tlen=%x opcode=%x egridx=%x: %s\n", 977 - eflags, l, etype, tlen, bthbytes[0], 978 - ipath_hdrget_index((__le32 *) rc), emsg); 979 - /* Count local link integrity errors. */ 980 - if (eflags & (INFINIPATH_RHF_H_ICRCERR | 981 - INFINIPATH_RHF_H_VCRCERR)) { 982 - u8 n = (dd->ipath_ibcctrl >> 983 - INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT) & 984 - INFINIPATH_IBCC_PHYERRTHRESHOLD_MASK; 985 - 986 - if (++dd->ipath_lli_counter > n) { 987 - dd->ipath_lli_counter = 0; 988 - dd->ipath_lli_errors++; 989 - } 990 - } 991 - } else if (etype == RCVHQ_RCV_TYPE_NON_KD) { 941 + if (unlikely(eflags)) 942 + ipath_rcv_hdrerr(dd, eflags, l, etail, rc); 943 + else if (etype == RCVHQ_RCV_TYPE_NON_KD) { 992 944 int ret = __ipath_verbs_rcv(dd, rc + 1, 993 945 ebuf, tlen); 994 946 if (ret == -ENODEV) ··· 995 981 else if (etype == RCVHQ_RCV_TYPE_EXPECTED) 996 982 ipath_dbg("Bug: Expected TID, opcode %x; ignored\n", 997 983 be32_to_cpu(hdr->bth[0]) & 0xff); 998 - else if (eflags & (INFINIPATH_RHF_H_TIDERR | 999 - INFINIPATH_RHF_H_IHDRERR)) { 1000 - /* 1001 - * This is a type 3 packet, only the LRH is in the 1002 - * rcvhdrq, the rest of the header is in the eager 1003 - * buffer. 1004 - */ 1005 - u8 opcode; 1006 - if (ebuf) { 1007 - bthbytes = (u8 *) ebuf; 1008 - opcode = *bthbytes; 1009 - } 1010 - else 1011 - opcode = 0; 1012 - get_rhf_errstring(eflags, emsg, sizeof emsg); 1013 - ipath_dbg("Err %x (%s), opcode %x, egrbuf %x, " 1014 - "len %x\n", eflags, emsg, opcode, etail, 1015 - tlen); 1016 - } else { 984 + else { 1017 985 /* 1018 986 * error packet, type of error unknown. 1019 987 * Probably type 3, but we don't know, so don't