diff options
author | Ralph Campbell <ralphc@pathscale.com> | 2006-07-17 21:18:36 -0400 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2006-07-24 12:18:05 -0400 |
commit | 3d37b9e209136cf178562bbedc7cd2ecb1da8beb (patch) | |
tree | 5035d87180506932500546d76a9bc62843b2e057 /drivers/infiniband | |
parent | 1252c517cf3df240ae51946a096035765dfd2e6d (diff) |
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>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_driver.c | 76 |
1 files changed, 36 insertions, 40 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c index 823131d58b34..f98518d912b5 100644 --- a/drivers/infiniband/hw/ipath/ipath_driver.c +++ b/drivers/infiniband/hw/ipath/ipath_driver.c | |||
@@ -859,6 +859,38 @@ static void ipath_rcv_layer(struct ipath_devdata *dd, u32 etail, | |||
859 | __ipath_layer_rcv_lid(dd, hdr); | 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 | * ipath_kreceive - receive a packet | 895 | * ipath_kreceive - receive a packet |
864 | * @dd: the infinipath device | 896 | * @dd: the infinipath device |
@@ -875,7 +907,6 @@ void ipath_kreceive(struct ipath_devdata *dd) | |||
875 | struct ipath_message_header *hdr; | 907 | struct ipath_message_header *hdr; |
876 | u32 eflags, i, etype, tlen, pkttot = 0, updegr=0, reloop=0; | 908 | u32 eflags, i, etype, tlen, pkttot = 0, updegr=0, reloop=0; |
877 | static u64 totcalls; /* stats, may eventually remove */ | 909 | static u64 totcalls; /* stats, may eventually remove */ |
878 | char emsg[128]; | ||
879 | 910 | ||
880 | if (!dd->ipath_hdrqtailptr) { | 911 | if (!dd->ipath_hdrqtailptr) { |
881 | ipath_dev_err(dd, | 912 | ipath_dev_err(dd, |
@@ -938,26 +969,9 @@ reloop: | |||
938 | "%x\n", etype); | 969 | "%x\n", etype); |
939 | } | 970 | } |
940 | 971 | ||
941 | if (eflags & ~(INFINIPATH_RHF_H_TIDERR | | 972 | if (unlikely(eflags)) |
942 | INFINIPATH_RHF_H_IHDRERR)) { | 973 | ipath_rcv_hdrerr(dd, eflags, l, etail, rc); |
943 | get_rhf_errstring(eflags, emsg, sizeof emsg); | 974 | else if (etype == RCVHQ_RCV_TYPE_NON_KD) { |
944 | ipath_cdbg(PKT, "RHFerrs %x hdrqtail=%x typ=%u " | ||
945 | "tlen=%x opcode=%x egridx=%x: %s\n", | ||
946 | eflags, l, etype, tlen, bthbytes[0], | ||
947 | ipath_hdrget_index((__le32 *) rc), emsg); | ||
948 | /* Count local link integrity errors. */ | ||
949 | if (eflags & (INFINIPATH_RHF_H_ICRCERR | | ||
950 | INFINIPATH_RHF_H_VCRCERR)) { | ||
951 | u8 n = (dd->ipath_ibcctrl >> | ||
952 | INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT) & | ||
953 | INFINIPATH_IBCC_PHYERRTHRESHOLD_MASK; | ||
954 | |||
955 | if (++dd->ipath_lli_counter > n) { | ||
956 | dd->ipath_lli_counter = 0; | ||
957 | dd->ipath_lli_errors++; | ||
958 | } | ||
959 | } | ||
960 | } else if (etype == RCVHQ_RCV_TYPE_NON_KD) { | ||
961 | int ret = __ipath_verbs_rcv(dd, rc + 1, | 975 | int ret = __ipath_verbs_rcv(dd, rc + 1, |
962 | ebuf, tlen); | 976 | ebuf, tlen); |
963 | if (ret == -ENODEV) | 977 | if (ret == -ENODEV) |
@@ -981,25 +995,7 @@ reloop: | |||
981 | else if (etype == RCVHQ_RCV_TYPE_EXPECTED) | 995 | else if (etype == RCVHQ_RCV_TYPE_EXPECTED) |
982 | ipath_dbg("Bug: Expected TID, opcode %x; ignored\n", | 996 | ipath_dbg("Bug: Expected TID, opcode %x; ignored\n", |
983 | be32_to_cpu(hdr->bth[0]) & 0xff); | 997 | be32_to_cpu(hdr->bth[0]) & 0xff); |
984 | else if (eflags & (INFINIPATH_RHF_H_TIDERR | | 998 | else { |
985 | INFINIPATH_RHF_H_IHDRERR)) { | ||
986 | /* | ||
987 | * This is a type 3 packet, only the LRH is in the | ||
988 | * rcvhdrq, the rest of the header is in the eager | ||
989 | * buffer. | ||
990 | */ | ||
991 | u8 opcode; | ||
992 | if (ebuf) { | ||
993 | bthbytes = (u8 *) ebuf; | ||
994 | opcode = *bthbytes; | ||
995 | } | ||
996 | else | ||
997 | opcode = 0; | ||
998 | get_rhf_errstring(eflags, emsg, sizeof emsg); | ||
999 | ipath_dbg("Err %x (%s), opcode %x, egrbuf %x, " | ||
1000 | "len %x\n", eflags, emsg, opcode, etail, | ||
1001 | tlen); | ||
1002 | } else { | ||
1003 | /* | 999 | /* |
1004 | * error packet, type of error unknown. | 1000 | * error packet, type of error unknown. |
1005 | * Probably type 3, but we don't know, so don't | 1001 | * Probably type 3, but we don't know, so don't |