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 | |
| 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>
| -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 |
